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 (
"context"
"fmt"
"history-api/internal/dtos/request"
"history-api/internal/dtos/response"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/internal/repositories"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
"slices"
@@ -34,15 +36,18 @@ type UserService interface {
type userService struct {
userRepo repositories.UserRepository
roleRepo repositories.RoleRepository
c cache.Cache
}
func NewUserService(
userRepo repositories.UserRepository,
roleRepo repositories.RoleRepository,
c cache.Cache,
) UserService {
return &userService{
userRepo: userRepo,
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")
}
rolesFromDB, err := u.roleRepo.GetByIDs(ctx, dto.Roles)
newListRole, err := u.roleRepo.GetByIDs(ctx, dto.Roles)
if err != nil {
return nil, err
}
@@ -101,8 +106,9 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
hasUserRole := false
hasAdminRole := false
hasBannedRole := false
hasModRole := false
for _, r := range rolesFromDB {
for _, r := range newListRole {
if r.Name == constants.USER.String() {
hasUserRole = true
}
@@ -112,6 +118,9 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
if r.Name == constants.BANNED.String() {
hasBannedRole = true
}
if r.Name == constants.MOD.String() {
hasModRole = true
}
}
if !hasUserRole {
@@ -122,21 +131,39 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
if hasAdminRole {
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 {
if r.Name == string(constants.ADMIN) {
isTargetAdmin = true
if r.Name == constants.ADMIN.String() || r.Name == constants.MOD.String() {
isTargetAdminOrMod = true
break
}
}
if isTargetAdmin && hasBannedRole {
return nil, fiber.NewError(fiber.StatusForbidden, "MOD cannot assign BANNED role to an ADMIN user")
if isTargetAdminOrMod && hasBannedRole {
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)
roleIdList := make([]pgtype.UUID, 0)
for _, role := range rolesFromDB {
for _, role := range newListRole {
roleID, err := convert.StringToUUID(role.ID)
if err != nil {
continue
@@ -158,6 +185,21 @@ func (u *userService) ChangeRoleUser(ctx context.Context, claims *response.JWTCl
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
}