Files
Dušan Borovčanin 61d0427898 NOISSUE - Rename to Magistrala (#3427)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 15:23:42 +02:00

157 lines
3.7 KiB
Go

// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package permissions
import (
"fmt"
"github.com/absmach/magistrala/pkg/errors"
)
var (
ErrMergeInvalidOperations = errors.New("failed to merge: invalid operations type")
ErrRemoveInvalidOperations = errors.New("failed to remove: invalid operations type")
)
type Permission string
func (p Permission) String() string {
return string(p)
}
type Operation int
type ExternalOperation int
type RoleOperation int
type OperationKey interface {
Operation | ExternalOperation | RoleOperation
}
type OperationName[K OperationKey] map[K]string
type OperationDetails struct {
Name string
PermissionRequired bool
}
type operations[K OperationKey] struct {
opPermission map[K]Permission
opDetails map[K]OperationDetails
}
type Operations[K OperationKey] interface {
GetPermission(op K) (Permission, error)
GetPermissionAndRequired(op K) (Permission, bool, error)
OperationName(op K) string
Validate() error
Merge(nops Operations[K]) error
Remove(rops Operations[K]) error
}
func NewOperations[K OperationKey](opdetails map[K]OperationDetails, opnamePerm map[string]Permission) (Operations[K], error) {
ops := newEmptyOperations(opdetails)
if err := ops.addOperationPermission(opnamePerm); err != nil {
return nil, err
}
if err := ops.Validate(); err != nil {
return nil, err
}
return &ops, nil
}
func newEmptyOperations[K OperationKey](opdetails map[K]OperationDetails) operations[K] {
return operations[K]{
opPermission: make(map[K]Permission),
opDetails: opdetails,
}
}
func (ops *operations[K]) OperationName(op K) string {
opDetail, ok := ops.opDetails[op]
if !ok {
return fmt.Sprintf("UnknownOperation(%v)", op)
}
return opDetail.Name
}
func (ops *operations[K]) addOperationPermission(opnamePerm map[string]Permission) error {
for op, opd := range ops.opDetails {
if opd.PermissionRequired {
perm, ok := opnamePerm[opd.Name]
if !ok {
return fmt.Errorf("permission related to operation name %s not found", opd.Name)
}
ops.opPermission[op] = perm
}
}
return nil
}
func (ops *operations[K]) Validate() error {
for op, opd := range ops.opDetails {
if opd.PermissionRequired {
if _, ok := ops.opPermission[op]; !ok {
return fmt.Errorf("permission related to operation name %s not found", opd.Name)
}
}
}
return nil
}
func (ops *operations[K]) GetPermission(op K) (Permission, error) {
if perm, ok := ops.opPermission[op]; ok {
return perm, nil
}
return "", fmt.Errorf("operation %s doesn't have any permissions", ops.OperationName(op))
}
func (ops *operations[K]) GetPermissionAndRequired(op K) (Permission, bool, error) {
opd, ok := ops.opDetails[op]
if !ok {
return "", false, fmt.Errorf("operation not found %s", ops.OperationName(op))
}
perm, ok := ops.opPermission[op]
if opd.PermissionRequired && !ok {
return "", false, fmt.Errorf("operation %s doesn't have any permissions", ops.OperationName(op))
}
return perm, opd.PermissionRequired, nil
}
func (ops *operations[K]) Merge(nops Operations[K]) error {
newOps, ok := nops.(*operations[K])
if !ok {
return ErrMergeInvalidOperations
}
for op, opd := range newOps.opDetails {
ops.opDetails[op] = opd
if opd.PermissionRequired {
perm, exists := newOps.opPermission[op]
if !exists {
return fmt.Errorf("missing permission for required operation %s", opd.Name)
}
ops.opPermission[op] = perm
}
}
return nil
}
func (ops *operations[K]) Remove(rops Operations[K]) error {
remOps, ok := rops.(*operations[K])
if !ok {
return ErrRemoveInvalidOperations
}
for op := range remOps.opDetails {
delete(ops.opDetails, op)
delete(ops.opPermission, op)
}
return nil
}