diff --git a/internal/rules/interfaces.go b/internal/rules/interfaces.go index 15d3cbddc..e9fba3a4e 100644 --- a/internal/rules/interfaces.go +++ b/internal/rules/interfaces.go @@ -9,7 +9,7 @@ import ( type ResourcesInterface interface { With(ctx context.Context, db *factory.DB) ResourcesInterface - IsAllowed(resource string, operation string) Access + Check(resource string, operation string) Access Grant(roleID uint64, rules []Rule) error Read(roleID uint64) ([]Rule, error) diff --git a/internal/rules/resources.go b/internal/rules/resources.go index 267439d88..9269070ef 100644 --- a/internal/rules/resources.go +++ b/internal/rules/resources.go @@ -35,7 +35,7 @@ func (r *resources) identity() uint64 { // IsAllowed function checks granted permission for specific resource and operation. Permission checks on // global level are not allowed and will always return Deny. -func (r *resources) IsAllowed(resource string, operation string) Access { +func (r *resources) Check(resource string, operation string) Access { parts := strings.Split(resource, delimiter) // Permission check on global level is not allowed. diff --git a/internal/rules/resources_test.go b/internal/rules/resources_test.go index e3875b34b..69b4505c6 100644 --- a/internal/rules/resources_test.go +++ b/internal/rules/resources_test.go @@ -40,8 +40,8 @@ func TestRules(t *testing.T) { // default (unset=deny), forbidden check ...:* { - Expect(rules.Inherit, resources.IsAllowed("messaging:channel:1", "update"), "messaging:channel:1 update - Inherit") - Expect(rules.Deny, resources.IsAllowed("messaging:channel:*", "update"), "messaging:channel:* update - Deny") + Expect(rules.Inherit, resources.Check("messaging:channel:1", "update"), "messaging:channel:1 update - Inherit") + Expect(rules.Deny, resources.Check("messaging:channel:*", "update"), "messaging:channel:* update - Deny") } // allow messaging:channel:2 update,delete @@ -53,9 +53,9 @@ func TestRules(t *testing.T) { err := resources.Grant(roleID, list) NoError(t, err, "expect no error") - Expect(rules.Inherit, resources.IsAllowed("messaging:channel:1", "update"), "messaging:channel:1 update - Inherit") - Expect(rules.Allow, resources.IsAllowed("messaging:channel:2", "update"), "messaging:channel:2 update - Allow") - Expect(rules.Deny, resources.IsAllowed("messaging:channel:*", "update"), "messaging:channel:* update - Deny") + Expect(rules.Inherit, resources.Check("messaging:channel:1", "update"), "messaging:channel:1 update - Inherit") + Expect(rules.Allow, resources.Check("messaging:channel:2", "update"), "messaging:channel:2 update - Allow") + Expect(rules.Deny, resources.Check("messaging:channel:*", "update"), "messaging:channel:* update - Deny") } // list grants for test role @@ -79,9 +79,9 @@ func TestRules(t *testing.T) { err := resources.Grant(roleID, list) NoError(t, err, "expect no error") - Expect(rules.Deny, resources.IsAllowed("messaging:channel:1", "update"), "messaging:channel:1 update - Deny") - Expect(rules.Allow, resources.IsAllowed("messaging:channel:2", "update"), "messaging:channel:2 update - Allow") - Expect(rules.Deny, resources.IsAllowed("messaging:channel:*", "update"), "messaging:channel:* update - Deny") + Expect(rules.Deny, resources.Check("messaging:channel:1", "update"), "messaging:channel:1 update - Deny") + Expect(rules.Allow, resources.Check("messaging:channel:2", "update"), "messaging:channel:2 update - Allow") + Expect(rules.Deny, resources.Check("messaging:channel:*", "update"), "messaging:channel:* update - Deny") } // reset messaging:channel:1, messaging:channel:2 @@ -95,8 +95,8 @@ func TestRules(t *testing.T) { err := resources.Grant(roleID, list) NoError(t, err, "expect no error") - Expect(rules.Inherit, resources.IsAllowed("messaging:channel:1", "update"), "messaging:channel:1 update - Inherit") - Expect(rules.Inherit, resources.IsAllowed("messaging:channel:2", "update"), "messaging:channel:2 update - Inherit") + Expect(rules.Inherit, resources.Check("messaging:channel:1", "update"), "messaging:channel:1 update - Inherit") + Expect(rules.Inherit, resources.Check("messaging:channel:2", "update"), "messaging:channel:2 update - Inherit") } // [messaging:channel:*,update] - allow, [messaging:channel:1, deny] @@ -110,8 +110,8 @@ func TestRules(t *testing.T) { err := resources.Grant(roleID, list) NoError(t, err, "expected no error") - Expect(rules.Deny, resources.IsAllowed("messaging:channel:1", "update"), "messaging:channel:1 update - Deny") - Expect(rules.Allow, resources.IsAllowed("messaging:channel:2", "update"), "messaging:channel:2 update - Allow") + Expect(rules.Deny, resources.Check("messaging:channel:1", "update"), "messaging:channel:1 update - Deny") + Expect(rules.Allow, resources.Check("messaging:channel:2", "update"), "messaging:channel:2 update - Allow") } // list all by roleID diff --git a/messaging/rest/router.go b/messaging/rest/router.go index 10953ef28..b77728c2d 100644 --- a/messaging/rest/router.go +++ b/messaging/rest/router.go @@ -8,7 +8,7 @@ import ( ) func MountRoutes() func(chi.Router) { - // Initialize handers & controllers. + // Initialize handlers & controllers. return func(r chi.Router) { r.Group(func(r chi.Router) { r.Use(auth.MiddlewareValidOnly404) diff --git a/messaging/service/channel.go b/messaging/service/channel.go index 2720ff2f8..8eb39f099 100644 --- a/messaging/service/channel.go +++ b/messaging/service/channel.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/crusttech/crust/internal/auth" + "github.com/crusttech/crust/internal/organization" "github.com/crusttech/crust/messaging/repository" "github.com/crusttech/crust/messaging/types" systemService "github.com/crusttech/crust/system/service" @@ -19,7 +20,9 @@ type ( ctx context.Context usr systemService.UserService + evl EventService + prm PermissionsService channel repository.ChannelRepository cmember repository.ChannelMemberRepository @@ -52,10 +55,11 @@ type ( Undelete(ID uint64) (*types.Channel, error) RecordView(userID, channelID, lastMessageID uint64) error } +) - // channelSecurity interface { - // CanRead(ch *types.Channel) bool - // } +var ( + ErrUnknownChannelType = errors.New("Unknown ChannelType") + ErrNoPermission = errors.New("No permissions") ) const ( @@ -67,6 +71,7 @@ func Channel() ChannelService { return (&channel{ usr: systemService.DefaultUser, evl: DefaultEvent, + prm: DefaultPermissions, }).With(context.Background()) } @@ -78,6 +83,7 @@ func (svc *channel) With(ctx context.Context) ChannelService { usr: svc.usr.With(ctx), evl: svc.evl.With(ctx), + prm: svc.prm.With(ctx), channel: repository.Channel(ctx, db), cmember: repository.ChannelMember(ctx, db), @@ -197,13 +203,10 @@ func (svc *channel) FindMembers(channelID uint64) (out types.ChannelMemberSet, e } func (svc *channel) Create(in *types.Channel) (out *types.Channel, err error) { - // @todo: [SECURITY] permission check if user can add channel - return out, svc.db.Transaction(func() (err error) { var msg *types.Message - // @todo get organisation from somewhere - var organisationID uint64 = 0 + var organisationID = organization.Crust().ID var chCreatorID = repository.Identity(svc.ctx) @@ -220,23 +223,19 @@ func (svc *channel) Create(in *types.Channel) (out *types.Channel, err error) { } } - // @todo [SECURITY] check if channel topic can be set - if in.Topic != "" && false { + if in.Topic != "" && svc.prm.CanUpdate(in) { return errors.New("Not allowed to set channel topic") } - // @todo [SECURITY] check if user can create public channels - if in.Type == types.ChannelTypePublic && false { + if in.Type == types.ChannelTypePublic && svc.prm.CanCreatePublicChannel() { return errors.New("Not allowed to create public channels") } - // @todo [SECURITY] check if user can create private channels - if in.Type == types.ChannelTypePrivate && false { - return errors.New("Not allowed to create public channels") + if in.Type == types.ChannelTypePrivate && svc.prm.CanCreatePrivateChannel() { + return errors.New("Not allowed to create private channels") } - // @todo [SECURITY] check if user can create private channels - if in.Type == types.ChannelTypeGroup && false { + if in.Type == types.ChannelTypeGroup && svc.prm.CanCreateDirectChannel() { return errors.New("Not allowed to create group channels") } diff --git a/messaging/service/permissions.go b/messaging/service/permissions.go new file mode 100644 index 000000000..a775ef63f --- /dev/null +++ b/messaging/service/permissions.go @@ -0,0 +1,158 @@ +package service + +import ( + "context" + + internalRules "github.com/crusttech/crust/internal/rules" + "github.com/crusttech/crust/messaging/repository" + "github.com/crusttech/crust/messaging/types" + systemService "github.com/crusttech/crust/system/service" +) + +type ( + permissions struct { + db db + ctx context.Context + + prm systemService.PermissionsService + } + + // Fallback option + Fallback func() bool + + PermissionsService interface { + With(context.Context) PermissionsService + + CanAccessMessaging() bool + CanGrantMessaging() bool + CanCreatePublicChannel() bool + CanCreatePrivateChannel() bool + CanCreateDirectChannel() bool + + CanUpdate(ch *types.Channel) bool + CanRead(ch *types.Channel) bool + CanJoin(ch *types.Channel) bool + CanLeave(ch *types.Channel) bool + + CanManageMembers(ch *types.Channel) bool + CanManageWebhooks(ch *types.Channel) bool + CanManageAttachments(ch *types.Channel) bool + + CanSendMessage(ch *types.Channel) bool + CanReplyMessage(ch *types.Channel) bool + CanEmbedMessage(ch *types.Channel) bool + CanAttachMessage(ch *types.Channel) bool + CanUpdateOwnMessages(ch *types.Channel) bool + CanUpdateMessages(ch *types.Channel) bool + CanReactMessage(ch *types.Channel) bool + } +) + +func Permissions() PermissionsService { + return (&permissions{ + prm: systemService.Permissions(), + }).With(context.Background()) +} + +func (p *permissions) With(ctx context.Context) PermissionsService { + db := repository.DB(ctx) + return &permissions{ + db: db, + ctx: ctx, + + prm: p.prm.With(ctx), + } +} + +func (p *permissions) CanAccessMessaging() bool { + return p.checkAccess("messaging", "access") +} + +func (p *permissions) CanGrantMessaging() bool { + return p.checkAccess("messaging", "grant") +} + +func (p *permissions) CanCreatePublicChannel() bool { + return p.checkAccess("messaging", "channel.public.create") +} + +func (p *permissions) CanCreatePrivateChannel() bool { + return p.checkAccess("messaging", "channel.private.create") +} + +func (p *permissions) CanCreateDirectChannel() bool { + return p.checkAccess("messaging", "channel.direct.create") +} + +func (p *permissions) CanUpdate(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "update") +} + +func (p *permissions) CanRead(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "read") +} + +func (p *permissions) CanJoin(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "join") +} + +func (p *permissions) CanLeave(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "leave") +} + +func (p *permissions) CanManageMembers(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "members.manage") +} + +func (p *permissions) CanManageWebhooks(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "webhooks.manage") +} + +func (p *permissions) CanManageAttachments(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "attachments.manage") +} + +func (p *permissions) CanSendMessage(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.send") +} + +func (p *permissions) CanReplyMessage(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.reply") +} + +func (p *permissions) CanEmbedMessage(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.embed") +} + +func (p *permissions) CanAttachMessage(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.attach") +} + +func (p *permissions) CanUpdateOwnMessages(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.update.own") +} + +func (p *permissions) CanUpdateMessages(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.update.all") +} + +func (p *permissions) CanReactMessage(ch *types.Channel) bool { + return p.checkAccess(ch.Resource().String(), "message.react") +} + +func (p *permissions) checkAccess(resource string, operation string, fbs ...Fallback) bool { + access := p.prm.Check(resource, operation) + switch access { + case internalRules.Allow: + return true + case internalRules.Deny: + return false + default: + for _, fb := range fbs { + if fb() == true { + return true + } + } + return false + } +} diff --git a/messaging/service/permissions_test.go b/messaging/service/permissions_test.go new file mode 100644 index 000000000..ac53cc9e0 --- /dev/null +++ b/messaging/service/permissions_test.go @@ -0,0 +1,115 @@ +package service + +import ( + "context" + "testing" + + "github.com/crusttech/crust/internal/auth" + "github.com/crusttech/crust/internal/rules" + . "github.com/crusttech/crust/internal/test" + "github.com/crusttech/crust/messaging/types" + systemService "github.com/crusttech/crust/system/service" + systemTypes "github.com/crusttech/crust/system/types" +) + +func TestPermissions(t *testing.T) { + ctx := context.TODO() + + // Create user with role and add it to context. + userSvc := systemService.User().With(ctx) + user := &systemTypes.User{ + Name: "John Doe", + Username: "johndoe", + SatosaID: "1234", + } + err := user.GeneratePassword("johndoe") + NoError(t, err, "expected no error generating password, got %v", err) + + _, err = userSvc.Create(user) + NoError(t, err, "expected no error creating user, got %v", err) + + roleSvc := systemService.Role().With(ctx) + role := &systemTypes.Role{ + Name: "Test role v1", + } + role, err = roleSvc.Create(role) + NoError(t, err, "expected no error creating role, got %v", err) + + err = roleSvc.MemberAdd(role.ID, user.ID) + NoError(t, err, "expected no error adding user to role, got %v", err) + + // Set Identity. + ctx = auth.SetIdentityToContext(ctx, user) + + // Generate services. + channelSvc := Channel().With(ctx) + permissionsSvc := Permissions().With(ctx) + systemPermissionSvc := systemService.Permissions().With(ctx) + + // Test `access` to messaging service. + ret := permissionsSvc.CanAccessMessaging() + Assert(t, ret == false, "expected CanAccessMessaging == false, got %v", ret) + + // Add `access` to messaging service. + list := []rules.Rule{ + rules.Rule{Resource: "messaging", Operation: "access", Value: rules.Allow}, + } + _, err = systemPermissionSvc.Update(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + + // Test `access` to messaging service. + ret = permissionsSvc.CanAccessMessaging() + Assert(t, ret == true, "expected CanAccessMessaging == true, got %v", ret) + + // Create test channel. + ch := &types.Channel{ + Name: "TestChan", + Topic: "No topic", + } + ch, err = channelSvc.Create(ch) + NoError(t, err, "expected no error, got %v", err) + + // @Todo: add permission for create channel and test it. + + // Test CanRead permissions. [1 - no permission, 2 - allow] + { + ret = permissionsSvc.CanRead(ch) + Assert(t, ret == false, "expected CanRead == false, got %v") + + // Add [messaging:channel:*, read, allow] + list = []rules.Rule{ + rules.Rule{Resource: "messaging:channel:*", Operation: "read", Value: rules.Allow}, + } + _, err = systemPermissionSvc.Update(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + + ret = permissionsSvc.CanRead(ch) + Assert(t, ret == true, "expected CanRead == true, got %v") + } + + // Test CanJoin permissions [1 - deny, 2 - allow for resourceID] + { + // Add [messaging:channel:*, join, deny] + list = []rules.Rule{ + rules.Rule{Resource: "messaging:channel:*", Operation: "join", Value: rules.Deny}, + } + _, err = systemPermissionSvc.Update(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + + ret = permissionsSvc.CanJoin(ch) + Assert(t, ret == false, "expected CanJoin == false, got %v") + + // Add [messaging:channel:ID, join, allow] + list = []rules.Rule{ + rules.Rule{Resource: ch.Resource().String(), Operation: "join", Value: rules.Allow}, + } + _, err = systemPermissionSvc.Update(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + + ret = permissionsSvc.CanJoin(ch) + Assert(t, ret == true, "expected CanJoin == true, got %v") + } + + // Remove test channel. + channelSvc.Delete(ch.ID) +} diff --git a/messaging/service/rules.go b/messaging/service/rules.go deleted file mode 100644 index 9a0cd40aa..000000000 --- a/messaging/service/rules.go +++ /dev/null @@ -1,143 +0,0 @@ -package service - -import ( - "context" - - internalRules "github.com/crusttech/crust/internal/rules" - "github.com/crusttech/crust/messaging/repository" - "github.com/crusttech/crust/messaging/types" - systemTypes "github.com/crusttech/crust/system/types" -) - -type ( - rules struct { - db db - ctx context.Context - - // identity is passed with context - resources internalRules.ResourcesInterface - role *systemTypes.Role - org *types.Organisation - } - - RulesService interface { - With(context.Context) RulesService - - // Applies mostly to admin panel - isAdmin() bool - - // Individual rules for administration - canManageOrganisation() bool - canManageRoles() bool - canManageChannels() bool - - canManageWebhooks(ch *types.Channel) bool - - // Messaging rules - canSendMessages(ch *types.Channel) bool - canEmbedLinks(ch *types.Channel) bool - canAttachFiles(ch *types.Channel) bool - canUpdateOwnMessages(ch *types.Channel) bool - canUpdateMessages(ch *types.Channel) bool - canReact(ch *types.Channel) bool - } -) - -func Rules() RulesService { - return (&rules{ - role: &systemTypes.Role{}, - }).With(context.Background()) -} - -func (r *rules) With(ctx context.Context) RulesService { - db := repository.DB(ctx) - org := repository.Organization(ctx) - return &rules{ - db: db, - ctx: ctx, - org: org, - role: r.role, - - resources: internalRules.NewResources(ctx, db), - } -} - -// @todo: honor defaults from (org/team/channel).Permissions() - -func (r *rules) isAdmin() bool { - op := "admin" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String()) -} - -func (r *rules) canManageOrganisation() bool { - op := "manage.organisation" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String()) -} - -func (r *rules) canManageRoles() bool { - op := "manage.roles" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String()) -} - -func (r *rules) canManageChannels() bool { - op := "manage.channels" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String()) -} - -func (r *rules) canManageWebhooks(ch *types.Channel) bool { - op := "manage.webhooks" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) canSendMessages(ch *types.Channel) bool { - op := "message.send" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) canEmbedLinks(ch *types.Channel) bool { - op := "message.embed" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) canAttachFiles(ch *types.Channel) bool { - op := "message.attach" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) canUpdateOwnMessages(ch *types.Channel) bool { - op := "message.update_own" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) canUpdateMessages(ch *types.Channel) bool { - op := "message.update_all" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) canReact(ch *types.Channel) bool { - op := "message.react" - return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.role.Resource().All(), ch.Resource().String()) -} - -func (r *rules) hasAccess(operation string, value internalRules.Access, scopes ...string) bool { - // reverse scopes from to order it from most-least significant - // aka: [0]channel [1]teams [2]org - last := len(scopes) - 1 - for i := 0; i < len(scopes)/2; i++ { - scopes[i], scopes[last-i] = scopes[last-i], scopes[i] - } - - for _, scope := range scopes { - if scope == "" { - continue - } - switch r.resources.IsAllowed(scope, operation) { - case internalRules.Allow: - return true - case internalRules.Deny: - return false - default: // inherit - } - } - return false -} diff --git a/messaging/service/service.go b/messaging/service/service.go index afb19b9b9..d60165fc5 100644 --- a/messaging/service/service.go +++ b/messaging/service/service.go @@ -5,10 +5,7 @@ import ( "sync" "time" - internalRules "github.com/crusttech/crust/internal/rules" "github.com/crusttech/crust/internal/store" - - "github.com/crusttech/crust/messaging/types" ) type ( @@ -18,12 +15,13 @@ type ( ) var ( - o sync.Once - DefaultAttachment AttachmentService - DefaultChannel ChannelService - DefaultMessage MessageService - DefaultPubSub *pubSub - DefaultEvent EventService + o sync.Once + DefaultAttachment AttachmentService + DefaultChannel ChannelService + DefaultMessage MessageService + DefaultPubSub *pubSub + DefaultEvent EventService + DefaultPermissions PermissionsService ) func Init() { @@ -33,11 +31,7 @@ func Init() { log.Fatalf("Failed to initialize stor: %v", err) } - scopes := internalRules.NewScope() - scopes.Add(&types.Organisation{}) - scopes.Add(&types.Role{}) - scopes.Add(&types.Channel{}) - + DefaultPermissions = Permissions() DefaultEvent = Event() DefaultAttachment = Attachment(fs) DefaultMessage = Message() diff --git a/messaging/types/channel.go b/messaging/types/channel.go index a21ec8509..b015b333d 100644 --- a/messaging/types/channel.go +++ b/messaging/types/channel.go @@ -58,7 +58,8 @@ type ( // Resource returns a system resource ID for this type func (r *Channel) Resource() rules.Resource { resource := rules.Resource{ - Scope: "channel", + Service: "messaging", + Scope: "channel", } if r != nil { resource.ID = r.ID diff --git a/system/rest/permissions.go b/system/rest/permissions.go index d9b6ce2a2..cdf84c6fc 100644 --- a/system/rest/permissions.go +++ b/system/rest/permissions.go @@ -21,7 +21,7 @@ type ( func (Permissions) New() *Permissions { ctrl := &Permissions{} - ctrl.svc.perm = service.DefaultPermission + ctrl.svc.perm = service.DefaultPermissions return ctrl } diff --git a/system/service/permissions.go b/system/service/permissions.go index 60f267c7d..2b0138c94 100644 --- a/system/service/permissions.go +++ b/system/service/permissions.go @@ -20,13 +20,16 @@ type ( With(ctx context.Context) PermissionsService List() (interface{}, error) + + Check(resource string, operation string) rules.Access + Read(roleID uint64) (interface{}, error) Update(roleID uint64, rules []rules.Rule) (interface{}, error) Delete(roleID uint64) (interface{}, error) } ) -func Permission() PermissionsService { +func Permissions() PermissionsService { return (&permissions{}).With(context.Background()) } @@ -50,6 +53,10 @@ func (p *permissions) List() (interface{}, error) { return perms, nil } +func (p *permissions) Check(resource string, operation string) rules.Access { + return p.resources.Check(resource, operation) +} + func (p *permissions) Read(roleID uint64) (interface{}, error) { return p.resources.Read(roleID) } diff --git a/system/service/permissions_test.go b/system/service/permissions_test.go index 648f5d62b..6389d14ba 100644 --- a/system/service/permissions_test.go +++ b/system/service/permissions_test.go @@ -48,7 +48,7 @@ func TestPermission(t *testing.T) { ctx = internalAuth.SetIdentityToContext(ctx, user) // Create permission service. - permissionSvc := Permission().With(ctx) + permissionSvc := Permissions().With(ctx) // Update rules for test role. { diff --git a/system/service/service.go b/system/service/service.go index abae3dacf..a8b34e8bd 100644 --- a/system/service/service.go +++ b/system/service/service.go @@ -15,7 +15,7 @@ var ( DefaultAuth AuthService DefaultUser UserService DefaultRole RoleService - DefaultPermission PermissionsService + DefaultPermissions PermissionsService DefaultOrganisation OrganisationService ) @@ -24,7 +24,7 @@ func Init() { DefaultAuth = Auth() DefaultUser = User() DefaultRole = Role() - DefaultPermission = Permission() + DefaultPermissions = Permissions() DefaultOrganisation = Organisation() }) } diff --git a/system/types/organisation.go b/system/types/organisation.go index 68fb973d3..a3b0b07db 100644 --- a/system/types/organisation.go +++ b/system/types/organisation.go @@ -26,7 +26,8 @@ type ( // Resource returns a system resource ID for this type func (r *Organisation) Resource() rules.Resource { resource := rules.Resource{ - Scope: "organisation", + Service: "system", + Scope: "organisation", } if r != nil { resource.ID = r.ID diff --git a/system/types/role.go b/system/types/role.go index 36de7d1fe..aa0fd5f04 100644 --- a/system/types/role.go +++ b/system/types/role.go @@ -26,7 +26,8 @@ type ( // Resource returns a system resource ID for this type func (r *Role) Resource() rules.Resource { resource := rules.Resource{ - Scope: "team", + Service: "system", + Scope: "role", } if r != nil { resource.ID = r.ID