meti-backend/internal/service/rbac_service.go
2025-08-09 15:28:25 +07:00

129 lines
3.9 KiB
Go

package service
import (
"context"
"eslogad-be/internal/contract"
"eslogad-be/internal/entities"
"eslogad-be/internal/repository"
"eslogad-be/internal/transformer"
"github.com/google/uuid"
)
type RBACServiceImpl struct {
repo *repository.RBACRepository
}
func NewRBACService(repo *repository.RBACRepository) *RBACServiceImpl {
return &RBACServiceImpl{repo: repo}
}
// Permissions
func (s *RBACServiceImpl) CreatePermission(ctx context.Context, req *contract.CreatePermissionRequest) (*contract.PermissionResponse, error) {
p := &entities.Permission{Code: req.Code}
if req.Description != nil {
p.Description = *req.Description
}
if err := s.repo.CreatePermission(ctx, p); err != nil {
return nil, err
}
return &contract.PermissionResponse{ID: p.ID, Code: p.Code, Description: &p.Description, CreatedAt: p.CreatedAt, UpdatedAt: p.UpdatedAt}, nil
}
func (s *RBACServiceImpl) UpdatePermission(ctx context.Context, id uuid.UUID, req *contract.UpdatePermissionRequest) (*contract.PermissionResponse, error) {
p := &entities.Permission{ID: id}
if req.Code != nil {
p.Code = *req.Code
}
if req.Description != nil {
p.Description = *req.Description
}
if err := s.repo.UpdatePermission(ctx, p); err != nil {
return nil, err
}
// fetch full row
perms, err := s.repo.ListPermissions(ctx)
if err != nil {
return nil, err
}
for _, x := range perms {
if x.ID == id {
return &contract.PermissionResponse{ID: x.ID, Code: x.Code, Description: &x.Description, CreatedAt: x.CreatedAt, UpdatedAt: x.UpdatedAt}, nil
}
}
return nil, nil
}
func (s *RBACServiceImpl) DeletePermission(ctx context.Context, id uuid.UUID) error {
return s.repo.DeletePermission(ctx, id)
}
func (s *RBACServiceImpl) ListPermissions(ctx context.Context) (*contract.ListPermissionsResponse, error) {
perms, err := s.repo.ListPermissions(ctx)
if err != nil {
return nil, err
}
return &contract.ListPermissionsResponse{Permissions: transformer.PermissionsToContract(perms)}, nil
}
// Roles
func (s *RBACServiceImpl) CreateRole(ctx context.Context, req *contract.CreateRoleRequest) (*contract.RoleWithPermissionsResponse, error) {
role := &entities.Role{Name: req.Name, Code: req.Code}
if req.Description != nil {
role.Description = *req.Description
}
if err := s.repo.CreateRole(ctx, role); err != nil {
return nil, err
}
if len(req.PermissionCodes) > 0 {
_ = s.repo.SetRolePermissionsByCodes(ctx, role.ID, req.PermissionCodes)
}
perms, _ := s.repo.GetPermissionsByRoleID(ctx, role.ID)
resp := transformer.RoleWithPermissionsToContract(*role, perms)
return &resp, nil
}
func (s *RBACServiceImpl) UpdateRole(ctx context.Context, id uuid.UUID, req *contract.UpdateRoleRequest) (*contract.RoleWithPermissionsResponse, error) {
role := &entities.Role{ID: id}
if req.Name != nil {
role.Name = *req.Name
}
if req.Code != nil {
role.Code = *req.Code
}
if req.Description != nil {
role.Description = *req.Description
}
if err := s.repo.UpdateRole(ctx, role); err != nil {
return nil, err
}
if req.PermissionCodes != nil {
_ = s.repo.SetRolePermissionsByCodes(ctx, id, *req.PermissionCodes)
}
perms, _ := s.repo.GetPermissionsByRoleID(ctx, id)
// fetch updated role
roles, err := s.repo.ListRoles(ctx)
if err != nil {
return nil, err
}
for _, r := range roles {
if r.ID == id {
resp := transformer.RoleWithPermissionsToContract(r, perms)
return &resp, nil
}
}
return nil, nil
}
func (s *RBACServiceImpl) DeleteRole(ctx context.Context, id uuid.UUID) error {
return s.repo.DeleteRole(ctx, id)
}
func (s *RBACServiceImpl) ListRoles(ctx context.Context) (*contract.ListRolesResponse, error) {
roles, err := s.repo.ListRoles(ctx)
if err != nil {
return nil, err
}
out := make([]contract.RoleWithPermissionsResponse, 0, len(roles))
for _, r := range roles {
perms, _ := s.repo.GetPermissionsByRoleID(ctx, r.ID)
out = append(out, transformer.RoleWithPermissionsToContract(r, perms))
}
return &contract.ListRolesResponse{Roles: out}, nil
}