diff --git a/app/app.go b/app/app.go index e13f8bc..2bc3978 100644 --- a/app/app.go +++ b/app/app.go @@ -198,21 +198,11 @@ func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.Co Addr: fmt.Sprintf(":%s", options.NumberPortLocal), } - // Account Server - accountService := service.NewAccount(database) - accountServer := NewAccountHTTP(database, zapLogger) - - accountServer.Register(accountService.GetRoutes()...) - go func() { defer func() { if err := server.Shutdown(ctx); err != nil { errChan <- err } - - if err := accountServer.Stop(); err != nil { - errChan <- err - } }() logger.Emit(InfoSvcStarted{}) @@ -230,25 +220,11 @@ func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.Co }) errChan <- err } - - go func() { - if err := accountServer.StartTLS(options.AccountAddress, tmplCrt, tmplKey); err != nil { - logger.Emit(ErrorCanNotServe{Err: err}) - errChan <- err - } - }() } else { fmt.Println("startserver" + options.NumberPortLocal) if err := server.ListenAndServe(); err != nil { errChan <- err } - - go func() { - if err := accountServer.Start(options.AccountAddress); err != nil { - logger.Emit(ErrorCanNotServe{Err: err}) - errChan <- err - } - }() } }() diff --git a/internal/app/app.go b/internal/app/app.go index 04d0acf..78a99ca 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -84,6 +84,17 @@ func Run(ctx context.Context, cfg initialize.Config, build Build) error { return err } + repositories, err := initialize.NewRepositories(ctx, initialize.DepsRepositories{ + MinioClient: minioClient, + MongoDatabase: mdb, + HLogger: hlogger, + Cfg: cfg, + }) + if err != nil { + logger.Error("Error initializing Repositories", zap.Error(err)) + return err + } + //shutdownGroup.Add(closer.CloserFunc(clientServer.Shutdown)) //shutdownGroup.Add(closer.CloserFunc(adminServer.Shutdown)) //shutdownGroup.Add(closer.CloserFunc(grpcServer.Stop)) diff --git a/service/service_account.go b/service/service_account.go deleted file mode 100644 index e6209b5..0000000 --- a/service/service_account.go +++ /dev/null @@ -1,481 +0,0 @@ -package service - -import ( - "github.com/go-playground/validator/v10" - "github.com/gofiber/fiber/v2" - "heruvym/dal/mongo" - "heruvym/internal/utils/jwt_adapter" - "heruvym/model" - "reflect" -) - -type Account struct { - dal *mongo.DAL -} - -var validate = validator.New() - -// validateStruct - возвращает строку с ошибкой, если структура не прошла валидацию -func validateStruct(s interface{}) []*model.RespErrorValidate { - err := validate.Struct(s) - - var errorsValidate []*model.RespErrorValidate - if err != nil { - for _, err := range err.(validator.ValidationErrors) { - field := err.Field() - - r, _ := reflect.TypeOf(s).Elem().FieldByName(err.Field()) - if queryTag := r.Tag.Get("query"); queryTag != "" { - field = queryTag - } - if jsonTag := r.Tag.Get("json"); jsonTag != "" { - field = jsonTag - } - - errorsValidate = append(errorsValidate, &model.RespErrorValidate{ - Field: field, - Tag: err.Tag(), - Value: err.Param(), - }) - } - } - - return errorsValidate -} - -type Route struct { - Method string - Path string - Name string - Handler fiber.Handler -} - -func NewAccount(dal *mongo.DAL) *Account { - return &Account{ - dal: dal, - } -} - -func (a *Account) GetRoutes() []Route { - return []Route{ - {"GET", "/account/pagination", "AccountPagination", a.AccountPagination}, - {"GET", "/account/:userId", "GetAccount", a.GetAccount}, - {"POST", "/account", "CreateAccount", a.CreateAccount}, - {"DELETE", "/account/:userId", "SetAccountDelete", a.SetAccountDelete}, - {"POST", "/account/restore/:userId", "RestoreAccount", a.RestoreAccount}, - {"PATCH", "/account/role", "SetAccountRole", a.SetAccountRole}, - {"PATCH", "/account/nickname", "SetAccountNickname", a.SetAccountNickname}, - {"PATCH", "/account/avatar", "SetAccountAvatar", a.SetAccountAvatar}, - {"DELETE", "/account/delete/:userId", "DeleteAccount", a.DeleteAccount}, - } -} - -type ReqAccountPagination struct { - Search string `json:"search"` - Offset int64 `json:"offset"` - Limit int64 `json:"limit" validate:"min=1"` -} - -// AccountPagination - GET метод для получения страницы пагинации. -// -// Request: ReqAccountPagination -// -// Responses: -// Success -// Status 200 -// Body: {model.Account, ...} -// -// Bad request - parsing error -// Status: 400 -// Body: error -// -// Bad request - validation error -// Status: 400 -// Body: { {field: string, tag: string, value: string}, ... } -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) AccountPagination(c *fiber.Ctx) error { - var req ReqAccountPagination - - 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) - } - - resp, err := a.dal.GetAccountPage(c.Context(), req.Search, req.Offset, req.Limit) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -// GetAccount - GET метод для получения аккаунта. Если параметр пустой, возьмет userId из jwt -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - validation error -// Status: 400 -// Body: error -// -// Unauthorized -// Status: 401 -// Body: nil -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) GetAccount(c *fiber.Ctx) error { - userId := c.Params("userId") - - if userId == "" { - session, ok := c.Locals("adapter").(*jwt_adapter.JwtAdapter) - if !ok { - return fiber.NewError(fiber.StatusUnauthorized) - } - userId = session.GetUserID() - } - - if userId == "" { - return fiber.NewError(fiber.StatusBadRequest, "userId cannot be empty") - } - - resp, err := a.dal.GetAccountByUserID(c.Context(), userId) - - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -type ReqCreateAccount struct { - Nickname string `json:"nickname"` - Avatar string `json:"avatar"` -} - -// CreateAccount - POST метод для создания аккаунта -// -// Request: ReqCreateAccount -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - parsing error -// Status: 400 -// Body: error -// -// Bad request - validation error -// Status: 400 -// Body: { {field: string, tag: string, value: string}, ... } -// -// Unauthorized -// Status: 401 -// Body: nil -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) CreateAccount(c *fiber.Ctx) error { - var req ReqCreateAccount - - session, ok := c.Locals("adapter").(*jwt_adapter.JwtAdapter) - if !ok { - return fiber.NewError(fiber.StatusUnauthorized) - } - - role, ok := c.Locals("role").(string) - if !ok { - role = "user" - } - - 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) - } - - resp, err := a.dal.InsertAccount(c.Context(), &model.Account{ - UserID: session.GetUserID(), - Nickname: req.Nickname, - Avatar: req.Avatar, - Role: role, - }) - - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -// SetAccountDelete - DELETE метод для пометки аккаунта как удаленный -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - validation error -// Status: 400 -// Body: error -// -// Unauthorized -// Status: 401 -// Body: nil -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) SetAccountDelete(c *fiber.Ctx) error { - userId := c.Params("userId") - - if userId == "" { - session := c.Locals("adapter").(*jwt_adapter.JwtAdapter) - if session == nil { - return fiber.NewError(fiber.StatusUnauthorized) - } - userId = session.GetUserID() - } - - if userId == "" { - return fiber.NewError(fiber.StatusBadRequest, "userId cannot be empty") - } - - resp, err := a.dal.SetAccountDelete(c.Context(), userId, true) - - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -// RestoreAccount - POST метод для пометки аккаунта как не удаленный -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - validation error -// Status: 400 -// Body: error -// -// Unauthorized -// Status: 401 -// Body: nil -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) RestoreAccount(c *fiber.Ctx) error { - userId := c.Params("userId") - - if userId == "" { - session := c.Locals("adapter").(*jwt_adapter.JwtAdapter) - if session == nil { - return fiber.NewError(fiber.StatusUnauthorized) - } - userId = session.GetUserID() - } - - if userId == "" { - return fiber.NewError(fiber.StatusBadRequest, "userId cannot be empty") - } - - resp, err := a.dal.SetAccountDelete(c.Context(), userId, false) - - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -type ReqSetAccountRole struct { - UserID string `json:"userId" validate:"required"` - Role string `json:"role" validate:"required"` -} - -// SetAccountRole - PATCH метод для присвоения роли аккаунту -// -// Request: ReqSetAccountRole -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - parsing error -// Status: 400 -// Body: error -// -// Bad request - validation error -// Status: 400 -// Body: { {field: string, tag: string, value: string}, ... } -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) SetAccountRole(c *fiber.Ctx) error { - var req ReqSetAccountRole - - 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) - } - - resp, err := a.dal.SetAccountRole(c.Context(), req.UserID, req.Role) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -type ReqSetAccountNickname struct { - UserID string `json:"userId" validate:"required"` - Nickname string `json:"nickname" validate:"required"` -} - -// SetAccountNickname - PATCH метод для присвоения никнейма аккаунту -// -// Request: ReqSetAccountNickname -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - parsing error -// Status: 400 -// Body: error -// -// Bad request - validation error -// Status: 400 -// Body: { {field: string, tag: string, value: string}, ... } -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) SetAccountNickname(c *fiber.Ctx) error { - var req ReqSetAccountNickname - - 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) - } - - resp, err := a.dal.SetAccountRole(c.Context(), req.UserID, req.Nickname) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -type ReqSetAccountAvatar struct { - UserID string `json:"userId" validate:"required"` - Avatar string `json:"avatar" validate:"required"` -} - -// SetAccountAvatar - PATCH метод для присвоения никнейма аккаунту -// -// Request: ReqSetAccountAvatar -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - parsing error -// Status: 400 -// Body: error -// -// Bad request - validation error -// Status: 400 -// Body: { {field: string, tag: string, value: string}, ... } -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) SetAccountAvatar(c *fiber.Ctx) error { - var req ReqSetAccountAvatar - - 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) - } - - resp, err := a.dal.SetAccountRole(c.Context(), req.UserID, req.Avatar) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} - -// DeleteAccount - DELETE метод для полного удаления аккаунта -// -// Responses: -// Success -// Status 200 -// Body: model.Account -// -// Bad request - parsing error -// Status: 400 -// Body: error -// -// Internal server error - dal error -// Status: 500 -// Body: error -func (a *Account) DeleteAccount(c *fiber.Ctx) error { - userId := c.Params("userId") - - if userId == "" { - session := c.Locals("adapter").(*jwt_adapter.JwtAdapter) - if session == nil { - return fiber.NewError(fiber.StatusUnauthorized) - } - userId = session.GetUserID() - } - - resp, err := a.dal.DeleteAccount(c.Context(), userId) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, err.Error()) - } - - return c.Status(fiber.StatusOK).JSON(resp) -} diff --git a/service/service_account_test.go b/service/service_account_test.go deleted file mode 100644 index e569270..0000000 --- a/service/service_account_test.go +++ /dev/null @@ -1,341 +0,0 @@ -package service - -import ( - "bytes" - "context" - "encoding/json" - "github.com/gofiber/fiber/v2" - "github.com/stretchr/testify/suite" - "github.com/themakers/hlog" - "go.uber.org/zap" - "heruvym/dal/mongo" - "heruvym/internal/utils/middleware" - "heruvym/model" - "net/http" - "testing" -) - -var mongoUri = "mongodb://localmongo1:30001,localmongo2:30002,localmongo3:30003/?replicaSet=my-rs" - -type AccountTestSuite struct { - svc *Account - dal *mongo.DAL - app *fiber.App - arg *model.Account - suite.Suite -} - -func TestAccountTestSuite(t *testing.T) { - suite.Run(t, new(AccountTestSuite)) -} - -func (s *AccountTestSuite) SetupSuite() { - logger := hlog.New(zap.NewNop()) - dal, err := mongo.New(context.Background(), mongoUri, "support", logger) - - if s.NoError(err) { - s.dal = dal - } - - s.svc = NewAccount(dal) - - app := fiber.New() - - app.Use( - middleware.JwtPlug, - ) - s.app = app - - for _, route := range s.svc.GetRoutes() { - app.Add(route.Method, route.Path, route.Handler).Name(route.Name) - } - - b, err := json.Marshal(ReqCreateAccount{ - Nickname: "SomeNickname", - Avatar: "/some/avatar.jpeg", - }) - - s.NoError(err) - - req, err := http.NewRequest("POST", "/account", bytes.NewBuffer(b)) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := app.Test(req, 10) - s.NoError(err) - - var result model.Account - err = json.NewDecoder(resp.Body).Decode(&result) - s.NoError(err) - - s.arg = &result - - s.Equal(200, resp.StatusCode) -} - -func (s *AccountTestSuite) TearDownSuite() { - req, err := http.NewRequest("DELETE", "/account/delete/"+s.arg.UserID, nil) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - s.NoError(err) - - s.Equal(200, resp.StatusCode) -} - -func (s *AccountTestSuite) TestAccountPagination() { - tests := []struct { - name string - args *ReqAccountPagination - want int - }{ - { - name: "status 200", - args: &ReqAccountPagination{ - Search: "", - Offset: 0, - Limit: 10, - }, - want: fiber.StatusOK, - }, - { - name: "status 400", - args: &ReqAccountPagination{ - Offset: 0, - Limit: 0, - }, - want: fiber.StatusBadRequest, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - - b, err := json.Marshal(tt.args) - s.NoError(err) - - req, err := http.NewRequest("GET", "/account/pagination", bytes.NewBuffer(b)) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -} - -func (s *AccountTestSuite) TestGetAccount() { - tests := []struct { - name string - args string - want int - }{ - { - name: "status 200", - args: s.arg.UserID, - want: 200, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - req, err := http.NewRequest("GET", "/account/"+tt.args, nil) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -} - -func (s *AccountTestSuite) TestSetAccountDelete() { - tests := []struct { - name string - args string - want int - }{ - { - name: "status 200", - args: s.arg.UserID, - want: 200, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - req, err := http.NewRequest("DELETE", "/account/"+tt.args, nil) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -} - -func (s *AccountTestSuite) TestAccountRestore() { - tests := []struct { - name string - args string - want int - }{ - { - name: "status 200", - args: s.arg.UserID, - want: 200, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - req, err := http.NewRequest("POST", "/account/restore/"+tt.args, nil) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -} - -func (s *AccountTestSuite) TestSetAccountRole() { - tests := []struct { - name string - args *ReqSetAccountRole - want int - }{ - { - name: "status 200", - args: &ReqSetAccountRole{ - UserID: s.arg.UserID, - Role: "test", - }, - want: fiber.StatusOK, - }, - { - name: "status 400", - args: &ReqSetAccountRole{}, - want: fiber.StatusBadRequest, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - - b, err := json.Marshal(tt.args) - s.NoError(err) - - req, err := http.NewRequest("PATCH", "/account/role", bytes.NewBuffer(b)) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -} - -func (s *AccountTestSuite) TestSetAccountNickname() { - tests := []struct { - name string - args *ReqSetAccountNickname - want int - }{ - { - name: "status 200", - args: &ReqSetAccountNickname{ - UserID: s.arg.UserID, - Nickname: "test", - }, - want: fiber.StatusOK, - }, - { - name: "status 400", - args: &ReqSetAccountNickname{}, - want: fiber.StatusBadRequest, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - - b, err := json.Marshal(tt.args) - s.NoError(err) - - req, err := http.NewRequest("PATCH", "/account/nickname", bytes.NewBuffer(b)) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -} - -func (s *AccountTestSuite) TestSetAccountAvatar() { - tests := []struct { - name string - args *ReqSetAccountAvatar - want int - }{ - { - name: "status 200", - args: &ReqSetAccountAvatar{ - UserID: s.arg.UserID, - Avatar: "/test.jpeg", - }, - want: fiber.StatusOK, - }, - { - name: "status 400", - args: &ReqSetAccountAvatar{}, - want: fiber.StatusBadRequest, - }, - } - - for _, tt := range tests { - s.Run(tt.name, func() { - - b, err := json.Marshal(tt.args) - s.NoError(err) - - req, err := http.NewRequest("PATCH", "/account/avatar", bytes.NewBuffer(b)) - s.NoError(err) - - req.Header.Set("Content-Type", "application/json") - - resp, err := s.app.Test(req, 10) - - s.NoError(err) - - s.Equal(tt.want, resp.StatusCode) - }) - } -}