UPDATE: Change role logic
Some checks failed
Build and Release / release (push) Failing after 53s

This commit is contained in:
2026-04-08 16:44:04 +07:00
parent 4706d4ea81
commit d4e17a8905

View File

@@ -2,11 +2,13 @@ package services
import ( import (
"context" "context"
"fmt"
"history-api/internal/dtos/request" "history-api/internal/dtos/request"
"history-api/internal/dtos/response" "history-api/internal/dtos/response"
"history-api/internal/gen/sqlc" "history-api/internal/gen/sqlc"
"history-api/internal/models" "history-api/internal/models"
"history-api/internal/repositories" "history-api/internal/repositories"
"history-api/pkg/cache"
"history-api/pkg/constants" "history-api/pkg/constants"
"history-api/pkg/convert" "history-api/pkg/convert"
"slices" "slices"
@@ -34,15 +36,18 @@ type UserService interface {
type userService struct { type userService struct {
userRepo repositories.UserRepository userRepo repositories.UserRepository
roleRepo repositories.RoleRepository roleRepo repositories.RoleRepository
c cache.Cache
} }
func NewUserService( func NewUserService(
userRepo repositories.UserRepository, userRepo repositories.UserRepository,
roleRepo repositories.RoleRepository, roleRepo repositories.RoleRepository,
c cache.Cache,
) UserService { ) UserService {
return &userService{ return &userService{
userRepo: userRepo, userRepo: userRepo,
roleRepo: roleRepo, roleRepo: roleRepo,
c: c,
} }
} }
@@ -93,7 +98,7 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
return nil, fiber.NewError(fiber.StatusNotFound, "User not found") return nil, fiber.NewError(fiber.StatusNotFound, "User not found")
} }
rolesFromDB, err := u.roleRepo.GetByIDs(ctx, dto.Roles) newListRole, err := u.roleRepo.GetByIDs(ctx, dto.Roles)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -101,8 +106,9 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
hasUserRole := false hasUserRole := false
hasAdminRole := false hasAdminRole := false
hasBannedRole := false hasBannedRole := false
hasModRole := false
for _, r := range rolesFromDB { for _, r := range newListRole {
if r.Name == constants.USER.String() { if r.Name == constants.USER.String() {
hasUserRole = true hasUserRole = true
} }
@@ -112,6 +118,9 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
if r.Name == constants.BANNED.String() { if r.Name == constants.BANNED.String() {
hasBannedRole = true hasBannedRole = true
} }
if r.Name == constants.MOD.String() {
hasModRole = true
}
} }
if !hasUserRole { if !hasUserRole {
@@ -122,21 +131,39 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
if hasAdminRole { if hasAdminRole {
return nil, fiber.NewError(fiber.StatusForbidden, "MOD cannot assign ADMIN role to any user") return nil, fiber.NewError(fiber.StatusForbidden, "MOD cannot assign ADMIN role to any user")
} }
isTargetAdmin := false
if dto.UserID == claims.UId && !hasModRole {
return nil, fiber.NewError(fiber.StatusForbidden, "You can't remove MOD role of yourself")
}
if dto.UserID == claims.UId && hasBannedRole {
return nil, fiber.NewError(fiber.StatusForbidden, "You can't assign BANNED role to yourself")
}
isTargetAdminOrMod := false
for _, r := range user.Roles { for _, r := range user.Roles {
if r.Name == string(constants.ADMIN) { if r.Name == constants.ADMIN.String() || r.Name == constants.MOD.String() {
isTargetAdmin = true isTargetAdminOrMod = true
break break
} }
} }
if isTargetAdmin && hasBannedRole { if isTargetAdminOrMod && hasBannedRole {
return nil, fiber.NewError(fiber.StatusForbidden, "MOD cannot assign BANNED role to an ADMIN user") return nil, fiber.NewError(fiber.StatusForbidden, "MOD cannot assign BANNED role to an ADMIN or MOD user")
}
}
if slices.Contains(claims.Roles, constants.ADMIN) {
if dto.UserID == claims.UId && hasBannedRole {
return nil, fiber.NewError(fiber.StatusForbidden, "You can't assign BANNED role to yourself")
}
if dto.UserID == claims.UId && !hasAdminRole {
return nil, fiber.NewError(fiber.StatusForbidden, "You can't remove ADMIN role of yourself")
} }
} }
user.Roles = make([]*models.RoleSimple, 0) user.Roles = make([]*models.RoleSimple, 0)
roleIdList := make([]pgtype.UUID, 0) roleIdList := make([]pgtype.UUID, 0)
for _, role := range rolesFromDB { for _, role := range newListRole {
roleID, err := convert.StringToUUID(role.ID) roleID, err := convert.StringToUUID(role.ID)
if err != nil { if err != nil {
continue continue
@@ -158,6 +185,21 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
return nil, fiber.NewError(fiber.StatusInternalServerError, err.Error()) return nil, fiber.NewError(fiber.StatusInternalServerError, err.Error())
} }
err = u.userRepo.UpdateTokenVersion(ctx, sqlc.UpdateTokenVersionParams{
ID: userId,
TokenVersion: user.TokenVersion + 1,
})
if err != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
user.TokenVersion += 1
mapCache := map[string]any{
fmt.Sprintf("user:email:%s", user.Email): user,
fmt.Sprintf("user:id:%s", user.ID): user,
}
_ = u.c.MSet(ctx, mapCache, constants.NormalCacheDuration)
return user.ToResponse(), nil return user.ToResponse(), nil
} }