kra-oa/internal/biz/authority.go

74 lines
2.2 KiB
Go

package biz
import (
"context"
"time"
)
type AuthorityAccessRepo interface {
CreateAuthority(context.Context, *Authority) error
CopyAuthority(context.Context, uint, *Authority) error
UpdateAuthority(context.Context, *Authority) error
DeleteAuthority(context.Context, uint) error
ListAuthorities(context.Context) ([]*Authority, error)
SetAuthorityUsers(context.Context, uint, []uint) error
AuthorityUserIDs(context.Context, uint) ([]uint, error)
SetDataScope(context.Context, uint, int, []uint) error
DataScopeDepartmentIDs(context.Context, uint) ([]uint, error)
ResolveDataScope(context.Context, uint, uint) (DataScope, error)
}
// Authority is the domain representation of an administration role. Keep the
// audit timestamps because exports and API clients use them even though the
// administration screens do not display them.
type Authority struct {
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
AuthorityID uint
AuthorityName string
ParentID *uint
DataScope int
DefaultRouter string
Children []*Authority
}
type AuthorityUsecase struct{ AuthorityAccessRepo }
func NewAuthorityUsecase(repo AuthorityAccessRepo) *AuthorityUsecase {
return &AuthorityUsecase{AuthorityAccessRepo: repo}
}
func (uc *AuthorityUsecase) AuthorityTree(ctx context.Context) ([]*Authority, error) {
items, err := uc.ListAuthorities(ctx)
if err != nil {
return nil, err
}
byID := make(map[uint]*Authority, len(items))
for _, item := range items {
item.Children = nil
byID[item.AuthorityID] = item
}
roots := make([]*Authority, 0)
for _, item := range items {
if item.ParentID != nil && *item.ParentID != 0 && byID[*item.ParentID] != nil {
parent := byID[*item.ParentID]
parent.Children = append(parent.Children, item)
} else if item.ParentID != nil && *item.ParentID == 0 {
roots = append(roots, item)
}
}
// In strict-authority mode a non-root actor receives its direct
// children as the top-level result even though their parent is omitted.
if len(roots) == 0 {
if actor, ok := ActorFromContext(ctx); ok {
for _, item := range items {
if item.ParentID != nil && *item.ParentID == actor.AuthorityID {
roots = append(roots, item)
}
}
}
}
return roots, nil
}