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) }