template-monorepo/internal/model/permission/usecase/role_permission_usecase.go

102 lines
2.8 KiB
Go
Raw Normal View History

package usecase
import (
"context"
"gateway/internal/model/permission/domain/entity"
domrepo "gateway/internal/model/permission/domain/repository"
dom "gateway/internal/model/permission/domain/usecase"
)
// PolicyReloader is the optional callback invoked after Replace mutates
// role_permissions. RBACUseCase.BroadcastReload satisfies it; passing nil
// disables the post-replace broadcast (useful in tests).
type PolicyReloader func(ctx context.Context, tenantID string) error
// RolePermissionUseCaseParam injects all repos needed to replace role
// permission sets and the reloader hook.
type RolePermissionUseCaseParam struct {
Roles domrepo.RoleRepository
Permissions domrepo.PermissionRepository
RolePermissions domrepo.RolePermissionRepository
Reloader PolicyReloader
}
type rolePermissionUseCase struct {
roles domrepo.RoleRepository
perms domrepo.PermissionRepository
rolePerms domrepo.RolePermissionRepository
reload PolicyReloader
}
// NewRolePermissionUseCase returns the role↔permission editor.
func NewRolePermissionUseCase(param RolePermissionUseCaseParam) dom.RolePermissionUseCase {
return &rolePermissionUseCase{
roles: param.Roles,
perms: param.Permissions,
rolePerms: param.RolePermissions,
reload: param.Reloader,
}
}
func (uc *rolePermissionUseCase) List(
ctx context.Context,
tenantID, roleID string,
) ([]*entity.Permission, error) {
if _, err := uc.roles.GetByID(ctx, tenantID, roleID); err != nil {
return nil, wrapRepoErr(err)
}
rps, err := uc.rolePerms.ListByRole(ctx, tenantID, roleID)
if err != nil {
return nil, wrapRepoErr(err)
}
if len(rps) == 0 {
return nil, nil
}
ids := make([]string, 0, len(rps))
for _, rp := range rps {
ids = append(ids, rp.PermissionID)
}
perms, err := uc.perms.GetByIDs(ctx, ids)
if err != nil {
return nil, wrapRepoErr(err)
}
return perms, nil
}
func (uc *rolePermissionUseCase) Replace(
ctx context.Context,
tenantID, roleID string,
permissionIDs []string,
) error {
role, err := uc.roles.GetByID(ctx, tenantID, roleID)
if err != nil {
return wrapRepoErr(err)
}
allPerms, err := uc.perms.GetAll(ctx, nil)
if err != nil {
return wrapRepoErr(err)
}
allowed := make(map[string]struct{}, len(allPerms))
for _, perm := range allPerms {
allowed[perm.ID.Hex()] = struct{}{}
}
for _, id := range permissionIDs {
if _, ok := allowed[id]; !ok {
return errb.ResNotFound("permission not in catalog: " + id)
}
}
closure := getFullParentPermissionIDs(permissionIDs, allPerms)
if err := uc.rolePerms.SetForRole(ctx, tenantID, roleID, closure); err != nil {
return wrapRepoErr(err, "set role permissions")
}
if uc.reload != nil {
if err := uc.reload(ctx, role.TenantID); err != nil {
return wrapRepoErr(err, "reload policy")
}
}
return nil
}
var _ dom.RolePermissionUseCase = (*rolePermissionUseCase)(nil)