Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions channels/middleware/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"github.com/absmach/supermq/pkg/policies"
"github.com/absmach/supermq/pkg/roles"
rmMW "github.com/absmach/supermq/pkg/roles/rolemanager/middleware"
"github.com/absmach/supermq/pkg/svcutil"
)

var (
Expand Down Expand Up @@ -48,8 +47,8 @@
svc channels.Service
repo channels.Repository
authz smqauthz.Authorization
opp svcutil.OperationPerm
extOpp svcutil.ExternalOperationPerm
opp channels.OperationPerm
extOpp channels.ExternalOperationPerm
callout callout.Callout
rmMW.RoleManagerAuthorizationMiddleware
}
Expand All @@ -59,8 +58,9 @@
svc channels.Service,
repo channels.Repository,
authz smqauthz.Authorization,
channelsOpPerm, rolesOpPerm map[svcutil.Operation]svcutil.Permission,
extOpPerm map[svcutil.ExternalOperation]svcutil.Permission,
channelsOpPerm map[channels.Operation]channels.Permission,
rolesOpPerm map[roles.Operation]roles.Permission,
extOpPerm map[channels.ExternalOperation]channels.Permission,
callout callout.Callout,
) (channels.Service, error) {
opp := channels.NewOperationPerm()
Expand All @@ -78,6 +78,7 @@
if err := extOpp.Validate(); err != nil {
return nil, err
}

ram, err := rmMW.NewRoleManagerAuthorizationMiddleware(policies.ChannelType, svc, authz, rolesOpPerm, callout)
if err != nil {
return nil, err
Expand Down Expand Up @@ -134,7 +135,7 @@
"entities": chs,
"count": len(chs),
}
if err := am.callOut(ctx, session, channels.OpCreateChannel.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpCreateChannel.String(), params); err != nil {

Check warning on line 138 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L138

Added line #L138 was not covered by tests
return []channels.Channel{}, []roles.RoleProvision{}, err
}

Expand Down Expand Up @@ -167,7 +168,7 @@
params := map[string]any{
"entity_id": id,
}
if err := am.callOut(ctx, session, channels.OpViewChannel.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpViewChannel.String(), params); err != nil {

Check warning on line 171 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L171

Added line #L171 was not covered by tests
return channels.Channel{}, err
}
return am.svc.ViewChannel(ctx, session, id, withRoles)
Expand All @@ -193,7 +194,7 @@
params := map[string]any{
"pagemeta": pm,
}
if err := am.callOut(ctx, session, channels.OpListChannels.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpListChannels.String(), params); err != nil {

Check warning on line 197 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L197

Added line #L197 was not covered by tests
return channels.ChannelsPage{}, err
}
return am.svc.ListChannels(ctx, session, pm)
Expand All @@ -219,7 +220,7 @@
"user_id": userID,
"pagemeta": pm,
}
if err := am.callOut(ctx, session, channels.OpListUserChannels.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpListUserChannels.String(), params); err != nil {

Check warning on line 223 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L223

Added line #L223 was not covered by tests
return channels.ChannelsPage{}, err
}
return am.svc.ListUserChannels(ctx, session, userID, pm)
Expand Down Expand Up @@ -251,7 +252,7 @@
params := map[string]any{
"entity_id": channel.ID,
}
if err := am.callOut(ctx, session, channels.OpUpdateChannel.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpUpdateChannel.String(), params); err != nil {

Check warning on line 255 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L255

Added line #L255 was not covered by tests
return channels.Channel{}, err
}
return am.svc.UpdateChannel(ctx, session, channel)
Expand Down Expand Up @@ -283,7 +284,7 @@
params := map[string]any{
"entity_id": channel.ID,
}
if err := am.callOut(ctx, session, channels.OpUpdateChannelTags.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpUpdateChannelTags.String(), params); err != nil {

Check warning on line 287 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L287

Added line #L287 was not covered by tests
return channels.Channel{}, err
}
return am.svc.UpdateChannelTags(ctx, session, channel)
Expand Down Expand Up @@ -315,7 +316,7 @@
params := map[string]any{
"entity_id": id,
}
if err := am.callOut(ctx, session, channels.OpEnableChannel.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpEnableChannel.String(), params); err != nil {

Check warning on line 319 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L319

Added line #L319 was not covered by tests
return channels.Channel{}, err
}
return am.svc.EnableChannel(ctx, session, id)
Expand Down Expand Up @@ -347,7 +348,7 @@
params := map[string]any{
"entity_id": id,
}
if err := am.callOut(ctx, session, channels.OpDisableChannel.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpDisableChannel.String(), params); err != nil {

Check warning on line 351 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L351

Added line #L351 was not covered by tests
return channels.Channel{}, err
}
return am.svc.DisableChannel(ctx, session, id)
Expand Down Expand Up @@ -378,7 +379,7 @@
params := map[string]any{
"entity_id": id,
}
if err := am.callOut(ctx, session, channels.OpDeleteChannel.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpDeleteChannel.String(), params); err != nil {

Check warning on line 382 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L382

Added line #L382 was not covered by tests
return err
}

Expand Down Expand Up @@ -440,7 +441,7 @@
"client_ids": thIDs,
"connection_types": connTypes,
}
if err := am.callOut(ctx, session, channels.OpConnectClient.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpConnectClient.String(), params); err != nil {

Check warning on line 444 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L444

Added line #L444 was not covered by tests
return err
}
return am.svc.Connect(ctx, session, chIDs, thIDs, connTypes)
Expand Down Expand Up @@ -502,7 +503,7 @@
"client_ids": thIDs,
"connection_types": connTypes,
}
if err := am.callOut(ctx, session, channels.OpDisconnectClient.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpDisconnectClient.String(), params); err != nil {

Check warning on line 506 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L506

Added line #L506 was not covered by tests
return err
}
return am.svc.Disconnect(ctx, session, chIDs, thIDs, connTypes)
Expand Down Expand Up @@ -545,7 +546,7 @@
"entity_id": id,
"parent_group_id": parentGroupID,
}
if err := am.callOut(ctx, session, channels.OpSetParentGroup.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpSetParentGroup.String(), params); err != nil {

Check warning on line 549 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L549

Added line #L549 was not covered by tests
return err
}
return am.svc.SetParentGroup(ctx, session, parentGroupID, id)
Expand Down Expand Up @@ -593,15 +594,15 @@
"entity_id": id,
"parent_group_id": ch.ParentGroup,
}
if err := am.callOut(ctx, session, channels.OpRemoveParentGroup.String(channels.OperationNames), params); err != nil {
if err := am.callOut(ctx, session, channels.OpRemoveParentGroup.String(), params); err != nil {

Check warning on line 597 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L597

Added line #L597 was not covered by tests
return err
}
return am.svc.RemoveParentGroup(ctx, session, id)
}
return nil
}

func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Operation, req smqauthz.PolicyReq) error {
func (am *authorizationMiddleware) authorize(ctx context.Context, op channels.Operation, req smqauthz.PolicyReq) error {

Check warning on line 605 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L605

Added line #L605 was not covered by tests
perm, err := am.opp.GetPermission(op)
if err != nil {
return err
Expand All @@ -616,7 +617,7 @@
return nil
}

func (am *authorizationMiddleware) extAuthorize(ctx context.Context, extOp svcutil.ExternalOperation, req smqauthz.PolicyReq) error {
func (am *authorizationMiddleware) extAuthorize(ctx context.Context, extOp channels.ExternalOperation, req smqauthz.PolicyReq) error {

Check warning on line 620 in channels/middleware/authorization.go

View check run for this annotation

Codecov / codecov/patch

channels/middleware/authorization.go#L620

Added line #L620 was not covered by tests
perm, err := am.extOpp.GetPermission(extOp)
if err != nil {
return err
Expand Down
186 changes: 186 additions & 0 deletions channels/operationperm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package channels

import "fmt"

type Operation int

func (op Operation) String() string {
switch op {
case OpViewChannel:
return OpViewChannelStr
case OpUpdateChannel:
return OpUpdateChannelStr
case OpUpdateChannelTags:
return OpUpdateChannelTagsStr
case OpEnableChannel:
return OpEnableChannelStr
case OpDisableChannel:
return OpDisableChannelStr
case OpDeleteChannel:
return OpDeleteChannelStr
case OpSetParentGroup:
return OpSetParentGroupStr
case OpRemoveParentGroup:
return OpRemoveParentGroupStr
case OpConnectClient:
return OpConnectClientStr
case OpDisconnectClient:
return OpDisconnectClientStr
case OpCreateChannel:
return OpCreateChannelStr
case OpListChannels:
return OpListChannelsStr
case OpListUserChannels:
return OpListUserChannelsStr
default:
return fmt.Sprintf("unknown operation: %d", op)

Check warning on line 39 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L10-L39

Added lines #L10 - L39 were not covered by tests
}
}

type OperationPerm struct {
opPerm map[Operation]Permission
expectedOps []Operation
}

func newOperationPerm(expectedOps []Operation) OperationPerm {
return OperationPerm{
opPerm: make(map[Operation]Permission),
expectedOps: expectedOps,
}

Check warning on line 52 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L48-L52

Added lines #L48 - L52 were not covered by tests
}

func (opp OperationPerm) AddOperationPermissionMap(opMap map[Operation]Permission) error {
// First iteration check all the keys are valid, If any one key is invalid then no key should be added.
for op := range opMap {
if !opp.isKeyRequired(op) {
return fmt.Errorf("%v is not a valid operation", op.String())
}

Check warning on line 60 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L55-L60

Added lines #L55 - L60 were not covered by tests
}
for op, perm := range opMap {
opp.opPerm[op] = perm
}
return nil

Check warning on line 65 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L62-L65

Added lines #L62 - L65 were not covered by tests
}

func (opp OperationPerm) isKeyRequired(op Operation) bool {
for _, key := range opp.expectedOps {
if key == op {
return true
}

Check warning on line 72 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L68-L72

Added lines #L68 - L72 were not covered by tests
}
return false

Check warning on line 74 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L74

Added line #L74 was not covered by tests
}

func (opp OperationPerm) AddOperationPermission(op Operation, perm Permission) error {
if !opp.isKeyRequired(op) {
return fmt.Errorf("%v is not a valid operation", op.String())
}
opp.opPerm[op] = perm
return nil

Check warning on line 82 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L77-L82

Added lines #L77 - L82 were not covered by tests
}

func (opp OperationPerm) Validate() error {
for op := range opp.opPerm {
if !opp.isKeyRequired(op) {
return fmt.Errorf("OperationPerm: \"%s\" is not a valid operation", op.String())
}

Check warning on line 89 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L85-L89

Added lines #L85 - L89 were not covered by tests
}
for _, eeo := range opp.expectedOps {
if _, ok := opp.opPerm[eeo]; !ok {
return fmt.Errorf("OperationPerm: \"%s\" operation is missing", eeo.String())
}

Check warning on line 94 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L91-L94

Added lines #L91 - L94 were not covered by tests
}
return nil

Check warning on line 96 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L96

Added line #L96 was not covered by tests
}

func (opp OperationPerm) GetPermission(op Operation) (Permission, error) {
if perm, ok := opp.opPerm[op]; ok {
return perm, nil
}
return "", fmt.Errorf("operation \"%s\" doesn't have any permissions", op.String())

Check warning on line 103 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L99-L103

Added lines #L99 - L103 were not covered by tests
}

type Permission string

func (p Permission) String() string {
return string(p)

Check warning on line 109 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L108-L109

Added lines #L108 - L109 were not covered by tests
}

type ExternalOperation int

func (ep ExternalOperation) String() string {
switch ep {
case DomainOpCreateChannel:
return DomainOpCreateChannelStr
case DomainOpListChannel:
return DomainOpListChannelStr
case GroupOpSetChildChannel:
return GroupOpSetChildChannelStr
case GroupsOpRemoveChildChannel:
return GroupsOpRemoveChildChannelStr
case ClientsOpConnectChannel:
return ClientsOpConnectChannelStr
case ClientsOpDisconnectChannel:
return ClientsOpDisconnectChannelStr
default:
return fmt.Sprintf("unknown external operation: %d", ep)

Check warning on line 129 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L114-L129

Added lines #L114 - L129 were not covered by tests
}
}

type ExternalOperationPerm struct {
opPerm map[ExternalOperation]Permission
expectedOps []ExternalOperation
}

func newExternalOperationPerm(expectedOps []ExternalOperation) ExternalOperationPerm {
return ExternalOperationPerm{
opPerm: make(map[ExternalOperation]Permission),
expectedOps: expectedOps,
}

Check warning on line 142 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L138-L142

Added lines #L138 - L142 were not covered by tests
}

func (eopp ExternalOperationPerm) isKeyRequired(eop ExternalOperation) bool {
for _, key := range eopp.expectedOps {
if key == eop {
return true
}

Check warning on line 149 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L145-L149

Added lines #L145 - L149 were not covered by tests
}
return false

Check warning on line 151 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L151

Added line #L151 was not covered by tests
}

func (eopp ExternalOperationPerm) AddOperationPermissionMap(eopMap map[ExternalOperation]Permission) error {
// First iteration check all the keys are valid, If any one key is invalid then no key should be added.
for eop := range eopMap {
if !eopp.isKeyRequired(eop) {
return fmt.Errorf("%v is not a valid external operation", eop.String())
}

Check warning on line 159 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L154-L159

Added lines #L154 - L159 were not covered by tests
}
for eop, perm := range eopMap {
eopp.opPerm[eop] = perm
}
return nil

Check warning on line 164 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L161-L164

Added lines #L161 - L164 were not covered by tests
}

func (eopp ExternalOperationPerm) Validate() error {
for eop := range eopp.opPerm {
if !eopp.isKeyRequired(eop) {
return fmt.Errorf("ExternalOperationPerm: \"%s\" is not a valid external operation", eop.String())
}

Check warning on line 171 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L167-L171

Added lines #L167 - L171 were not covered by tests
}
for _, eeo := range eopp.expectedOps {
if _, ok := eopp.opPerm[eeo]; !ok {
return fmt.Errorf("ExternalOperationPerm: \"%s\" external operation is missing", eeo.String())
}

Check warning on line 176 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L173-L176

Added lines #L173 - L176 were not covered by tests
}
return nil

Check warning on line 178 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L178

Added line #L178 was not covered by tests
}

func (eopp ExternalOperationPerm) GetPermission(eop ExternalOperation) (Permission, error) {
if perm, ok := eopp.opPerm[eop]; ok {
return perm, nil
}
return "", fmt.Errorf("external operation \"%s\" doesn't have any permissions", eop.String())

Check warning on line 185 in channels/operationperm.go

View check run for this annotation

Codecov / codecov/patch

channels/operationperm.go#L181-L185

Added lines #L181 - L185 were not covered by tests
}
Loading
Loading