mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
61d0427898
Signed-off-by: dusan <borovcanindusan1@gmail.com>
157 lines
3.7 KiB
Go
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
|
|
}
|