some rework initialization api and separate controllers
This commit is contained in:
parent
83b20bd5b8
commit
fb51a1acf6
@ -75,12 +75,14 @@ func Run(cfg *config.Config) {
|
|||||||
CustomerServiceHost: cfg.CustomerRPCHost,
|
CustomerServiceHost: cfg.CustomerRPCHost,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
httpSrv := server.NewHTTP(cfg, logger).Register(cons.List()...)
|
httpSrv := server.NewHTTP(server.ServerConfig{
|
||||||
|
Logger: logger,
|
||||||
|
Controllers: []server.Controller{cons.VerificationUser, cons.VerificationAdmin},
|
||||||
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := httpSrv.Start()
|
if err := httpSrv.Start(cfg.HttpAddress); err != nil {
|
||||||
if err != nil {
|
logger.Fatal("Server startup error", zap.Error(err))
|
||||||
logger.Fatal("CanNotServe", zap.Error(err))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func gracefulShutdown(ctx context.Context, logger *zap.Logger, httpSrv *server.HTTP, mongoDB *mongo.Database) {
|
func gracefulShutdown(ctx context.Context, logger *zap.Logger, httpSrv *server.Server, mongoDB *mongo.Database) {
|
||||||
interrupt := make(chan os.Signal, 1)
|
interrupt := make(chan os.Signal, 1)
|
||||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
|
||||||
killSignal := <-interrupt
|
killSignal := <-interrupt
|
||||||
@ -21,7 +21,7 @@ func gracefulShutdown(ctx context.Context, logger *zap.Logger, httpSrv *server.H
|
|||||||
logger.Info("AppTerminated")
|
logger.Info("AppTerminated")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := httpSrv.Stop(); err != nil {
|
if err := httpSrv.Shutdown(ctx); err != nil {
|
||||||
logger.Error("HttpServerShutdown", zap.Error(err))
|
logger.Error("HttpServerShutdown", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
internal/controllers/admin/route.go
Normal file
12
internal/controllers/admin/route.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
func (r *VerifyAdminController) Register(router fiber.Router) {
|
||||||
|
router.Get("/verification/:userID", r.GetVerification)
|
||||||
|
router.Patch("/verification", r.SetVerificationStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *VerifyAdminController) Name() string {
|
||||||
|
return ""
|
||||||
|
}
|
78
internal/controllers/admin/verification_admin.go
Normal file
78
internal/controllers/admin/verification_admin.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
||||||
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/repository"
|
||||||
|
"penahub.gitlab.yandexcloud.net/backend/verification/pkg/validate_controllers"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/customer_clients"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VerifyAdminControllerDeps struct {
|
||||||
|
Repository *repository.VerificationRepository
|
||||||
|
Customer *customer_clients.CustomersClient
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyAdminController struct {
|
||||||
|
repository *repository.VerificationRepository
|
||||||
|
customer *customer_clients.CustomersClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVerificationAdminController(deps VerifyAdminControllerDeps) *VerifyAdminController {
|
||||||
|
return &VerifyAdminController{
|
||||||
|
repository: deps.Repository,
|
||||||
|
customer: deps.Customer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *VerifyAdminController) SetVerificationStatus(c *fiber.Ctx) error {
|
||||||
|
var req models.ReqSetVerification
|
||||||
|
|
||||||
|
err := c.BodyParser(&req)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
errValidate := validate_controllers.ValidateStruct(&req)
|
||||||
|
if errValidate != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(errValidate)
|
||||||
|
}
|
||||||
|
|
||||||
|
updated, err := r.repository.Update(c.Context(), &models.Verification{
|
||||||
|
ID: req.ID,
|
||||||
|
Accepted: req.Accepted,
|
||||||
|
Status: req.Status,
|
||||||
|
Comment: req.Comment,
|
||||||
|
TaxNumber: req.TaxNumber,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Accepted {
|
||||||
|
_, err := r.customer.SetVerifyAccount(c.Context(), updated.UserID, req.Status)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(fiber.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *VerifyAdminController) GetVerification(c *fiber.Ctx) error {
|
||||||
|
userID := c.Params("userID")
|
||||||
|
if userID == "" {
|
||||||
|
return fiber.NewError(fiber.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := r.repository.GetByUserID(c.Context(), userID)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp == nil {
|
||||||
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).JSON(resp)
|
||||||
|
}
|
13
internal/controllers/user/route.go
Normal file
13
internal/controllers/user/route.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
func (r *VerifyUserController) Register(router fiber.Router) {
|
||||||
|
router.Get("/verification/create", r.GetVerification)
|
||||||
|
router.Post("/verification", r.CreateVerification)
|
||||||
|
router.Put("/verification", r.SetVerificationFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *VerifyUserController) Name() string {
|
||||||
|
return ""
|
||||||
|
}
|
@ -1,44 +1,37 @@
|
|||||||
package controllers
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"mime/multipart"
|
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/customer_clients"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
|
"mime/multipart"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/client"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/client"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/repository"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/repository"
|
||||||
|
"penahub.gitlab.yandexcloud.net/backend/verification/pkg/validate_controllers"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VerificationController struct {
|
type VerifyUserControllerDeps struct {
|
||||||
|
Repository *repository.VerificationRepository
|
||||||
|
Telegram *client.Telegram
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyUserController struct {
|
||||||
repository *repository.VerificationRepository
|
repository *repository.VerificationRepository
|
||||||
telegram *client.Telegram
|
telegram *client.Telegram
|
||||||
customer *customer_clients.CustomersClient
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVerificationController(rep *repository.VerificationRepository, telegram *client.Telegram, customer *customer_clients.CustomersClient) *VerificationController {
|
func NewVerificationUserController(deps VerifyUserControllerDeps) *VerifyUserController {
|
||||||
return &VerificationController{repository: rep, telegram: telegram, customer: customer}
|
return &VerifyUserController{
|
||||||
}
|
repository: deps.Repository,
|
||||||
|
telegram: deps.Telegram,
|
||||||
func (r *VerificationController) GetRoutes() []Route {
|
|
||||||
return []Route{
|
|
||||||
{"GET", "/verification/:userID", "GetVerification", r.GetVerification},
|
|
||||||
{"POST", "/verification", "CreateVerification", r.CreateVerification},
|
|
||||||
{"PATCH", "/verification", "SetVerificationStatus", r.SetVerificationStatus},
|
|
||||||
{"PATCH", "/verification/file", "SetVerificationFile", r.SetVerificationFile},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VerificationController) GetVerification(c *fiber.Ctx) error {
|
func (r *VerifyUserController) GetVerification(c *fiber.Ctx) error {
|
||||||
userID := c.Params("userID")
|
userID := c.Locals("userID").(string)
|
||||||
|
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
userID = c.Locals("userID").(string)
|
return fiber.NewError(fiber.StatusUnauthorized)
|
||||||
if userID == "" {
|
|
||||||
return fiber.NewError(fiber.StatusUnauthorized)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := r.repository.GetByUserID(c.Context(), userID)
|
resp, err := r.repository.GetByUserID(c.Context(), userID)
|
||||||
@ -53,7 +46,7 @@ func (r *VerificationController) GetVerification(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusOK).JSON(resp)
|
return c.Status(fiber.StatusOK).JSON(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VerificationController) CreateVerification(c *fiber.Ctx) error {
|
func (r *VerifyUserController) CreateVerification(c *fiber.Ctx) error {
|
||||||
var req models.ReqCreateVerification
|
var req models.ReqCreateVerification
|
||||||
|
|
||||||
userID := c.Params("userID")
|
userID := c.Params("userID")
|
||||||
@ -71,7 +64,7 @@ func (r *VerificationController) CreateVerification(c *fiber.Ctx) error {
|
|||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
errValidate := validateStruct(&req)
|
errValidate := validate_controllers.ValidateStruct(&req)
|
||||||
if errValidate != nil {
|
if errValidate != nil {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(errValidate)
|
return c.Status(fiber.StatusBadRequest).JSON(errValidate)
|
||||||
}
|
}
|
||||||
@ -126,41 +119,7 @@ func (r *VerificationController) CreateVerification(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusOK).JSON(result)
|
return c.Status(fiber.StatusOK).JSON(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VerificationController) SetVerificationStatus(c *fiber.Ctx) error {
|
func (r *VerifyUserController) SetVerificationFile(c *fiber.Ctx) error {
|
||||||
var req models.ReqSetVerification
|
|
||||||
|
|
||||||
err := c.BodyParser(&req)
|
|
||||||
if err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
errValidate := validateStruct(&req)
|
|
||||||
if errValidate != nil {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(errValidate)
|
|
||||||
}
|
|
||||||
|
|
||||||
updated, err := r.repository.Update(c.Context(), &models.Verification{
|
|
||||||
ID: req.ID,
|
|
||||||
Accepted: req.Accepted,
|
|
||||||
Status: req.Status,
|
|
||||||
Comment: req.Comment,
|
|
||||||
TaxNumber: req.TaxNumber,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Accepted {
|
|
||||||
_, err := r.customer.SetVerifyAccount(c.Context(), updated.UserID, req.Status)
|
|
||||||
if err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *VerificationController) SetVerificationFile(c *fiber.Ctx) error {
|
|
||||||
userID := c.Params("userID")
|
userID := c.Params("userID")
|
||||||
baseURL := c.BaseURL()
|
baseURL := c.BaseURL()
|
||||||
|
|
@ -1,11 +1,11 @@
|
|||||||
package controllers
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VerificationTestSuite struct {
|
type VerificationTestSuite struct {
|
||||||
controller *VerificationController
|
controller *VerifyUserController
|
||||||
suite.Suite
|
suite.Suite
|
||||||
}
|
}
|
||||||
|
|
@ -2,34 +2,25 @@ package initialize
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/client"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/client"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/controllers"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/controllers/admin"
|
||||||
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/controllers/user"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/customer_clients"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/customer_clients"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Controller interface {
|
|
||||||
GetRoutes() []controllers.Route
|
|
||||||
}
|
|
||||||
|
|
||||||
type Controllers struct {
|
type Controllers struct {
|
||||||
Verification *controllers.VerificationController
|
VerificationAdmin *admin.VerifyAdminController
|
||||||
}
|
VerificationUser *user.VerifyUserController
|
||||||
|
|
||||||
func (c *Controllers) List() []Controller {
|
|
||||||
fields := reflect.ValueOf(c).Elem()
|
|
||||||
|
|
||||||
var controllersArr []Controller
|
|
||||||
for i := 0; i < fields.NumField(); i++ {
|
|
||||||
vf := fields.Field(i)
|
|
||||||
|
|
||||||
if vf.Type().Implements(reflect.TypeOf((*Controller)(nil)).Elem()) {
|
|
||||||
controllersArr = append(controllersArr, vf.Interface().(Controller))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return controllersArr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewControllers(reps *Repositories, telegram *client.Telegram, customer *customer_clients.CustomersClient) *Controllers {
|
func NewControllers(reps *Repositories, telegram *client.Telegram, customer *customer_clients.CustomersClient) *Controllers {
|
||||||
return &Controllers{Verification: controllers.NewVerificationController(reps.Verification, telegram, customer)}
|
return &Controllers{
|
||||||
|
VerificationAdmin: admin.NewVerificationAdminController(admin.VerifyAdminControllerDeps{
|
||||||
|
Repository: reps.Verification,
|
||||||
|
Customer: customer,
|
||||||
|
}),
|
||||||
|
VerificationUser: user.NewVerificationUserController(user.VerifyUserControllerDeps{
|
||||||
|
Repository: reps.Verification,
|
||||||
|
Telegram: telegram,
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,26 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/gofiber/contrib/fiberzap"
|
"github.com/gofiber/contrib/fiberzap"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/config"
|
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/initialize"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTTP struct {
|
type ServerConfig struct {
|
||||||
fiber *fiber.App
|
Logger *zap.Logger
|
||||||
cfg *config.Config
|
Controllers []Controller
|
||||||
logger *zap.Logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTP(cfg *config.Config, logger *zap.Logger) *HTTP {
|
type Server struct {
|
||||||
|
Logger *zap.Logger
|
||||||
|
Controllers []Controller
|
||||||
|
app *fiber.App
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHTTP(cfg ServerConfig) *Server {
|
||||||
srv := fiber.New(fiber.Config{
|
srv := fiber.New(fiber.Config{
|
||||||
AppName: "Verification",
|
AppName: "Verification",
|
||||||
ErrorHandler: fiber.DefaultErrorHandler,
|
ErrorHandler: fiber.DefaultErrorHandler,
|
||||||
@ -24,30 +29,51 @@ func NewHTTP(cfg *config.Config, logger *zap.Logger) *HTTP {
|
|||||||
|
|
||||||
srv.Use(
|
srv.Use(
|
||||||
recover.New(recover.Config{EnableStackTrace: true}),
|
recover.New(recover.Config{EnableStackTrace: true}),
|
||||||
fiberzap.New(fiberzap.Config{Logger: logger}),
|
fiberzap.New(fiberzap.Config{Logger: cfg.Logger}),
|
||||||
LocalJwt(),
|
LocalJwt(),
|
||||||
Jwt(),
|
Jwt(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return &HTTP{fiber: srv, cfg: cfg, logger: logger}
|
s := &Server{
|
||||||
|
Logger: cfg.Logger,
|
||||||
|
Controllers: cfg.Controllers,
|
||||||
|
app: srv,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.registerRoutes()
|
||||||
|
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register - автоматически регистрирует все контроллеры.
|
func (s *Server) Start(addr string) error {
|
||||||
func (srv *HTTP) Register(controllers ...initialize.Controller) *HTTP {
|
if err := s.app.Listen(addr); err != nil {
|
||||||
for _, controller := range controllers {
|
s.Logger.Error("Failed to start server", zap.Error(err))
|
||||||
for _, route := range controller.GetRoutes() {
|
return err
|
||||||
srv.fiber.Add(route.Method, route.Path, route.Handler).Name(route.Name)
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Shutdown(ctx context.Context) error {
|
||||||
|
return s.app.Shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) registerRoutes() {
|
||||||
|
for _, c := range s.Controllers {
|
||||||
|
router := s.app.Group(c.Name())
|
||||||
|
c.Register(router)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Controller interface {
|
||||||
|
Register(router fiber.Router)
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) ListRoutes() {
|
||||||
|
fmt.Println("Registered routes:")
|
||||||
|
for _, stack := range s.app.Stack() {
|
||||||
|
for _, route := range stack {
|
||||||
|
fmt.Printf("%s %s\n", route.Method, route.Path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return srv
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start - запускает http сервер.
|
|
||||||
func (srv *HTTP) Start() error {
|
|
||||||
return srv.fiber.Listen(srv.cfg.HttpAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop - останавливает http сервер.
|
|
||||||
func (srv *HTTP) Stop() error {
|
|
||||||
return srv.fiber.Shutdown()
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package controllers
|
package validate_controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -18,7 +18,7 @@ type Route struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateStruct - возвращает строку с ошибкой, если структура не прошла валидацию.
|
// validateStruct - возвращает строку с ошибкой, если структура не прошла валидацию.
|
||||||
func validateStruct(s any) []*models.RespErrorValidate {
|
func ValidateStruct(s any) []*models.RespErrorValidate {
|
||||||
err := validate.Struct(s)
|
err := validate.Struct(s)
|
||||||
|
|
||||||
var errorsValidate []*models.RespErrorValidate
|
var errorsValidate []*models.RespErrorValidate
|
Loading…
Reference in New Issue
Block a user