From 8d852521c4d11d4a2038f053169e6af74f739a96 Mon Sep 17 00:00:00 2001 From: Habib Fatkhul Rohman Date: Wed, 3 Dec 2025 13:30:59 +0700 Subject: [PATCH] feat: add ToRoleResponse function and integrate logging in role service --- modules/role/dto/role_dto.go | 56 ++++++++ modules/role/service/role_service.go | 191 +++++++++------------------ providers/core.go | 2 +- 3 files changed, 118 insertions(+), 131 deletions(-) diff --git a/modules/role/dto/role_dto.go b/modules/role/dto/role_dto.go index 62dfe69..ecef52f 100644 --- a/modules/role/dto/role_dto.go +++ b/modules/role/dto/role_dto.go @@ -3,7 +3,9 @@ package dto import ( "errors" + "github.com/Caknoooo/go-gin-clean-starter/database/entities" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" + "github.com/google/uuid" ) const ( @@ -145,3 +147,57 @@ type AssignMenuRequest struct { type RemoveMenuRequest struct { MenuID []string `json:"menu_ids" binding:"required,dive,uuid4"` } + +func ToRoleResponse(role entities.M_Role) RoleResponse { + var permissions []RolePermissionsResponse + for _, p := range role.Permissions { + permissions = append(permissions, RolePermissionsResponse{ + ID: p.ID.String(), + Name: p.Name, + }) + } + + var client pkgdto.IdNameResponse + if role.Client.ID != uuid.Nil { + client = pkgdto.IdNameResponse{ + ID: role.Client.ID.String(), + Name: role.Client.Name, + } + } + + var menus []RoleMenuResponse + for _, m := range role.Menus { + var parent *RoleMenuResponse + if m.Parent != nil { + parent = &RoleMenuResponse{ + ID: m.Parent.ID.String(), + Name: m.Parent.Name, + IconUrl: m.Parent.IconUrl, + Url: m.Parent.Url, + Sequence: m.Parent.Sequence, + Parent: nil, + } + } + menus = append(menus, RoleMenuResponse{ + ID: m.ID.String(), + Name: m.Name, + IconUrl: m.IconUrl, + Url: m.Url, + Sequence: m.Sequence, + Parent: parent, + }) + } + + return RoleResponse{ + ID: role.ID.String(), + Name: role.Name, + Description: role.Description, + IconUrl: role.IconUrl, + Type: role.Type, + HomeUrl: role.HomeUrl, + Level: role.Level, + Client: client, + Permissions: permissions, + Menus: menus, + } +} diff --git a/modules/role/service/role_service.go b/modules/role/service/role_service.go index b73493f..323cbef 100644 --- a/modules/role/service/role_service.go +++ b/modules/role/service/role_service.go @@ -11,7 +11,8 @@ import ( "github.com/Caknoooo/go-gin-clean-starter/modules/role/repository" userDto "github.com/Caknoooo/go-gin-clean-starter/modules/user/dto" userService "github.com/Caknoooo/go-gin-clean-starter/modules/user/service" - pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" + "github.com/Caknoooo/go-gin-clean-starter/pkg/constants" + "github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/google/uuid" "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -40,6 +41,7 @@ type roleService struct { jwtService service.JWTService userService userService.UserService db *gorm.DB + log *logrus.Logger } // GetAll implements RoleService. @@ -51,13 +53,12 @@ func (r *roleService) GetAll(ctx context.Context) ([]dto.RoleResponse, error) { var responses []dto.RoleResponse for _, role := range roles { - responses = append(responses, ToRoleResponse(role)) + responses = append(responses, dto.ToRoleResponse(role)) } return responses, nil } -// AssignMenusToRole implements RoleService. // AssignMenusToRole implements RoleService. func (r *roleService) AssignMenusToRole(ctx context.Context, roleId string, menuIds []string) error { if len(menuIds) == 0 { @@ -257,47 +258,65 @@ func (r *roleService) AssignRolesToUser(ctx context.Context, userId string, role // CreateRole implements RoleService. func (r *roleService) CreateRole(ctx context.Context, req dto.RoleCreateRequest) (dto.RoleResponse, error) { - // _, exists, err := r.roleRepo.CheckRoleName(ctx, r.db, req.Name) - // if err != nil && err != gorm.ErrRecordNotFound { - // return dto.RoleResponse{}, err - // } - // if exists { - // return dto.RoleResponse{}, dto.ErrRoleAlreadyExists - // } - + userID := "" + if ctx != nil { + userID = utils.GetUserID(ctx) + } clientUUID, err := uuid.Parse(req.ClientID) if err != nil { return dto.RoleResponse{}, err } role := entities.M_Role{ - Name: req.Name, - Description: req.Description, - IconUrl: req.IconUrl, - Level: req.Level, - Type: req.Type, - HomeUrl: req.HomeUrl, - ClientID: clientUUID, + Name: req.Name, + Description: req.Description, + IconUrl: req.IconUrl, + Level: req.Level, + Type: req.Type, + HomeUrl: req.HomeUrl, + ClientID: clientUUID, + FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE), } - createdRole, err := r.roleRepo.CreateRole(ctx, r.db, role) if err != nil { return dto.RoleResponse{}, err } - result, err := r.roleRepo.GetRoleByID(ctx, r.db, createdRole.ID.String()) if err != nil { return dto.RoleResponse{}, err } - return ToRoleResponse(result), nil - + r.log.WithFields(logrus.Fields{ + "user_id": userID, + "action": "create", + "entity": "role", + "entity_id": createdRole.ID.String(), + }).Info("Role created") + return dto.ToRoleResponse(result), nil } // DeleteRole implements RoleService. func (r *roleService) DeleteRole(ctx context.Context, id string) error { - if _, err := r.roleRepo.GetRoleByID(ctx, r.db, id); err != nil { + role, err := r.roleRepo.GetRoleByID(ctx, r.db, id) + if err != nil { return dto.ErrRoleNotFound } - return r.roleRepo.DeleteRole(ctx, r.db, id) + role.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE) + if _, err := r.roleRepo.UpdateRole(ctx, r.db, role); err != nil { + return err + } + if err := r.roleRepo.DeleteRole(ctx, r.db, id); err != nil { + return err + } + userID := "" + if ctx != nil { + userID = utils.GetUserID(ctx) + } + r.log.WithFields(logrus.Fields{ + "user_id": userID, + "action": "delete", + "entity": "role", + "entity_id": id, + }).Info("Role deleted") + return nil } // GetRoleByID implements RoleService. @@ -307,7 +326,7 @@ func (r *roleService) GetRoleByID(ctx context.Context, id string) (dto.RoleRespo return dto.RoleResponse{}, err } - return ToRoleResponse(role), nil + return dto.ToRoleResponse(role), nil } // GetRoles implements RoleService. @@ -316,44 +335,6 @@ func (r *roleService) GetRoles(ctx context.Context, filter query.RoleFilter) ([] } // GetRolesByUserID implements RoleService. -// func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dto.RoleResponse, error) { -// if _, err := r.userService.GetUserById(ctx, userId); err != nil { -// return nil, userDto.ErrUserNotFound -// } - -// roles, err := r.roleRepo.GetRolesByUserID(ctx, r.db, userId) -// if err != nil { -// logrus.Error("Error fetching roles for user ", userId, ": ", err) -// return nil, err -// } - -// logrus.Info("Fetched ", len(roles), " roles for user ", userId) - -// var responses []dto.RoleResponse -// for _, role := range roles { -// var permissions []dto.RolePermissionsResponse -// for _, p := range role.Permissions { -// permissions = append(permissions, dto.RolePermissionsResponse{ -// ID: p.ID.String(), -// Name: p.Name, -// }) -// } - -// responses = append(responses, dto.RoleResponse{ -// ID: role.ID.String(), -// Name: role.Name, -// Description: role.Description, -// IconUrl: role.IconUrl, -// Type: role.Type, -// HomeUrl: role.HomeUrl, -// ClientID: role.ClientID.String(), -// Permissions: permissions, -// }) -// } - -// return responses, nil -// } - func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dto.RoleResponse, error) { if _, err := r.userService.GetUserById(ctx, userId); err != nil { return nil, userDto.ErrUserNotFound @@ -366,7 +347,7 @@ func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dt var responses []dto.RoleResponse for _, role := range roles { - responses = append(responses, ToRoleResponse(role)) + responses = append(responses, dto.ToRoleResponse(role)) } return responses, nil @@ -470,16 +451,8 @@ func (r *roleService) UpdateRole(ctx context.Context, id string, req dto.RoleUpd if err != nil { return dto.RoleResponse{}, dto.ErrRoleNotFound } - + before := existingRole if req.Name != "" { - // _, exists, err := r.roleRepo.CheckRoleName(ctx, r.db, req.Name) - - // if err != nil { - // return dto.RoleResponse{}, err - // } - // if exists { - // return dto.RoleResponse{}, dto.ErrRoleAlreadyExists - // } existingRole.Name = req.Name } if req.Description != "" { @@ -497,72 +470,28 @@ func (r *roleService) UpdateRole(ctx context.Context, id string, req dto.RoleUpd if req.Level != 0 { existingRole.Level = req.Level } - + existingRole.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE) updatedRole, err := r.roleRepo.UpdateRole(ctx, r.db, existingRole) if err != nil { return dto.RoleResponse{}, err } - result, err := r.roleRepo.GetRoleByID(ctx, r.db, updatedRole.ID.String()) if err != nil { return dto.RoleResponse{}, err } - - return ToRoleResponse(result), nil -} - -func ToRoleResponse(role entities.M_Role) dto.RoleResponse { - var permissions []dto.RolePermissionsResponse - for _, p := range role.Permissions { - permissions = append(permissions, dto.RolePermissionsResponse{ - ID: p.ID.String(), - Name: p.Name, - }) - } - - var client pkgdto.IdNameResponse - if role.Client.ID != uuid.Nil { - client = pkgdto.IdNameResponse{ - ID: role.Client.ID.String(), - Name: role.Client.Name, - } - } - - var menus []dto.RoleMenuResponse - for _, m := range role.Menus { - var parent *dto.RoleMenuResponse - if m.Parent != nil { - parent = &dto.RoleMenuResponse{ - ID: m.Parent.ID.String(), - Name: m.Parent.Name, - IconUrl: m.Parent.IconUrl, - Url: m.Parent.Url, - Sequence: m.Parent.Sequence, - Parent: nil, // atau rekursif jika ingin nested lebih dalam - } - } - menus = append(menus, dto.RoleMenuResponse{ - ID: m.ID.String(), - Name: m.Name, - IconUrl: m.IconUrl, - Url: m.Url, - Sequence: m.Sequence, - Parent: parent, - }) - } - - return dto.RoleResponse{ - ID: role.ID.String(), - Name: role.Name, - Description: role.Description, - IconUrl: role.IconUrl, - Type: role.Type, - HomeUrl: role.HomeUrl, - Level: role.Level, - Client: client, - Permissions: permissions, - Menus: menus, + changes := utils.GetChangedFields(before, result) + userID := "" + if ctx != nil { + userID = utils.GetUserID(ctx) } + r.log.WithFields(logrus.Fields{ + "user_id": userID, + "action": "update", + "entity": "role", + "entity_id": id, + "changes": changes, + }).Info("Role updated") + return dto.ToRoleResponse(result), nil } func NewRoleService( @@ -571,6 +500,7 @@ func NewRoleService( jwtService service.JWTService, userService userService.UserService, db *gorm.DB, + log *logrus.Logger, ) RoleService { return &roleService{ roleRepo: roleRepo, @@ -578,5 +508,6 @@ func NewRoleService( jwtService: jwtService, userService: userService, db: db, + log: log, } } diff --git a/providers/core.go b/providers/core.go index 233cb87..832bd51 100644 --- a/providers/core.go +++ b/providers/core.go @@ -176,7 +176,7 @@ func RegisterDependencies(injector *do.Injector) { sequenceServ := sequenceService.NewSequenceService(sequenceRepository, db) userServ := userService.NewUserService(userRepository, roleRepository, warehouseRepository, clientRepository, refreshTokenRepository, jwtService, db) productService := productService.NewProductService(productRepository, db, inventoryTransactionRepository, inventoryStorageRepository, categoryRepository, sequenceServ) - roleServ := roleService.NewRoleService(roleRepository, refreshTokenRepository, jwtService, userServ, db) + roleServ := roleService.NewRoleService(roleRepository, refreshTokenRepository, jwtService, userServ, db, log) menuSvc := menuService.NewMenuService(menuRepository, jwtService, db) maintenanceGroupServ := maintGroupService.NewMaintenanceGroupService(maintenanceGroupRepository, maintenanceGroupRoleRepository, maintenanceGroupRoleUserRepository, db) clientServ := clientService.NewClientService(clientRepository, db)