Add user Roles
This commit is contained in:
parent
9e95e8ee5e
commit
001d02c587
@ -43,14 +43,16 @@ func (a *App) Initialize(cfg *config.Config) error {
|
||||
middlewares := a.initMiddleware(services)
|
||||
healthHandler := handler.NewHealthHandler()
|
||||
fileHandler := handler.NewFileHandler(services.fileService)
|
||||
rbacHandler := handler.NewRBACHandler(services.rbacService)
|
||||
|
||||
a.router = router.NewRouter(
|
||||
cfg,
|
||||
handler.NewAuthHandler(services.authService),
|
||||
middlewares.authMiddleware,
|
||||
healthHandler,
|
||||
handler.NewUserHandler(services.userService, &validator.UserValidatorImpl{}),
|
||||
handler.NewUserHandler(services.userService, validator.NewUserValidator()),
|
||||
fileHandler,
|
||||
rbacHandler,
|
||||
)
|
||||
|
||||
return nil
|
||||
@ -99,6 +101,7 @@ type repositories struct {
|
||||
userRepo *repository.UserRepositoryImpl
|
||||
userProfileRepo *repository.UserProfileRepository
|
||||
titleRepo *repository.TitleRepository
|
||||
rbacRepo *repository.RBACRepository
|
||||
}
|
||||
|
||||
func (a *App) initRepositories() *repositories {
|
||||
@ -106,6 +109,7 @@ func (a *App) initRepositories() *repositories {
|
||||
userRepo: repository.NewUserRepository(a.db),
|
||||
userProfileRepo: repository.NewUserProfileRepository(a.db),
|
||||
titleRepo: repository.NewTitleRepository(a.db),
|
||||
rbacRepo: repository.NewRBACRepository(a.db),
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,6 +127,7 @@ type services struct {
|
||||
userService *service.UserServiceImpl
|
||||
authService *service.AuthServiceImpl
|
||||
fileService *service.FileServiceImpl
|
||||
rbacService *service.RBACServiceImpl
|
||||
}
|
||||
|
||||
func (a *App) initServices(processors *processors, repos *repositories, cfg *config.Config) *services {
|
||||
@ -137,10 +142,13 @@ func (a *App) initServices(processors *processors, repos *repositories, cfg *con
|
||||
s3Client := client.NewFileClient(fileCfg)
|
||||
fileSvc := service.NewFileService(s3Client, processors.userProcessor, "profile", "documents")
|
||||
|
||||
rbacSvc := service.NewRBACService(repos.rbacRepo)
|
||||
|
||||
return &services{
|
||||
userService: userSvc,
|
||||
authService: authService,
|
||||
fileService: fileSvc,
|
||||
rbacService: rbacSvc,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
57
internal/contract/rbac_contract.go
Normal file
57
internal/contract/rbac_contract.go
Normal file
@ -0,0 +1,57 @@
|
||||
package contract
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type PermissionResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Code string `json:"code"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CreatePermissionRequest struct {
|
||||
Code string `json:"code"` // unique
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
type UpdatePermissionRequest struct {
|
||||
Code *string `json:"code,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
type ListPermissionsResponse struct {
|
||||
Permissions []PermissionResponse `json:"permissions"`
|
||||
}
|
||||
|
||||
type RoleWithPermissionsResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Permissions []PermissionResponse `json:"permissions"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CreateRoleRequest struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
PermissionCodes []string `json:"permission_codes,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateRoleRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Code *string `json:"code,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
PermissionCodes *[]string `json:"permission_codes,omitempty"`
|
||||
}
|
||||
|
||||
type ListRolesResponse struct {
|
||||
Roles []RoleWithPermissionsResponse `json:"roles"`
|
||||
}
|
||||
10
internal/entities/role_permission.go
Normal file
10
internal/entities/role_permission.go
Normal file
@ -0,0 +1,10 @@
|
||||
package entities
|
||||
|
||||
import "github.com/google/uuid"
|
||||
|
||||
type RolePermission struct {
|
||||
RoleID uuid.UUID `gorm:"type:uuid;primaryKey" json:"role_id"`
|
||||
PermissionID uuid.UUID `gorm:"type:uuid;primaryKey" json:"permission_id"`
|
||||
}
|
||||
|
||||
func (RolePermission) TableName() string { return "role_permissions" }
|
||||
137
internal/handler/rbac_handler.go
Normal file
137
internal/handler/rbac_handler.go
Normal file
@ -0,0 +1,137 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"eslogad-be/internal/contract"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type RBACService interface {
|
||||
CreatePermission(ctx context.Context, req *contract.CreatePermissionRequest) (*contract.PermissionResponse, error)
|
||||
UpdatePermission(ctx context.Context, id uuid.UUID, req *contract.UpdatePermissionRequest) (*contract.PermissionResponse, error)
|
||||
DeletePermission(ctx context.Context, id uuid.UUID) error
|
||||
ListPermissions(ctx context.Context) (*contract.ListPermissionsResponse, error)
|
||||
|
||||
CreateRole(ctx context.Context, req *contract.CreateRoleRequest) (*contract.RoleWithPermissionsResponse, error)
|
||||
UpdateRole(ctx context.Context, id uuid.UUID, req *contract.UpdateRoleRequest) (*contract.RoleWithPermissionsResponse, error)
|
||||
DeleteRole(ctx context.Context, id uuid.UUID) error
|
||||
ListRoles(ctx context.Context) (*contract.ListRolesResponse, error)
|
||||
}
|
||||
|
||||
type RBACHandler struct{ svc RBACService }
|
||||
|
||||
func NewRBACHandler(svc RBACService) *RBACHandler { return &RBACHandler{svc: svc} }
|
||||
|
||||
func (h *RBACHandler) CreatePermission(c *gin.Context) {
|
||||
var req contract.CreatePermissionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
resp, err := h.svc.CreatePermission(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *RBACHandler) UpdatePermission(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: 400})
|
||||
return
|
||||
}
|
||||
var req contract.UpdatePermissionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: 400})
|
||||
return
|
||||
}
|
||||
resp, err := h.svc.UpdatePermission(c.Request.Context(), id, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *RBACHandler) DeletePermission(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: 400})
|
||||
return
|
||||
}
|
||||
if err := h.svc.DeletePermission(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "deleted"})
|
||||
}
|
||||
|
||||
func (h *RBACHandler) ListPermissions(c *gin.Context) {
|
||||
resp, err := h.svc.ListPermissions(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *RBACHandler) CreateRole(c *gin.Context) {
|
||||
var req contract.CreateRoleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: 400})
|
||||
return
|
||||
}
|
||||
resp, err := h.svc.CreateRole(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *RBACHandler) UpdateRole(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: 400})
|
||||
return
|
||||
}
|
||||
var req contract.UpdateRoleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: 400})
|
||||
return
|
||||
}
|
||||
resp, err := h.svc.UpdateRole(c.Request.Context(), id, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *RBACHandler) DeleteRole(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: 400})
|
||||
return
|
||||
}
|
||||
if err := h.svc.DeleteRole(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "deleted"})
|
||||
}
|
||||
|
||||
func (h *RBACHandler) ListRoles(c *gin.Context) {
|
||||
resp, err := h.svc.ListRoles(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
97
internal/repository/rbac_repository.go
Normal file
97
internal/repository/rbac_repository.go
Normal file
@ -0,0 +1,97 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"eslogad-be/internal/entities"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RBACRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewRBACRepository(db *gorm.DB) *RBACRepository { return &RBACRepository{db: db} }
|
||||
|
||||
// Permissions
|
||||
func (r *RBACRepository) CreatePermission(ctx context.Context, p *entities.Permission) error {
|
||||
return r.db.WithContext(ctx).Create(p).Error
|
||||
}
|
||||
func (r *RBACRepository) UpdatePermission(ctx context.Context, p *entities.Permission) error {
|
||||
return r.db.WithContext(ctx).Model(&entities.Permission{}).Where("id = ?", p.ID).Updates(p).Error
|
||||
}
|
||||
func (r *RBACRepository) DeletePermission(ctx context.Context, id uuid.UUID) error {
|
||||
return r.db.WithContext(ctx).Delete(&entities.Permission{}, "id = ?", id).Error
|
||||
}
|
||||
func (r *RBACRepository) ListPermissions(ctx context.Context) ([]entities.Permission, error) {
|
||||
var perms []entities.Permission
|
||||
if err := r.db.WithContext(ctx).Order("code ASC").Find(&perms).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return perms, nil
|
||||
}
|
||||
func (r *RBACRepository) GetPermissionByCode(ctx context.Context, code string) (*entities.Permission, error) {
|
||||
var p entities.Permission
|
||||
if err := r.db.WithContext(ctx).First(&p, "code = ?", code).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
// Roles
|
||||
func (r *RBACRepository) CreateRole(ctx context.Context, role *entities.Role) error {
|
||||
return r.db.WithContext(ctx).Create(role).Error
|
||||
}
|
||||
func (r *RBACRepository) UpdateRole(ctx context.Context, role *entities.Role) error {
|
||||
return r.db.WithContext(ctx).Model(&entities.Role{}).Where("id = ?", role.ID).Updates(role).Error
|
||||
}
|
||||
func (r *RBACRepository) DeleteRole(ctx context.Context, id uuid.UUID) error {
|
||||
return r.db.WithContext(ctx).Delete(&entities.Role{}, "id = ?", id).Error
|
||||
}
|
||||
func (r *RBACRepository) ListRoles(ctx context.Context) ([]entities.Role, error) {
|
||||
var roles []entities.Role
|
||||
if err := r.db.WithContext(ctx).Order("name ASC").Find(&roles).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
func (r *RBACRepository) GetRoleByCode(ctx context.Context, code string) (*entities.Role, error) {
|
||||
var role entities.Role
|
||||
if err := r.db.WithContext(ctx).First(&role, "code = ?", code).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &role, nil
|
||||
}
|
||||
|
||||
func (r *RBACRepository) SetRolePermissionsByCodes(ctx context.Context, roleID uuid.UUID, permCodes []string) error {
|
||||
if err := r.db.WithContext(ctx).Where("role_id = ?", roleID).Delete(&entities.RolePermission{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if len(permCodes) == 0 {
|
||||
return nil
|
||||
}
|
||||
var perms []entities.Permission
|
||||
if err := r.db.WithContext(ctx).Where("code IN ?", permCodes).Find(&perms).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
pairs := make([]entities.RolePermission, 0, len(perms))
|
||||
for _, p := range perms {
|
||||
pairs = append(pairs, entities.RolePermission{RoleID: roleID, PermissionID: p.ID})
|
||||
}
|
||||
return r.db.WithContext(ctx).Create(&pairs).Error
|
||||
}
|
||||
|
||||
func (r *RBACRepository) GetPermissionsByRoleID(ctx context.Context, roleID uuid.UUID) ([]entities.Permission, error) {
|
||||
var perms []entities.Permission
|
||||
if err := r.db.WithContext(ctx).
|
||||
Table("permissions p").
|
||||
Select("p.*").
|
||||
Joins("JOIN role_permissions rp ON rp.permission_id = p.id").
|
||||
Where("rp.role_id = ?", roleID).
|
||||
Find(&perms).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return perms, nil
|
||||
}
|
||||
@ -18,3 +18,15 @@ type FileHandler interface {
|
||||
UploadProfileAvatar(c *gin.Context)
|
||||
UploadDocument(c *gin.Context)
|
||||
}
|
||||
|
||||
type RBACHandler interface {
|
||||
CreatePermission(c *gin.Context)
|
||||
UpdatePermission(c *gin.Context)
|
||||
DeletePermission(c *gin.Context)
|
||||
ListPermissions(c *gin.Context)
|
||||
|
||||
CreateRole(c *gin.Context)
|
||||
UpdateRole(c *gin.Context)
|
||||
DeleteRole(c *gin.Context)
|
||||
ListRoles(c *gin.Context)
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ type Router struct {
|
||||
authMiddleware AuthMiddleware
|
||||
userHandler UserHandler
|
||||
fileHandler FileHandler
|
||||
rbacHandler RBACHandler
|
||||
}
|
||||
|
||||
func NewRouter(
|
||||
@ -23,6 +24,7 @@ func NewRouter(
|
||||
healthHandler HealthHandler,
|
||||
userHandler UserHandler,
|
||||
fileHandler FileHandler,
|
||||
rbacHandler RBACHandler,
|
||||
) *Router {
|
||||
return &Router{
|
||||
config: cfg,
|
||||
@ -31,6 +33,7 @@ func NewRouter(
|
||||
healthHandler: healthHandler,
|
||||
userHandler: userHandler,
|
||||
fileHandler: fileHandler,
|
||||
rbacHandler: rbacHandler,
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,5 +80,18 @@ func (r *Router) addAppRoutes(rg *gin.Engine) {
|
||||
{
|
||||
files.POST("/documents", r.fileHandler.UploadDocument)
|
||||
}
|
||||
|
||||
rbac := v1.Group("/rbac")
|
||||
rbac.Use(r.authMiddleware.RequireAuth())
|
||||
{
|
||||
rbac.GET("/permissions", r.rbacHandler.ListPermissions)
|
||||
rbac.POST("/permissions", r.rbacHandler.CreatePermission)
|
||||
rbac.PUT("/permissions/:id", r.rbacHandler.UpdatePermission)
|
||||
rbac.DELETE("/permissions/:id", r.rbacHandler.DeletePermission)
|
||||
rbac.GET("/roles", r.rbacHandler.ListRoles)
|
||||
rbac.POST("/roles", r.rbacHandler.CreateRole)
|
||||
rbac.PUT("/roles/:id", r.rbacHandler.UpdateRole)
|
||||
rbac.DELETE("/roles/:id", r.rbacHandler.DeleteRole)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
128
internal/service/rbac_service.go
Normal file
128
internal/service/rbac_service.go
Normal file
@ -0,0 +1,128 @@
|
||||
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
|
||||
}
|
||||
@ -170,3 +170,23 @@ func TitlesToContract(titles []entities.Title) []contract.TitleResponse {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func PermissionsToContract(perms []entities.Permission) []contract.PermissionResponse {
|
||||
out := make([]contract.PermissionResponse, 0, len(perms))
|
||||
for _, p := range perms {
|
||||
out = append(out, contract.PermissionResponse{ID: p.ID, Code: p.Code, Description: &p.Description, CreatedAt: p.CreatedAt, UpdatedAt: p.UpdatedAt})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func RoleWithPermissionsToContract(role entities.Role, perms []entities.Permission) contract.RoleWithPermissionsResponse {
|
||||
return contract.RoleWithPermissionsResponse{
|
||||
ID: role.ID,
|
||||
Name: role.Name,
|
||||
Code: role.Code,
|
||||
Description: &role.Description,
|
||||
Permissions: PermissionsToContract(perms),
|
||||
CreatedAt: role.CreatedAt,
|
||||
UpdatedAt: role.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user