102 lines
2.8 KiB
Go
102 lines
2.8 KiB
Go
|
|
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)
|