heruvym/service/service_account.go
2024-09-25 17:22:57 +03:00

482 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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