mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
MG-2048 - Authorize groups and channels with PATs (#2501)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> Signed-off-by: Felix Gateru <felix.gateru@gmail.com> Signed-off-by: Arvindh <arvindh91@gmail.com> Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
This commit is contained in:
+2
-2
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/auth"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
@@ -24,7 +25,6 @@ func AuthenticateMiddleware(authn smqauthn.Authentication, domainCheck bool) fun
|
||||
EncodeError(r.Context(), apiutil.ErrBearerToken, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := authn.Authenticate(r.Context(), token)
|
||||
if err != nil {
|
||||
EncodeError(r.Context(), err, w)
|
||||
@@ -38,7 +38,7 @@ func AuthenticateMiddleware(authn smqauthn.Authentication, domainCheck bool) fun
|
||||
return
|
||||
}
|
||||
resp.DomainID = domain
|
||||
resp.DomainUserID = domain + "_" + resp.UserID
|
||||
resp.DomainUserID = auth.EncodeDomainUserID(domain, resp.UserID)
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), SessionKey, resp)
|
||||
|
||||
+2
-7
@@ -514,13 +514,8 @@ func (svc service) UpdatePATDescription(ctx context.Context, token, patID, descr
|
||||
return pat, nil
|
||||
}
|
||||
|
||||
func (svc service) RetrievePAT(ctx context.Context, token, patID string) (PAT, error) {
|
||||
key, err := svc.Identify(ctx, token)
|
||||
if err != nil {
|
||||
return PAT{}, err
|
||||
}
|
||||
|
||||
pat, err := svc.pats.Retrieve(ctx, key.User, patID)
|
||||
func (svc service) RetrievePAT(ctx context.Context, userID, patID string) (PAT, error) {
|
||||
pat, err := svc.pats.Retrieve(ctx, userID, patID)
|
||||
if err != nil {
|
||||
return PAT{}, errors.Wrap(errRetrievePAT, err)
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/absmach/supermq/auth"
|
||||
"github.com/absmach/supermq/channels"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/authz"
|
||||
smqauthz "github.com/absmach/supermq/pkg/authz"
|
||||
"github.com/absmach/supermq/pkg/connections"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
@@ -82,7 +82,21 @@ func AuthorizationMiddleware(svc channels.Service, repo channels.Repository, aut
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) CreateChannels(ctx context.Context, session authn.Session, chs ...channels.Channel) ([]channels.Channel, []roles.RoleProvision, error) {
|
||||
if err := am.extAuthorize(ctx, channels.DomainOpCreateChannel, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.CreateOp,
|
||||
EntityIDs: auth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return []channels.Channel{}, []roles.RoleProvision{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.extAuthorize(ctx, channels.DomainOpCreateChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -94,7 +108,7 @@ func (am *authorizationMiddleware) CreateChannels(ctx context.Context, session a
|
||||
|
||||
for _, ch := range chs {
|
||||
if ch.ParentGroup != "" {
|
||||
if err := am.extAuthorize(ctx, channels.GroupOpSetChildChannel, authz.PolicyReq{
|
||||
if err := am.extAuthorize(ctx, channels.GroupOpSetChildChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -109,7 +123,21 @@ func (am *authorizationMiddleware) CreateChannels(ctx context.Context, session a
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ViewChannel(ctx context.Context, session authn.Session, id string) (channels.Channel, error) {
|
||||
if err := am.authorize(ctx, channels.OpViewChannel, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.ReadOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return channels.Channel{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpViewChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -122,6 +150,20 @@ func (am *authorizationMiddleware) ViewChannel(ctx context.Context, session auth
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListChannels(ctx context.Context, session authn.Session, pm channels.PageMetadata) (channels.Page, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.ListOp,
|
||||
EntityIDs: auth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return channels.Page{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.checkSuperAdmin(ctx, session.UserID); err != nil {
|
||||
session.SuperAdmin = true
|
||||
}
|
||||
@@ -129,11 +171,38 @@ func (am *authorizationMiddleware) ListChannels(ctx context.Context, session aut
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListChannelsByClient(ctx context.Context, session authn.Session, clientID string, pm channels.PageMetadata) (channels.Page, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.ListOp,
|
||||
EntityIDs: auth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return channels.Page{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
return am.svc.ListChannelsByClient(ctx, session, clientID, pm)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateChannel(ctx context.Context, session authn.Session, channel channels.Channel) (channels.Channel, error) {
|
||||
if err := am.authorize(ctx, channels.OpUpdateChannel, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{channel.ID},
|
||||
}); err != nil {
|
||||
return channels.Channel{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpUpdateChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -146,7 +215,21 @@ func (am *authorizationMiddleware) UpdateChannel(ctx context.Context, session au
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateChannelTags(ctx context.Context, session authn.Session, channel channels.Channel) (channels.Channel, error) {
|
||||
if err := am.authorize(ctx, channels.OpUpdateChannelTags, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{channel.ID},
|
||||
}); err != nil {
|
||||
return channels.Channel{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpUpdateChannelTags, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -159,7 +242,21 @@ func (am *authorizationMiddleware) UpdateChannelTags(ctx context.Context, sessio
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) EnableChannel(ctx context.Context, session authn.Session, id string) (channels.Channel, error) {
|
||||
if err := am.authorize(ctx, channels.OpEnableChannel, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return channels.Channel{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpEnableChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -172,7 +269,21 @@ func (am *authorizationMiddleware) EnableChannel(ctx context.Context, session au
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DisableChannel(ctx context.Context, session authn.Session, id string) (channels.Channel, error) {
|
||||
if err := am.authorize(ctx, channels.OpDisableChannel, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return channels.Channel{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpDisableChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -185,7 +296,21 @@ func (am *authorizationMiddleware) DisableChannel(ctx context.Context, session a
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RemoveChannel(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := am.authorize(ctx, channels.OpDeleteChannel, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpDeleteChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -198,8 +323,33 @@ func (am *authorizationMiddleware) RemoveChannel(ctx context.Context, session au
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) Connect(ctx context.Context, session authn.Session, chIDs, thIDs []string, connTypes []connections.ConnType) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.CreateOp,
|
||||
EntityIDs: chIDs,
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainClientsScope,
|
||||
Operation: auth.CreateOp,
|
||||
EntityIDs: thIDs,
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
for _, chID := range chIDs {
|
||||
if err := am.authorize(ctx, channels.OpConnectClient, authz.PolicyReq{
|
||||
if err := am.authorize(ctx, channels.OpConnectClient, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -211,7 +361,7 @@ func (am *authorizationMiddleware) Connect(ctx context.Context, session authn.Se
|
||||
}
|
||||
|
||||
for _, thID := range thIDs {
|
||||
if err := am.extAuthorize(ctx, channels.ClientsOpConnectChannel, authz.PolicyReq{
|
||||
if err := am.extAuthorize(ctx, channels.ClientsOpConnectChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -225,8 +375,34 @@ func (am *authorizationMiddleware) Connect(ctx context.Context, session authn.Se
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) Disconnect(ctx context.Context, session authn.Session, chIDs, thIDs []string, connTypes []connections.ConnType) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: chIDs,
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainClientsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: thIDs,
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, chID := range chIDs {
|
||||
if err := am.authorize(ctx, channels.OpDisconnectClient, authz.PolicyReq{
|
||||
if err := am.authorize(ctx, channels.OpDisconnectClient, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -238,7 +414,7 @@ func (am *authorizationMiddleware) Disconnect(ctx context.Context, session authn
|
||||
}
|
||||
|
||||
for _, thID := range thIDs {
|
||||
if err := am.extAuthorize(ctx, channels.ClientsOpDisconnectChannel, authz.PolicyReq{
|
||||
if err := am.extAuthorize(ctx, channels.ClientsOpDisconnectChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -252,7 +428,21 @@ func (am *authorizationMiddleware) Disconnect(ctx context.Context, session authn
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) SetParentGroup(ctx context.Context, session authn.Session, parentGroupID string, id string) error {
|
||||
if err := am.authorize(ctx, channels.OpSetParentGroup, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpSetParentGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -262,7 +452,7 @@ func (am *authorizationMiddleware) SetParentGroup(ctx context.Context, session a
|
||||
return errors.Wrap(err, errSetParentGroup)
|
||||
}
|
||||
|
||||
if err := am.extAuthorize(ctx, channels.GroupOpSetChildChannel, authz.PolicyReq{
|
||||
if err := am.extAuthorize(ctx, channels.GroupOpSetChildChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -275,7 +465,21 @@ func (am *authorizationMiddleware) SetParentGroup(ctx context.Context, session a
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RemoveParentGroup(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := am.authorize(ctx, channels.OpSetParentGroup, authz.PolicyReq{
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainChannelsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, channels.OpSetParentGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -290,7 +494,7 @@ func (am *authorizationMiddleware) RemoveParentGroup(ctx context.Context, sessio
|
||||
return errors.Wrap(svcerr.ErrRemoveEntity, err)
|
||||
}
|
||||
if ch.ParentGroup != "" {
|
||||
if err := am.extAuthorize(ctx, channels.GroupOpSetChildChannel, authz.PolicyReq{
|
||||
if err := am.extAuthorize(ctx, channels.GroupOpSetChildChannel, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
Subject: session.DomainUserID,
|
||||
@@ -304,7 +508,7 @@ func (am *authorizationMiddleware) RemoveParentGroup(ctx context.Context, sessio
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Operation, req authz.PolicyReq) error {
|
||||
func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Operation, req smqauthz.PolicyReq) error {
|
||||
perm, err := am.opp.GetPermission(op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -319,7 +523,7 @@ func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Ope
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) extAuthorize(ctx context.Context, extOp svcutil.ExternalOperation, req authz.PolicyReq) error {
|
||||
func (am *authorizationMiddleware) extAuthorize(ctx context.Context, extOp svcutil.ExternalOperation, req smqauthz.PolicyReq) error {
|
||||
perm, err := am.extOpp.GetPermission(extOp)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -429,6 +429,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/absmach/supermq/auth"
|
||||
"github.com/absmach/supermq/groups"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/authz"
|
||||
smqauthz "github.com/absmach/supermq/pkg/authz"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
@@ -81,6 +81,19 @@ func AuthorizationMiddleware(entityType string, svc groups.Service, repo groups.
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) CreateGroup(ctx context.Context, session authn.Session, g groups.Group) (groups.Group, []roles.RoleProvision, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.CreateOp,
|
||||
EntityIDs: auth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return groups.Group{}, []roles.RoleProvision{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
if err := am.extAuthorize(ctx, groups.DomainOpCreateGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -109,6 +122,20 @@ func (am *authorizationMiddleware) CreateGroup(ctx context.Context, session auth
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateGroup(ctx context.Context, session authn.Session, g groups.Group) (groups.Group, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{g.ID},
|
||||
}); err != nil {
|
||||
return groups.Group{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpUpdateGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -124,6 +151,20 @@ func (am *authorizationMiddleware) UpdateGroup(ctx context.Context, session auth
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ViewGroup(ctx context.Context, session authn.Session, id string) (groups.Group, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.ReadOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return groups.Group{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpViewGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -139,6 +180,20 @@ func (am *authorizationMiddleware) ViewGroup(ctx context.Context, session authn.
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListGroups(ctx context.Context, session authn.Session, gm groups.PageMeta) (groups.Page, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.ListOp,
|
||||
EntityIDs: auth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return groups.Page{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
err := am.checkSuperAdmin(ctx, session.UserID)
|
||||
if err == nil {
|
||||
session.SuperAdmin = true
|
||||
@@ -177,6 +232,20 @@ func (am *authorizationMiddleware) ListUserGroups(ctx context.Context, session a
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) EnableGroup(ctx context.Context, session authn.Session, id string) (groups.Group, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return groups.Group{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpEnableGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -191,6 +260,20 @@ func (am *authorizationMiddleware) EnableGroup(ctx context.Context, session auth
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DisableGroup(ctx context.Context, session authn.Session, id string) (groups.Group, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return groups.Group{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpDisableGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -205,6 +288,20 @@ func (am *authorizationMiddleware) DisableGroup(ctx context.Context, session aut
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DeleteGroup(ctx context.Context, session authn.Session, id string) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpDeleteGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -219,6 +316,20 @@ func (am *authorizationMiddleware) DeleteGroup(ctx context.Context, session auth
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RetrieveGroupHierarchy(ctx context.Context, session authn.Session, id string, hm groups.HierarchyPageMeta) (groups.HierarchyPage, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.ListOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return groups.HierarchyPage{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpRetrieveGroupHierarchy, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -232,6 +343,20 @@ func (am *authorizationMiddleware) RetrieveGroupHierarchy(ctx context.Context, s
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) AddParentGroup(ctx context.Context, session authn.Session, id, parentID string) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpAddParentGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -255,6 +380,20 @@ func (am *authorizationMiddleware) AddParentGroup(ctx context.Context, session a
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RemoveParentGroup(ctx context.Context, session authn.Session, id string) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpRemoveParentGroup, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -285,6 +424,20 @@ func (am *authorizationMiddleware) RemoveParentGroup(ctx context.Context, sessio
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) AddChildrenGroups(ctx context.Context, session authn.Session, id string, childrenGroupIDs []string) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.UpdateOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpAddChildrenGroups, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -311,6 +464,20 @@ func (am *authorizationMiddleware) AddChildrenGroups(ctx context.Context, sessio
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RemoveChildrenGroups(ctx context.Context, session authn.Session, id string, childrenGroupIDs []string) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpRemoveChildrenGroups, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -325,6 +492,20 @@ func (am *authorizationMiddleware) RemoveChildrenGroups(ctx context.Context, ses
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RemoveAllChildrenGroups(ctx context.Context, session authn.Session, id string) error {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.DeleteOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpRemoveAllChildrenGroups, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -339,6 +520,20 @@ func (am *authorizationMiddleware) RemoveAllChildrenGroups(ctx context.Context,
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListChildrenGroups(ctx context.Context, session authn.Session, id string, startLevel, endLevel int64, pm groups.PageMeta) (groups.Page, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.ID,
|
||||
PlatformEntityType: auth.PlatformDomainsScope,
|
||||
OptionalDomainID: session.DomainID,
|
||||
OptionalDomainEntityType: auth.DomainGroupsScope,
|
||||
Operation: auth.ListOp,
|
||||
EntityIDs: []string{id},
|
||||
}); err != nil {
|
||||
return groups.Page{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.authorize(ctx, groups.OpListChildrenGroups, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -353,7 +548,7 @@ func (am *authorizationMiddleware) ListChildrenGroups(ctx context.Context, sessi
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, adminID string) error {
|
||||
if err := am.authz.Authorize(ctx, authz.PolicyReq{
|
||||
if err := am.authz.Authorize(ctx, smqauthz.PolicyReq{
|
||||
SubjectType: policies.UserType,
|
||||
Subject: adminID,
|
||||
Permission: policies.AdminPermission,
|
||||
@@ -365,7 +560,7 @@ func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, adminID
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Operation, pr authz.PolicyReq) error {
|
||||
func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Operation, pr smqauthz.PolicyReq) error {
|
||||
perm, err := am.opp.GetPermission(op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -378,7 +573,7 @@ func (am *authorizationMiddleware) authorize(ctx context.Context, op svcutil.Ope
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) extAuthorize(ctx context.Context, extOp svcutil.ExternalOperation, req authz.PolicyReq) error {
|
||||
func (am *authorizationMiddleware) extAuthorize(ctx context.Context, extOp svcutil.ExternalOperation, req smqauthz.PolicyReq) error {
|
||||
perm, err := am.extOpp.GetPermission(extOp)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user