upd(system): add Permissions API
This commit is contained in:
parent
cbfdb34db0
commit
8cc4551efc
2
Makefile
2
Makefile
@ -151,7 +151,7 @@ mocks: $(GOMOCK)
|
||||
$(MOCKGEN) -package service -source messaging/service/channel.go -destination messaging/service/channel_mock_test.go
|
||||
$(MOCKGEN) -package service -source messaging/service/message.go -destination messaging/service/message_mock_test.go
|
||||
$(MOCKGEN) -package service -source system/service/organisation.go -destination system/service/organisation_mock_test.go
|
||||
$(MOCKGEN) -package service -source system/service/team.go -destination system/service/team_mock_test.go
|
||||
$(MOCKGEN) -package service -source system/service/role.go -destination system/service/role_mock_test.go
|
||||
$(MOCKGEN) -package service -source system/service/user.go -destination system/service/user_mock_test.go
|
||||
|
||||
$(MOCKGEN) -package mail -source internal/mail/mail.go -destination internal/mail/mail_mock_test.go
|
||||
|
||||
@ -679,95 +679,5 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Permissions",
|
||||
"parameters": {},
|
||||
"entrypoint": "permissions",
|
||||
"path": "/permissions",
|
||||
"authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/crusttech/crust/internal/rules"
|
||||
]
|
||||
}
|
||||
],
|
||||
"apis": [
|
||||
{
|
||||
"name": "list",
|
||||
"path": "/",
|
||||
"method": "GET",
|
||||
"title": "List default permissions",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "get",
|
||||
"path": "/{teamID}",
|
||||
"method": "GET",
|
||||
"title": "Retrieve current permission settings",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"type": "uint64",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
}
|
||||
],
|
||||
"get": [
|
||||
{
|
||||
"name": "resource",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Permissions resource"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "set",
|
||||
"path": "/{teamID}",
|
||||
"method": "POST",
|
||||
"title": "Update permission settings",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"type": "uint64",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "permissions",
|
||||
"type": "[]rules.Rules",
|
||||
"required": true,
|
||||
"title": "List of rules to set"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "scopes",
|
||||
"path": "/scopes/{scope}",
|
||||
"method": "GET",
|
||||
"title": "List resources for given scope",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "scope",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Scope"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -160,10 +160,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Teams",
|
||||
"description": "An organisation may have many teams. Teams may have many channels available. Access to channels may be shared between teams.",
|
||||
"path": "/teams",
|
||||
"entrypoint": "team",
|
||||
"title": "Roles",
|
||||
"description": "An organisation may have many roles. Roles may have many channels available. Access to channels may be shared between roles.",
|
||||
"path": "/roles",
|
||||
"entrypoint": "role",
|
||||
"authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
@ -172,7 +172,7 @@
|
||||
{
|
||||
"name": "list",
|
||||
"method": "GET",
|
||||
"title": "List teams",
|
||||
"title": "List roles",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"get": [
|
||||
@ -188,7 +188,7 @@
|
||||
{
|
||||
"name": "create",
|
||||
"method": "POST",
|
||||
"title": "Update team details",
|
||||
"title": "Update role details",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"post": [
|
||||
@ -196,13 +196,13 @@
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"title": "Name of Team"
|
||||
"title": "Name of Role"
|
||||
},
|
||||
{
|
||||
"type": "[]uint64",
|
||||
"name": "members",
|
||||
"required": false,
|
||||
"title": "Team member IDs"
|
||||
"title": "Role member IDs"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -210,15 +210,15 @@
|
||||
{
|
||||
"name": "update",
|
||||
"method": "PUT",
|
||||
"title": "Update team details",
|
||||
"path": "/{teamID}",
|
||||
"title": "Update role details",
|
||||
"path": "/{roleID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
"title": "Role ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
@ -226,13 +226,13 @@
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"required": false,
|
||||
"title": "Name of Team"
|
||||
"title": "Name of Role"
|
||||
},
|
||||
{
|
||||
"type": "[]uint64",
|
||||
"name": "members",
|
||||
"required": false,
|
||||
"title": "Team member IDs"
|
||||
"title": "Role member IDs"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -240,15 +240,15 @@
|
||||
{
|
||||
"name": "read",
|
||||
"method": "GET",
|
||||
"title": "Read team details and memberships",
|
||||
"path": "/{teamID}",
|
||||
"title": "Read role details and memberships",
|
||||
"path": "/{roleID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
"title": "Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -256,15 +256,15 @@
|
||||
{
|
||||
"name": "remove",
|
||||
"method": "DELETE",
|
||||
"title": "Remove team",
|
||||
"path": "/{teamID}",
|
||||
"title": "Remove role",
|
||||
"path": "/{roleID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
"title": "Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -272,15 +272,15 @@
|
||||
{
|
||||
"name": "archive",
|
||||
"method": "POST",
|
||||
"title": "Archive team",
|
||||
"path": "/{teamID}/archive",
|
||||
"title": "Archive role",
|
||||
"path": "/{roleID}/archive",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
"title": "Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -288,15 +288,15 @@
|
||||
{
|
||||
"name": "move",
|
||||
"method": "POST",
|
||||
"title": "Move team to different organisation",
|
||||
"path": "/{teamID}/move",
|
||||
"title": "Move role to different organisation",
|
||||
"path": "/{roleID}/move",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
"title": "Role ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
@ -304,7 +304,7 @@
|
||||
"type": "uint64",
|
||||
"name": "organisationID",
|
||||
"required": true,
|
||||
"title": "Team ID"
|
||||
"title": "Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -312,15 +312,15 @@
|
||||
{
|
||||
"name": "merge",
|
||||
"method": "POST",
|
||||
"title": "Merge one team into another",
|
||||
"path": "/{teamID}/merge",
|
||||
"title": "Merge one role into another",
|
||||
"path": "/{roleID}/merge",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Source Team ID"
|
||||
"title": "Source Role ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
@ -328,7 +328,7 @@
|
||||
"type": "uint64",
|
||||
"name": "destination",
|
||||
"required": true,
|
||||
"title": "Destination Team ID"
|
||||
"title": "Destination Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -336,15 +336,15 @@
|
||||
{
|
||||
"name": "memberAdd",
|
||||
"method": "POST",
|
||||
"title": "Add member to a team",
|
||||
"path": "/{teamID}/memberAdd",
|
||||
"title": "Add member to a role",
|
||||
"path": "/{roleID}/memberAdd",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Source Team ID"
|
||||
"title": "Source Role ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
@ -360,15 +360,15 @@
|
||||
{
|
||||
"name": "memberRemove",
|
||||
"method": "POST",
|
||||
"title": "Remove member from a team",
|
||||
"path": "/{teamID}/memberRemove",
|
||||
"title": "Remove member from a role",
|
||||
"path": "/{roleID}/memberRemove",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Source Team ID"
|
||||
"title": "Source Role ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
@ -561,5 +561,80 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Permissions",
|
||||
"parameters": {},
|
||||
"entrypoint": "permissions",
|
||||
"path": "/permissions",
|
||||
"authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/crusttech/crust/internal/rules"
|
||||
]
|
||||
}
|
||||
],
|
||||
"apis": [
|
||||
{
|
||||
"name": "get",
|
||||
"path": "/{roleID}/rules",
|
||||
"method": "GET",
|
||||
"title": "Retrieve role permissions",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "roleID",
|
||||
"type": "uint64",
|
||||
"required": true,
|
||||
"title": "Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "delete",
|
||||
"path": "/{roleID}/rules",
|
||||
"method": "DELETE",
|
||||
"title": "Remove all defined role permissions",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "roleID",
|
||||
"type": "uint64",
|
||||
"required": true,
|
||||
"title": "Role ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "update",
|
||||
"path": "/{roleID}/rules",
|
||||
"method": "PATCH",
|
||||
"title": "Update permission settings",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "roleID",
|
||||
"type": "uint64",
|
||||
"required": true,
|
||||
"title": "Role ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "permissions",
|
||||
"type": "[]rules.Rule",
|
||||
"required": true,
|
||||
"title": "List of permissions to set"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -16,48 +16,49 @@
|
||||
],
|
||||
"Path": "/permissions",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "list",
|
||||
"Method": "GET",
|
||||
"Title": "List default permissions",
|
||||
"Path": "/",
|
||||
"Parameters": {}
|
||||
},
|
||||
{
|
||||
"Name": "get",
|
||||
"Method": "GET",
|
||||
"Title": "Retrieve current permission settings",
|
||||
"Path": "/{teamID}",
|
||||
"Title": "Retrieve role permissions",
|
||||
"Path": "/{roleID}/rules",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "resource",
|
||||
"required": true,
|
||||
"title": "Permissions resource",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "set",
|
||||
"Method": "POST",
|
||||
"Title": "Update permission settings",
|
||||
"Path": "/{teamID}",
|
||||
"Name": "delete",
|
||||
"Method": "DELETE",
|
||||
"Title": "Remove all defined role permissions",
|
||||
"Path": "/{roleID}/rules",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "update",
|
||||
"Method": "PATCH",
|
||||
"Title": "Update permission settings",
|
||||
"Path": "/{roleID}/rules",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
@ -65,24 +66,8 @@
|
||||
{
|
||||
"name": "permissions",
|
||||
"required": true,
|
||||
"title": "List of rules to set",
|
||||
"type": "[]rules.Rules"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "scopes",
|
||||
"Method": "GET",
|
||||
"Title": "List resources for given scope",
|
||||
"Path": "/scopes/{scope}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "scope",
|
||||
"required": true,
|
||||
"title": "Scope",
|
||||
"type": "string"
|
||||
"title": "List of permissions to set",
|
||||
"type": "[]rules.Rule"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"Title": "Teams",
|
||||
"Description": "An organisation may have many teams. Teams may have many channels available. Access to channels may be shared between teams.",
|
||||
"Interface": "Team",
|
||||
"Title": "Roles",
|
||||
"Description": "An organisation may have many roles. Roles may have many channels available. Access to channels may be shared between roles.",
|
||||
"Interface": "Role",
|
||||
"Struct": null,
|
||||
"Parameters": null,
|
||||
"Protocol": "",
|
||||
@ -9,12 +9,12 @@
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"Path": "/teams",
|
||||
"Path": "/roles",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "list",
|
||||
"Method": "GET",
|
||||
"Title": "List teams",
|
||||
"Title": "List roles",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
@ -30,20 +30,20 @@
|
||||
{
|
||||
"Name": "create",
|
||||
"Method": "POST",
|
||||
"Title": "Update team details",
|
||||
"Title": "Update role details",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"title": "Name of Team",
|
||||
"title": "Name of Role",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "members",
|
||||
"required": false,
|
||||
"title": "Team member IDs",
|
||||
"title": "Role member IDs",
|
||||
"type": "[]uint64"
|
||||
}
|
||||
]
|
||||
@ -52,14 +52,14 @@
|
||||
{
|
||||
"Name": "update",
|
||||
"Method": "PUT",
|
||||
"Title": "Update team details",
|
||||
"Path": "/{teamID}",
|
||||
"Title": "Update role details",
|
||||
"Path": "/{roleID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
@ -67,13 +67,13 @@
|
||||
{
|
||||
"name": "name",
|
||||
"required": false,
|
||||
"title": "Name of Team",
|
||||
"title": "Name of Role",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "members",
|
||||
"required": false,
|
||||
"title": "Team member IDs",
|
||||
"title": "Role member IDs",
|
||||
"type": "[]uint64"
|
||||
}
|
||||
]
|
||||
@ -82,14 +82,14 @@
|
||||
{
|
||||
"Name": "read",
|
||||
"Method": "GET",
|
||||
"Title": "Read team details and memberships",
|
||||
"Path": "/{teamID}",
|
||||
"Title": "Read role details and memberships",
|
||||
"Path": "/{roleID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
@ -98,14 +98,14 @@
|
||||
{
|
||||
"Name": "remove",
|
||||
"Method": "DELETE",
|
||||
"Title": "Remove team",
|
||||
"Path": "/{teamID}",
|
||||
"Title": "Remove role",
|
||||
"Path": "/{roleID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
@ -114,14 +114,14 @@
|
||||
{
|
||||
"Name": "archive",
|
||||
"Method": "POST",
|
||||
"Title": "Archive team",
|
||||
"Path": "/{teamID}/archive",
|
||||
"Title": "Archive role",
|
||||
"Path": "/{roleID}/archive",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
@ -130,14 +130,14 @@
|
||||
{
|
||||
"Name": "move",
|
||||
"Method": "POST",
|
||||
"Title": "Move team to different organisation",
|
||||
"Path": "/{teamID}/move",
|
||||
"Title": "Move role to different organisation",
|
||||
"Path": "/{roleID}/move",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
@ -145,7 +145,7 @@
|
||||
{
|
||||
"name": "organisationID",
|
||||
"required": true,
|
||||
"title": "Team ID",
|
||||
"title": "Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
@ -154,14 +154,14 @@
|
||||
{
|
||||
"Name": "merge",
|
||||
"Method": "POST",
|
||||
"Title": "Merge one team into another",
|
||||
"Path": "/{teamID}/merge",
|
||||
"Title": "Merge one role into another",
|
||||
"Path": "/{roleID}/merge",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Source Team ID",
|
||||
"title": "Source Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
@ -169,7 +169,7 @@
|
||||
{
|
||||
"name": "destination",
|
||||
"required": true,
|
||||
"title": "Destination Team ID",
|
||||
"title": "Destination Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
@ -178,14 +178,14 @@
|
||||
{
|
||||
"Name": "memberAdd",
|
||||
"Method": "POST",
|
||||
"Title": "Add member to a team",
|
||||
"Path": "/{teamID}/memberAdd",
|
||||
"Title": "Add member to a role",
|
||||
"Path": "/{roleID}/memberAdd",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Source Team ID",
|
||||
"title": "Source Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
@ -202,14 +202,14 @@
|
||||
{
|
||||
"Name": "memberRemove",
|
||||
"Method": "POST",
|
||||
"Title": "Remove member from a team",
|
||||
"Path": "/{teamID}/memberRemove",
|
||||
"Title": "Remove member from a role",
|
||||
"Path": "/{roleID}/memberRemove",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "teamID",
|
||||
"name": "roleID",
|
||||
"required": true,
|
||||
"title": "Source Team ID",
|
||||
"title": "Source Role ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
@ -23,7 +23,7 @@ function permissions {
|
||||
fi
|
||||
|
||||
./build/gen-permissions -package types -object-name Organisation -input messaging/types/permissions/1-organisation.json -output messaging/types/organisation.perms.gen.go
|
||||
./build/gen-permissions -package types -object-name Team -input messaging/types/permissions/2-team.json -output messaging/types/team.perms.gen.go
|
||||
./build/gen-permissions -package types -object-name Role -input messaging/types/permissions/2-role.json -output messaging/types/role.perms.gen.go
|
||||
./build/gen-permissions -package types -object-name Channel -input messaging/types/permissions/3-channel.json -output messaging/types/channel.perms.gen.go
|
||||
|
||||
green "OK"
|
||||
@ -52,7 +52,7 @@ function types {
|
||||
./build/gen-type-set --with-primary-key=false --types Unread --output messaging/types/unread.gen.go
|
||||
|
||||
./build/gen-type-set --types User --output system/types/user.gen.go
|
||||
./build/gen-type-set --with-resources=true --resource-type "rules.Resource" --imports "github.com/crusttech/crust/internal/rules" --types Team --output system/types/team.gen.go
|
||||
./build/gen-type-set --with-resources=true --resource-type "rules.Resource" --imports "github.com/crusttech/crust/internal/rules" --types Role --output system/types/role.gen.go
|
||||
./build/gen-type-set --with-resources=true --resource-type "rules.Resource" --imports "github.com/crusttech/crust/internal/rules" --types Organisation --output system/types/organisation.gen.go
|
||||
./build/gen-type-set --types Credentials --output system/types/credentials.gen.go
|
||||
green "OK"
|
||||
|
||||
@ -17,7 +17,7 @@ foreach ($apis as $api) {
|
||||
$tpl->assign("name", $name);
|
||||
$tpl->assign("api", $api);
|
||||
$tpl->assign("apis", $apis);
|
||||
$tpl->assign("self", strtolower(substr($name, 0, 1)));
|
||||
$tpl->assign("self", strtolower(substr($name, 0, 2)));
|
||||
$tpl->assign("structs", $api['struct']);
|
||||
$imports = imports($api);
|
||||
$tpl->assign("imports", $imports);
|
||||
|
||||
@ -448,68 +448,6 @@ The following event types may be sent with a message event:
|
||||
|
||||
|
||||
|
||||
# Permissions
|
||||
|
||||
## List default permissions
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/permissions/` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
|
||||
## Retrieve current permission settings
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/permissions/{teamID}` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| resource | string | GET | Permissions resource | N/A | YES |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
|
||||
## Update permission settings
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/permissions/{teamID}` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
| permissions | []rules.Rules | POST | List of rules to set | N/A | YES |
|
||||
|
||||
## List resources for given scope
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/permissions/scopes/{scope}` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| scope | string | PATH | Scope | N/A | YES |
|
||||
|
||||
|
||||
|
||||
|
||||
# Search entry point
|
||||
|
||||
## Search for messages
|
||||
|
||||
@ -136,17 +136,65 @@ Organisations represent a top-level grouping entity. There may be many organisat
|
||||
|
||||
|
||||
|
||||
# Teams
|
||||
# Permissions
|
||||
|
||||
An organisation may have many teams. Teams may have many channels available. Access to channels may be shared between teams.
|
||||
|
||||
## List teams
|
||||
## Retrieve role permissions
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/` | HTTP/S | GET | Client ID, Session ID |
|
||||
| `/permissions/{roleID}/rules` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
|
||||
## Remove all defined role permissions
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/permissions/{roleID}/rules` | HTTP/S | DELETE | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
|
||||
## Update permission settings
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/permissions/{roleID}/rules` | HTTP/S | PATCH | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
| permissions | []rules.Rule | POST | List of permissions to set | N/A | YES |
|
||||
|
||||
|
||||
|
||||
|
||||
# Roles
|
||||
|
||||
An organisation may have many roles. Roles may have many channels available. Access to channels may be shared between roles.
|
||||
|
||||
## List roles
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/roles/` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
@ -154,137 +202,137 @@ An organisation may have many teams. Teams may have many channels available. Acc
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| query | string | GET | Search query | N/A | NO |
|
||||
|
||||
## Update team details
|
||||
## Update role details
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/` | HTTP/S | POST | Client ID, Session ID |
|
||||
| `/roles/` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| name | string | POST | Name of Team | N/A | YES |
|
||||
| members | []uint64 | POST | Team member IDs | N/A | NO |
|
||||
| name | string | POST | Name of Role | N/A | YES |
|
||||
| members | []uint64 | POST | Role member IDs | N/A | NO |
|
||||
|
||||
## Update team details
|
||||
## Update role details
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}` | HTTP/S | PUT | Client ID, Session ID |
|
||||
| `/roles/{roleID}` | HTTP/S | PUT | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
| name | string | POST | Name of Team | N/A | NO |
|
||||
| members | []uint64 | POST | Team member IDs | N/A | NO |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
| name | string | POST | Name of Role | N/A | NO |
|
||||
| members | []uint64 | POST | Role member IDs | N/A | NO |
|
||||
|
||||
## Read team details and memberships
|
||||
## Read role details and memberships
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}` | HTTP/S | GET | Client ID, Session ID |
|
||||
| `/roles/{roleID}` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
|
||||
## Remove team
|
||||
## Remove role
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}` | HTTP/S | DELETE | Client ID, Session ID |
|
||||
| `/roles/{roleID}` | HTTP/S | DELETE | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
|
||||
## Archive team
|
||||
## Archive role
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}/archive` | HTTP/S | POST | Client ID, Session ID |
|
||||
| `/roles/{roleID}/archive` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
|
||||
## Move team to different organisation
|
||||
## Move role to different organisation
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}/move` | HTTP/S | POST | Client ID, Session ID |
|
||||
| `/roles/{roleID}/move` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Team ID | N/A | YES |
|
||||
| organisationID | uint64 | POST | Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Role ID | N/A | YES |
|
||||
| organisationID | uint64 | POST | Role ID | N/A | YES |
|
||||
|
||||
## Merge one team into another
|
||||
## Merge one role into another
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}/merge` | HTTP/S | POST | Client ID, Session ID |
|
||||
| `/roles/{roleID}/merge` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Source Team ID | N/A | YES |
|
||||
| destination | uint64 | POST | Destination Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Source Role ID | N/A | YES |
|
||||
| destination | uint64 | POST | Destination Role ID | N/A | YES |
|
||||
|
||||
## Add member to a team
|
||||
## Add member to a role
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}/memberAdd` | HTTP/S | POST | Client ID, Session ID |
|
||||
| `/roles/{roleID}/memberAdd` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Source Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Source Role ID | N/A | YES |
|
||||
| userID | uint64 | POST | User ID | N/A | YES |
|
||||
|
||||
## Remove member from a team
|
||||
## Remove member from a role
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/teams/{teamID}/memberRemove` | HTTP/S | POST | Client ID, Session ID |
|
||||
| `/roles/{roleID}/memberRemove` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| teamID | uint64 | PATH | Source Team ID | N/A | YES |
|
||||
| roleID | uint64 | PATH | Source Role ID | N/A | YES |
|
||||
| userID | uint64 | POST | User ID | N/A | YES |
|
||||
|
||||
|
||||
|
||||
@ -11,6 +11,10 @@ type ResourcesInterface interface {
|
||||
|
||||
IsAllowed(resource string, operation string) Access
|
||||
|
||||
Grant(teamID uint64, resource string, operations []string, value Access) error
|
||||
ListGrants(teamID uint64, resource string) ([]Rules, error)
|
||||
GrantByResource(roleID uint64, resource string, operations []string, value Access) error
|
||||
ListByResource(roleID uint64, resource string) ([]Rule, error)
|
||||
|
||||
Grant(roleID uint64, rules []Rule) error
|
||||
List(roleID uint64) ([]Rule, error)
|
||||
Delete(roleID uint64) error
|
||||
}
|
||||
|
||||
@ -7,27 +7,29 @@ import (
|
||||
)
|
||||
|
||||
type Resource struct {
|
||||
ID uint64 `json:"id,string"`
|
||||
Name string `json:"name"`
|
||||
Scope string `json:"scope"`
|
||||
ID uint64 `json:"id,string"`
|
||||
Name string `json:"name"`
|
||||
Scope string `json:"scope"`
|
||||
Service string `json:"service"`
|
||||
}
|
||||
|
||||
type ResourceJSON struct {
|
||||
ID uint64 `json:"id,string"`
|
||||
Name string `json:"name"`
|
||||
Scope string `json:"scope"`
|
||||
Service string `json:"service"`
|
||||
ResourceID string `json:"resource"`
|
||||
}
|
||||
|
||||
func (r Resource) String() string {
|
||||
if r.ID > 0 {
|
||||
return fmt.Sprintf("%s:%d", r.Scope, r.ID)
|
||||
return fmt.Sprintf("%s:%s:%d", r.Service, r.Scope, r.ID)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r Resource) All() string {
|
||||
return fmt.Sprintf("%s:*", r.Scope)
|
||||
return fmt.Sprintf("%s:%s:*", r.Service, r.Scope)
|
||||
}
|
||||
|
||||
func (r Resource) MarshalJSON() ([]byte, error) {
|
||||
@ -35,6 +37,7 @@ func (r Resource) MarshalJSON() ([]byte, error) {
|
||||
r.ID,
|
||||
r.Name,
|
||||
r.Scope,
|
||||
r.Service,
|
||||
r.String(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ func TestResource(t *testing.T) {
|
||||
var (
|
||||
assert = test.Assert
|
||||
)
|
||||
r := Resource{123, "Test name", "team"}
|
||||
assert(t, r.String() == "team:123", "Resource ID doesn't match, team:123 != '%s'", r.String())
|
||||
r := Resource{123, "Test name", "channel", "messaging"}
|
||||
assert(t, r.String() == "messaging:channel:123", "Resource ID doesn't match, messaging:channel:123 != '%s'", r.String())
|
||||
|
||||
b, _ := json.Marshal(r)
|
||||
fmt.Println(string(b))
|
||||
@ -22,13 +22,13 @@ func TestResource(t *testing.T) {
|
||||
{
|
||||
r := ResourceJSON{}
|
||||
json.Unmarshal(b, &r)
|
||||
assert(t, r.ResourceID == "team:123", "Decoded full-json resource ID doesn't match, team:123 != '%s'", r.ResourceID)
|
||||
assert(t, r.ResourceID == "messaging:channel:123", "Decoded full-json resource ID doesn't match, messaging:channel:123 != '%s'", r.ResourceID)
|
||||
}
|
||||
|
||||
{
|
||||
r := Resource{}
|
||||
json.Unmarshal(b, &r)
|
||||
assert(t, r.String() == "team:123", "Decoded full-json resource ID doesn't match, team:123 != '%s'", r.String())
|
||||
assert(t, r.String() == "messaging:channel:123", "Decoded full-json resource ID doesn't match, messaging:channel:123 != '%s'", r.String())
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@ -43,7 +43,7 @@ func (r *resources) checkAccessMulti(resource string, operation string) Access {
|
||||
// select rules
|
||||
"select r.value from sys_rules r",
|
||||
// join members
|
||||
"inner join sys_team_member m on (m.rel_team = r.rel_team and m.rel_user=?)",
|
||||
"inner join sys_role_member m on (m.rel_role = r.rel_role and m.rel_user=?)",
|
||||
// add conditions
|
||||
"where r.resource LIKE ? and r.operation=?",
|
||||
}
|
||||
@ -75,7 +75,7 @@ func (r *resources) checkAccess(resource string, operation string) Access {
|
||||
// select rules
|
||||
"select r.value from sys_rules r",
|
||||
// join members
|
||||
"inner join sys_team_member m on (m.rel_team = r.rel_team and m.rel_user=?)",
|
||||
"inner join sys_role_member m on (m.rel_role = r.rel_role and m.rel_user=?)",
|
||||
// add conditions
|
||||
"where r.resource=? and r.operation=?",
|
||||
}
|
||||
@ -99,35 +99,75 @@ func (r *resources) checkAccess(resource string, operation string) Access {
|
||||
return Inherit
|
||||
}
|
||||
|
||||
func (r *resources) Grant(teamID uint64, resource string, operations []string, value Access) error {
|
||||
row := Rules{
|
||||
TeamID: teamID,
|
||||
Resource: resource,
|
||||
Value: value,
|
||||
}
|
||||
func (r *resources) GrantByResource(roleID uint64, resource string, operations []string, value Access) error {
|
||||
return r.db.Transaction(func() error {
|
||||
row := Rule{
|
||||
RoleID: roleID,
|
||||
Resource: resource,
|
||||
Value: value,
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, operation := range operations {
|
||||
row.Operation = operation
|
||||
switch value {
|
||||
case Inherit:
|
||||
_, err = r.db.NamedExec("delete from sys_rules where rel_team=:rel_team and resource=:resource and operation=:operation", row)
|
||||
default:
|
||||
err = r.db.Replace("sys_rules", row)
|
||||
var err error
|
||||
for _, operation := range operations {
|
||||
row.Operation = operation
|
||||
switch value {
|
||||
case Inherit:
|
||||
_, err = r.db.NamedExec("delete from sys_rules where rel_role=:rel_role and resource=:resource and operation=:operation", row)
|
||||
default:
|
||||
err = r.db.Replace("sys_rules", row)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *resources) ListGrants(teamID uint64, resource string) ([]Rules, error) {
|
||||
result := []Rules{}
|
||||
func (r *resources) ListByResource(roleID uint64, resource string) ([]Rule, error) {
|
||||
result := []Rule{}
|
||||
|
||||
query := "select * from sys_rules where rel_team = ? and resource = ?"
|
||||
if err := r.db.Select(&result, query, teamID, resource); err != nil {
|
||||
query := "select * from sys_rules where rel_role = ? and resource = ?"
|
||||
if err := r.db.Select(&result, query, roleID, resource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *resources) Grant(roleID uint64, rules []Rule) error {
|
||||
return r.db.Transaction(func() error {
|
||||
var err error
|
||||
for _, rule := range rules {
|
||||
rule.RoleID = roleID
|
||||
|
||||
switch rule.Value {
|
||||
case Inherit:
|
||||
_, err = r.db.NamedExec("delete from sys_rules where rel_role=:rel_role and resource=:resource and operation=:operation", rule)
|
||||
default:
|
||||
err = r.db.Replace("sys_rules", rule)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *resources) List(roleID uint64) ([]Rule, error) {
|
||||
result := []Rule{}
|
||||
|
||||
query := "select * from sys_rules where rel_role = ?"
|
||||
if err := r.db.Select(&result, query, roleID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *resources) Delete(roleID uint64) error {
|
||||
query := "delete from sys_rules where rel_role = ?"
|
||||
if _, err := r.db.Exec(query, roleID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package rules_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
@ -21,62 +20,101 @@ func TestRules(t *testing.T) {
|
||||
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
Error(t, db.Transaction(func() error {
|
||||
db.Insert("sys_user", user)
|
||||
var i uint64 = 0
|
||||
for i < 5 {
|
||||
db.Insert("sys_team", types.Team{ID: i, Name: fmt.Sprintf("Team %d", i)})
|
||||
i++
|
||||
}
|
||||
db.Insert("sys_team_member", types.TeamMember{TeamID: 1, UserID: user.ID})
|
||||
db.Insert("sys_team_member", types.TeamMember{TeamID: 2, UserID: user.ID})
|
||||
db.Insert("sys_user", user)
|
||||
var i uint64 = 0
|
||||
for i < 5 {
|
||||
db.Insert("sys_role", types.Role{ID: i, Name: fmt.Sprintf("Role %d", i)})
|
||||
i++
|
||||
}
|
||||
db.Insert("sys_role_member", types.RoleMember{RoleID: 1, UserID: user.ID})
|
||||
db.Insert("sys_role_member", types.RoleMember{RoleID: 2, UserID: user.ID})
|
||||
|
||||
Expect := func(expected rules.Access, actual rules.Access, format string, params ...interface{}) {
|
||||
Assert(t, expected == actual, format, params...)
|
||||
}
|
||||
Expect := func(expected rules.Access, actual rules.Access, format string, params ...interface{}) {
|
||||
Assert(t, expected == actual, format, params...)
|
||||
}
|
||||
|
||||
resources := rules.NewResources(ctx, db)
|
||||
resources := rules.NewResources(ctx, db)
|
||||
|
||||
// default (unset=deny)
|
||||
{
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:1", "edit"), "expected inherit")
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:*", "edit"), "expected inherit")
|
||||
}
|
||||
// default (unset=deny)
|
||||
{
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:1", "edit"), "expected inherit")
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:*", "edit"), "expected inherit")
|
||||
}
|
||||
|
||||
// allow channel:2 group:2 (default deny, multi=allow)
|
||||
{
|
||||
resources.Grant(2, "channel:2", []string{"edit", "delete"}, rules.Allow)
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:1", "edit"), "expected error, got nil")
|
||||
Expect(rules.Allow, resources.IsAllowed("channel:2", "edit"), "channel:2 edit, expected no error")
|
||||
Expect(rules.Allow, resources.IsAllowed("channel:*", "edit"), "channel:* edit, expected no error")
|
||||
}
|
||||
// allow channel:2 group:2 (default deny, multi=allow)
|
||||
{
|
||||
resources.GrantByResource(2, "channel:2", []string{"edit", "delete"}, rules.Allow)
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:1", "edit"), "expected error, got nil")
|
||||
Expect(rules.Allow, resources.IsAllowed("channel:2", "edit"), "channel:2 edit, expected no error")
|
||||
Expect(rules.Allow, resources.IsAllowed("channel:*", "edit"), "channel:* edit, expected no error")
|
||||
}
|
||||
|
||||
// list grants for team
|
||||
{
|
||||
grants, err := resources.ListGrants(2, "channel:2")
|
||||
NoError(t, err, "expect no error")
|
||||
Assert(t, len(grants) == 2, "expected 2 grants")
|
||||
Assert(t, grants[0].TeamID == 2, "expected TeamID == 2, got %v", grants[0].TeamID)
|
||||
Assert(t, grants[0].Resource == "channel:2", "expected Resource == channel:2, got %s", grants[0].Resource)
|
||||
Assert(t, grants[0].Operation == "delete", "expected Operation == delete, got %s", grants[0].Operation)
|
||||
Assert(t, grants[0].Value == rules.Allow, "expected Value == Allow, got %s", grants[0].Value)
|
||||
}
|
||||
// list grants for role
|
||||
{
|
||||
grants, err := resources.ListByResource(2, "channel:2")
|
||||
NoError(t, err, "expect no error")
|
||||
Assert(t, len(grants) == 2, "expected 2 grants")
|
||||
Assert(t, grants[0].RoleID == 2, "expected RoleID == 2, got %v", grants[0].RoleID)
|
||||
Assert(t, grants[0].Resource == "channel:2", "expected Resource == channel:2, got %s", grants[0].Resource)
|
||||
Assert(t, grants[0].Operation == "delete", "expected Operation == delete, got %s", grants[0].Operation)
|
||||
Assert(t, grants[0].Value == rules.Allow, "expected Value == Allow, got %s", grants[0].Value)
|
||||
}
|
||||
|
||||
// deny channel:1 group:1 (explicit deny, multi=deny)
|
||||
{
|
||||
resources.Grant(1, "channel:1", []string{"edit"}, rules.Deny)
|
||||
Expect(rules.Deny, resources.IsAllowed("channel:1", "edit"), "expected error, got nil")
|
||||
Expect(rules.Allow, resources.IsAllowed("channel:2", "edit"), "channel:2 edit, expected no error")
|
||||
Expect(rules.Deny, resources.IsAllowed("channel:*", "edit"), "expected error, got nil")
|
||||
}
|
||||
// list all by role
|
||||
{
|
||||
grants, err := resources.List(2)
|
||||
NoError(t, err, "expected no error")
|
||||
Assert(t, len(grants) == 2, "expected grants == 2, got %v", len(grants))
|
||||
}
|
||||
|
||||
// reset (unset=deny)
|
||||
{
|
||||
resources.Grant(2, "channel:2", []string{"edit", "delete"}, rules.Inherit)
|
||||
resources.Grant(1, "channel:1", []string{"edit", "delete"}, rules.Inherit)
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:1", "edit"), "expected error, got nil")
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:*", "edit"), "expected error, got nil")
|
||||
// deny channel:1 group:1 (explicit deny, multi=deny)
|
||||
{
|
||||
resources.GrantByResource(1, "channel:1", []string{"edit"}, rules.Deny)
|
||||
Expect(rules.Deny, resources.IsAllowed("channel:1", "edit"), "expected error, got nil")
|
||||
Expect(rules.Allow, resources.IsAllowed("channel:2", "edit"), "channel:2 edit, expected no error")
|
||||
Expect(rules.Deny, resources.IsAllowed("channel:*", "edit"), "expected error, got nil")
|
||||
}
|
||||
|
||||
// reset (unset=deny)
|
||||
{
|
||||
resources.GrantByResource(2, "channel:2", []string{"edit", "delete"}, rules.Inherit)
|
||||
resources.GrantByResource(1, "channel:1", []string{"edit", "delete"}, rules.Inherit)
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:1", "edit"), "expected error, got nil")
|
||||
Expect(rules.Inherit, resources.IsAllowed("channel:*", "edit"), "expected error, got nil")
|
||||
}
|
||||
|
||||
// Grant by roleID
|
||||
{
|
||||
list := []rules.Rule{
|
||||
rules.Rule{Resource: "channel:*", Operation: "update", Value: rules.Allow},
|
||||
rules.Rule{Resource: "channel:1", Operation: "update", Value: rules.Deny},
|
||||
rules.Rule{Resource: "channel:2", Operation: "update"},
|
||||
rules.Rule{Resource: "system", Operation: "organisation.create", Value: rules.Allow},
|
||||
}
|
||||
return errors.New("Rollback")
|
||||
}), "Expected rollback error, got nil")
|
||||
err := resources.Grant(2, list)
|
||||
NoError(t, err, "expected no error")
|
||||
}
|
||||
|
||||
// list all by roleID
|
||||
{
|
||||
grants, err := resources.List(2)
|
||||
|
||||
fmt.Println(grants)
|
||||
|
||||
NoError(t, err, "expected no error")
|
||||
Assert(t, len(grants) == 3, "expected grants == 3, got %v", len(grants))
|
||||
}
|
||||
|
||||
// delete all by role
|
||||
{
|
||||
err := resources.Delete(2)
|
||||
NoError(t, err, "expected no error")
|
||||
}
|
||||
|
||||
// list all by role
|
||||
{
|
||||
grants, err := resources.List(2)
|
||||
NoError(t, err, "expected no error")
|
||||
Assert(t, len(grants) == 0, "expected grants == 0, got %v", len(grants))
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ const (
|
||||
Inherit = 0
|
||||
)
|
||||
|
||||
type Rules struct {
|
||||
TeamID uint64 `db:"rel_team"`
|
||||
type Rule struct {
|
||||
RoleID uint64 `db:"rel_role"`
|
||||
Resource string `db:"resource"`
|
||||
Operation string `db:"operation"`
|
||||
Value Access `db:"value"`
|
||||
@ -1,37 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/crusttech/crust/messaging/rest/request"
|
||||
"github.com/crusttech/crust/messaging/service"
|
||||
_ "github.com/crusttech/crust/messaging/types"
|
||||
)
|
||||
|
||||
type Permissions struct {
|
||||
svc struct {
|
||||
perms service.PermissionsService
|
||||
}
|
||||
}
|
||||
|
||||
func (Permissions) New() *Permissions {
|
||||
ctrl := &Permissions{}
|
||||
ctrl.svc.perms = service.DefaultPermissions
|
||||
return ctrl
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) List(ctx context.Context, r *request.PermissionsList) (interface{}, error) {
|
||||
return ctrl.svc.perms.List()
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) Get(ctx context.Context, r *request.PermissionsGet) (interface{}, error) {
|
||||
return ctrl.svc.perms.Get(r.TeamID, r.Resource)
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) Set(ctx context.Context, r *request.PermissionsSet) (interface{}, error) {
|
||||
return ctrl.svc.perms.Set(r.TeamID, r.Permissions)
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) Scopes(ctx context.Context, r *request.PermissionsScopes) (interface{}, error) {
|
||||
return ctrl.svc.perms.Scopes(r.Scope)
|
||||
}
|
||||
@ -22,7 +22,6 @@ func MountRoutes() func(chi.Router) {
|
||||
handlers.NewChannel(Channel{}.New()).MountRoutes(r)
|
||||
handlers.NewMessage(Message{}.New()).MountRoutes(r)
|
||||
handlers.NewSearch(Search{}.New()).MountRoutes(r)
|
||||
handlers.NewPermissions(Permissions{}.New()).MountRoutes(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ func TestMain(m *testing.M) {
|
||||
|
||||
// clean up tables
|
||||
{
|
||||
for _, name := range []string{"sys_user", "sys_team", "sys_team_member", "sys_organisation", "sys_rules"} {
|
||||
for _, name := range []string{"sys_user", "sys_role", "sys_role_member", "sys_organisation", "sys_rules"} {
|
||||
_, err := db.Exec("truncate " + name)
|
||||
if err != nil {
|
||||
panic("Error when clearing " + name + ": " + err.Error())
|
||||
|
||||
@ -1,99 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/internal/organization"
|
||||
internalRules "github.com/crusttech/crust/internal/rules"
|
||||
"github.com/crusttech/crust/messaging/repository"
|
||||
"github.com/crusttech/crust/messaging/types"
|
||||
systemRepository "github.com/crusttech/crust/system/repository"
|
||||
)
|
||||
|
||||
type (
|
||||
permissions struct {
|
||||
db db
|
||||
ctx context.Context
|
||||
|
||||
team systemRepository.TeamRepository
|
||||
channel repository.ChannelRepository
|
||||
|
||||
scopes internalRules.ScopeInterface
|
||||
resources internalRules.ResourcesInterface
|
||||
}
|
||||
|
||||
PermissionsService interface {
|
||||
With(ctx context.Context) PermissionsService
|
||||
|
||||
List() (interface{}, error)
|
||||
Get(teamID uint64, resource string) (interface{}, error)
|
||||
Set(teamID uint64, rules []internalRules.Rules) (interface{}, error)
|
||||
|
||||
Scopes(scope string) (interface{}, error)
|
||||
}
|
||||
)
|
||||
|
||||
func Permissions(scopes internalRules.ScopeInterface) PermissionsService {
|
||||
return (&permissions{
|
||||
scopes: scopes,
|
||||
}).With(context.Background())
|
||||
}
|
||||
|
||||
func (p *permissions) With(ctx context.Context) PermissionsService {
|
||||
db := repository.DB(ctx)
|
||||
return &permissions{
|
||||
db: db,
|
||||
ctx: ctx,
|
||||
|
||||
team: systemRepository.Team(ctx, db),
|
||||
channel: repository.Channel(ctx, db),
|
||||
|
||||
scopes: p.scopes,
|
||||
resources: internalRules.NewResources(ctx, db),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *permissions) List() (interface{}, error) {
|
||||
return p.scopes.List(), nil
|
||||
}
|
||||
|
||||
func (p *permissions) Get(teamID uint64, resource string) (interface{}, error) {
|
||||
return p.resources.ListGrants(teamID, resource)
|
||||
}
|
||||
|
||||
func (p *permissions) Set(teamID uint64, rules []internalRules.Rules) (interface{}, error) {
|
||||
var err error
|
||||
for _, rule := range rules {
|
||||
err = p.resources.Grant(
|
||||
teamID,
|
||||
rule.Resource,
|
||||
[]string{rule.Operation},
|
||||
rule.Value,
|
||||
)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (p *permissions) Scopes(scope string) (interface{}, error) {
|
||||
switch scope {
|
||||
case "organization":
|
||||
// @todo organizations from DB once multi-org
|
||||
// return p.organizaion.Find(nil)
|
||||
orgs := []types.Organisation{
|
||||
types.Organisation{
|
||||
organization.Crust(),
|
||||
},
|
||||
}
|
||||
return orgs, nil
|
||||
case "team":
|
||||
return p.team.Find(nil)
|
||||
case "channel":
|
||||
return p.channel.FindChannels(nil)
|
||||
}
|
||||
return nil, errors.New("no scope defined")
|
||||
}
|
||||
@ -1,119 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/internal/auth"
|
||||
internalRules "github.com/crusttech/crust/internal/rules"
|
||||
. "github.com/crusttech/crust/internal/test"
|
||||
"github.com/crusttech/crust/messaging/types"
|
||||
systemRepos "github.com/crusttech/crust/system/repository"
|
||||
systemTypes "github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestPermissions(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
ctx := context.TODO()
|
||||
|
||||
// Create user for test.
|
||||
userRepo := systemRepos.User(ctx, factory.Database.MustGet())
|
||||
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 = userRepo.Create(user)
|
||||
NoError(t, err, "expected no error creating user, got %v", err)
|
||||
|
||||
// Create team for test and add user
|
||||
teamRepo := systemRepos.Team(ctx, factory.Database.MustGet())
|
||||
team := &systemTypes.Team{
|
||||
Name: "Test team v1",
|
||||
}
|
||||
_, err = teamRepo.Create(team)
|
||||
NoError(t, err, "expected no error creating team, got %v", err)
|
||||
|
||||
err = teamRepo.MemberAddByID(team.ID, user.ID)
|
||||
NoError(t, err, "expected no error adding user to team, got %v", err)
|
||||
|
||||
// Set Identity.
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
// Create scopes.
|
||||
scopes := internalRules.NewScope()
|
||||
scopes.Add(&types.Organisation{})
|
||||
scopes.Add(&types.Team{})
|
||||
scopes.Add(&types.Channel{})
|
||||
|
||||
permissionsSvc := Permissions(scopes).With(ctx)
|
||||
|
||||
// Get all available scopes and items
|
||||
list, err := permissionsSvc.List()
|
||||
|
||||
scopeItems := list.([]internalRules.ScopeItem)
|
||||
NoError(t, err, "expected no error, receiving scopes")
|
||||
Assert(t, len(scopeItems) == 3, "expected 3 scopes, got %v", len(scopeItems))
|
||||
|
||||
// Setup nothing for organization
|
||||
organisationScope := scopeItems[0]
|
||||
Assert(t, organisationScope.Scope == "organisation", "expected scope 'organisation', got %s", organisationScope.Scope)
|
||||
|
||||
// Setup everything allow for team
|
||||
teamScope := scopeItems[1]
|
||||
Assert(t, teamScope.Scope == "team", "expected scope 'team', got %s", teamScope.Scope)
|
||||
|
||||
rules := make([]internalRules.Rules, 0)
|
||||
for _, group := range teamScope.Permissions {
|
||||
for _, op := range group.Operations {
|
||||
r := internalRules.Rules{
|
||||
TeamID: team.ID,
|
||||
Resource: "team:1",
|
||||
Operation: op.Key,
|
||||
Value: internalRules.Allow,
|
||||
}
|
||||
rules = append(rules, r)
|
||||
}
|
||||
}
|
||||
_, err = permissionsSvc.Set(team.ID, rules)
|
||||
NoError(t, err, "expected no error, setting rules")
|
||||
|
||||
// Deny all permissions for scope channel:1
|
||||
channelScope := scopeItems[2]
|
||||
Assert(t, channelScope.Scope == "channel", "expected scope 'channel', got %s", channelScope.Scope)
|
||||
|
||||
rules = make([]internalRules.Rules, 0)
|
||||
for _, group := range channelScope.Permissions {
|
||||
for _, op := range group.Operations {
|
||||
r := internalRules.Rules{
|
||||
TeamID: team.ID,
|
||||
Resource: "channel:1",
|
||||
Operation: op.Key,
|
||||
Value: internalRules.Deny,
|
||||
}
|
||||
rules = append(rules, r)
|
||||
}
|
||||
}
|
||||
_, err = permissionsSvc.Set(team.ID, rules)
|
||||
NoError(t, err, "expected no error, setting rules")
|
||||
|
||||
// Check permission on channel and team level to test inheritance.
|
||||
rls := Rules().With(ctx)
|
||||
|
||||
canManageChannels := rls.canManageChannels()
|
||||
Assert(t, canManageChannels == false, "expected canManageChannels == false, got %v", canManageChannels)
|
||||
|
||||
canSendMessage := rls.canSendMessages(&types.Channel{ID: 1})
|
||||
Assert(t, canSendMessage == false, "expected canSendMessage == false, got %v", canSendMessage)
|
||||
|
||||
canSendMessage = rls.canSendMessages(&types.Channel{ID: 2})
|
||||
Assert(t, canSendMessage == true, "expected canSendMessage == true, got %v", canSendMessage)
|
||||
}
|
||||
@ -16,7 +16,7 @@ type (
|
||||
|
||||
// identity is passed with context
|
||||
resources internalRules.ResourcesInterface
|
||||
team *systemTypes.Team
|
||||
role *systemTypes.Role
|
||||
org *types.Organisation
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@ type (
|
||||
canManageRoles() bool
|
||||
canManageChannels() bool
|
||||
|
||||
// types.Team derived from identity uses a wildcard match
|
||||
canManageWebhooks(ch *types.Channel) bool
|
||||
|
||||
// Messaging rules
|
||||
@ -46,7 +45,7 @@ type (
|
||||
|
||||
func Rules() RulesService {
|
||||
return (&rules{
|
||||
team: &systemTypes.Team{},
|
||||
role: &systemTypes.Role{},
|
||||
}).With(context.Background())
|
||||
}
|
||||
|
||||
@ -57,7 +56,7 @@ func (r *rules) With(ctx context.Context) RulesService {
|
||||
db: db,
|
||||
ctx: ctx,
|
||||
org: org,
|
||||
team: r.team,
|
||||
role: r.role,
|
||||
|
||||
resources: internalRules.NewResources(ctx, db),
|
||||
}
|
||||
@ -87,37 +86,37 @@ func (r *rules) canManageChannels() bool {
|
||||
|
||||
func (r *rules) canManageWebhooks(ch *types.Channel) bool {
|
||||
op := "manage.webhooks"
|
||||
return r.hasAccess(op, r.org.PermissionDefault(op), r.org.Resource().String(), r.team.Resource().All(), ch.Resource().String())
|
||||
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.team.Resource().All(), ch.Resource().String())
|
||||
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.team.Resource().All(), ch.Resource().String())
|
||||
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.team.Resource().All(), ch.Resource().String())
|
||||
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.team.Resource().All(), ch.Resource().String())
|
||||
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.team.Resource().All(), ch.Resource().String())
|
||||
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.team.Resource().All(), ch.Resource().String())
|
||||
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 {
|
||||
|
||||
@ -18,13 +18,12 @@ type (
|
||||
)
|
||||
|
||||
var (
|
||||
o sync.Once
|
||||
DefaultAttachment AttachmentService
|
||||
DefaultChannel ChannelService
|
||||
DefaultMessage MessageService
|
||||
DefaultPermissions PermissionsService
|
||||
DefaultPubSub *pubSub
|
||||
DefaultEvent EventService
|
||||
o sync.Once
|
||||
DefaultAttachment AttachmentService
|
||||
DefaultChannel ChannelService
|
||||
DefaultMessage MessageService
|
||||
DefaultPubSub *pubSub
|
||||
DefaultEvent EventService
|
||||
)
|
||||
|
||||
func Init() {
|
||||
@ -36,13 +35,12 @@ func Init() {
|
||||
|
||||
scopes := internalRules.NewScope()
|
||||
scopes.Add(&types.Organisation{})
|
||||
scopes.Add(&types.Team{})
|
||||
scopes.Add(&types.Role{})
|
||||
scopes.Add(&types.Channel{})
|
||||
|
||||
DefaultEvent = Event()
|
||||
DefaultAttachment = Attachment(fs)
|
||||
DefaultMessage = Message()
|
||||
DefaultPermissions = Permissions(scopes)
|
||||
DefaultChannel = Channel()
|
||||
DefaultPubSub = PubSub()
|
||||
})
|
||||
|
||||
@ -12,5 +12,5 @@ type (
|
||||
|
||||
// These entities create resources in RBAC
|
||||
var _ ResourceProvider = &Organisation{}
|
||||
var _ ResourceProvider = &Team{}
|
||||
var _ ResourceProvider = &Role{}
|
||||
var _ ResourceProvider = &Channel{}
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
Team struct {
|
||||
types.Team
|
||||
Role struct {
|
||||
types.Role
|
||||
}
|
||||
)
|
||||
@ -2,9 +2,9 @@ package types
|
||||
|
||||
import "github.com/crusttech/crust/internal/rules"
|
||||
|
||||
/* File is generated from messaging/types/permissions/2-team.json with permissions.go */
|
||||
/* File is generated from messaging/types/permissions/2-role.json with permissions.go */
|
||||
|
||||
func (*Team) Permissions() []rules.OperationGroup {
|
||||
func (*Role) Permissions() []rules.OperationGroup {
|
||||
return []rules.OperationGroup{
|
||||
rules.OperationGroup{
|
||||
Title: "General permissions",
|
||||
@ -62,15 +62,15 @@ func (*Team) Permissions() []rules.OperationGroup {
|
||||
}
|
||||
}
|
||||
|
||||
func (*Team) PermissionDefault(key string) rules.Access {
|
||||
func (*Role) PermissionDefault(key string) rules.Access {
|
||||
values := map[string]rules.Access{
|
||||
"manage.webhooks": rules.Inherit,
|
||||
"message.send": rules.Inherit,
|
||||
"message.embed": rules.Inherit,
|
||||
"message.attach": rules.Inherit,
|
||||
"message.update_own": rules.Inherit,
|
||||
"message.update_all": rules.Inherit,
|
||||
"message.react": rules.Inherit,
|
||||
"manage.webhooks": rules.Inherit,
|
||||
"message.send": rules.Inherit,
|
||||
}
|
||||
if value, ok := values[key]; ok {
|
||||
return value
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,5 @@
|
||||
ALTER TABLE sys_team RENAME TO sys_role;
|
||||
ALTER TABLE sys_team_member RENAME TO sys_role_member;
|
||||
|
||||
ALTER TABLE `sys_role_member` CHANGE COLUMN `rel_team` `rel_role` BIGINT UNSIGNED NOT NULL;
|
||||
ALTER TABLE `sys_rules` CHANGE COLUMN `rel_team` `rel_role` BIGINT UNSIGNED NOT NULL;
|
||||
@ -45,7 +45,7 @@ func TestMain(m *testing.M) {
|
||||
|
||||
// clean up tables
|
||||
{
|
||||
for _, name := range []string{"sys_user", "sys_team", "sys_team_member", "sys_organisation", "settings"} {
|
||||
for _, name := range []string{"sys_user", "sys_role", "sys_role_member", "sys_organisation", "settings"} {
|
||||
_, err := db.Exec("truncate " + name)
|
||||
if err != nil {
|
||||
panic("Error when clearing " + name + ": " + err.Error())
|
||||
|
||||
157
system/repository/role.go
Normal file
157
system/repository/role.go
Normal file
@ -0,0 +1,157 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
type (
|
||||
RoleRepository interface {
|
||||
With(ctx context.Context, db *factory.DB) RoleRepository
|
||||
|
||||
FindByID(id uint64) (*types.Role, error)
|
||||
FindByMemberID(userID uint64) ([]*types.Role, error)
|
||||
Find(filter *types.RoleFilter) ([]*types.Role, error)
|
||||
|
||||
Create(mod *types.Role) (*types.Role, error)
|
||||
Update(mod *types.Role) (*types.Role, error)
|
||||
|
||||
ArchiveByID(id uint64) error
|
||||
UnarchiveByID(id uint64) error
|
||||
DeleteByID(id uint64) error
|
||||
|
||||
MergeByID(id, targetRoleID uint64) error
|
||||
MoveByID(id, targetOrganisationID uint64) error
|
||||
|
||||
MemberAddByID(id, userID uint64) error
|
||||
MemberRemoveByID(id, userID uint64) error
|
||||
}
|
||||
|
||||
role struct {
|
||||
*repository
|
||||
|
||||
// sql table reference
|
||||
roles string
|
||||
members string
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
sqlRoleScope = "deleted_at IS NULL AND archived_at IS NULL"
|
||||
|
||||
ErrRoleNotFound = repositoryError("RoleNotFound")
|
||||
)
|
||||
|
||||
func Role(ctx context.Context, db *factory.DB) RoleRepository {
|
||||
return (&role{}).With(ctx, db)
|
||||
}
|
||||
|
||||
func (r *role) With(ctx context.Context, db *factory.DB) RoleRepository {
|
||||
return &role{
|
||||
repository: r.repository.With(ctx, db),
|
||||
roles: "sys_role",
|
||||
members: "sys_role_member",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *role) FindByID(id uint64) (*types.Role, error) {
|
||||
sql := "SELECT * FROM " + r.roles + " WHERE id = ? AND " + sqlRoleScope
|
||||
mod := &types.Role{}
|
||||
|
||||
return mod, isFound(r.db().Get(mod, sql, id), mod.ID > 0, ErrRoleNotFound)
|
||||
}
|
||||
|
||||
func (r *role) FindByMemberID(userID uint64) ([]*types.Role, error) {
|
||||
ids := make([]uint64, 0)
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
sql := "SELECT DISTINCT rel_role FROM " + r.members + " "
|
||||
sql += "WHERE rel_user = ?"
|
||||
params = append(params, userID)
|
||||
|
||||
if err := r.db().Select(&ids, sql, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rval := make([]*types.Role, 0)
|
||||
for _, id := range ids {
|
||||
mod, err := r.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rval = append(rval, mod)
|
||||
}
|
||||
|
||||
return rval, nil
|
||||
}
|
||||
|
||||
func (r *role) Find(filter *types.RoleFilter) ([]*types.Role, error) {
|
||||
rval := make([]*types.Role, 0)
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
sql := "SELECT * FROM " + r.roles + " WHERE " + sqlRoleScope
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += " AND name LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
|
||||
sql += " ORDER BY name ASC"
|
||||
|
||||
return rval, r.db().Select(&rval, sql, params...)
|
||||
}
|
||||
|
||||
func (r *role) Create(mod *types.Role) (*types.Role, error) {
|
||||
mod.ID = factory.Sonyflake.NextID()
|
||||
mod.CreatedAt = time.Now()
|
||||
|
||||
return mod, r.db().Insert(r.roles, mod)
|
||||
}
|
||||
|
||||
func (r *role) Update(mod *types.Role) (*types.Role, error) {
|
||||
mod.UpdatedAt = timeNowPtr()
|
||||
|
||||
return mod, r.db().Replace(r.roles, mod)
|
||||
}
|
||||
|
||||
func (r *role) ArchiveByID(id uint64) error {
|
||||
return r.updateColumnByID(r.roles, "archived_at", time.Now(), id)
|
||||
}
|
||||
|
||||
func (r *role) UnarchiveByID(id uint64) error {
|
||||
return r.updateColumnByID(r.roles, "archived_at", nil, id)
|
||||
}
|
||||
|
||||
func (r *role) DeleteByID(id uint64) error {
|
||||
return r.updateColumnByID(r.roles, "deleted_at", time.Now(), id)
|
||||
}
|
||||
|
||||
func (r *role) MergeByID(id, targetRoleID uint64) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (r *role) MoveByID(id, targetOrganisationID uint64) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (r *role) MemberAddByID(id, userID uint64) error {
|
||||
mod := &types.RoleMember{
|
||||
RoleID: id,
|
||||
UserID: userID,
|
||||
}
|
||||
return r.db().Replace(r.members, mod)
|
||||
}
|
||||
|
||||
func (r *role) MemberRemoveByID(id, userID uint64) error {
|
||||
mod := &types.RoleMember{
|
||||
RoleID: id,
|
||||
UserID: userID,
|
||||
}
|
||||
return r.db().Delete(r.members, mod, "rel_role", "rel_user")
|
||||
}
|
||||
103
system/repository/role_test.go
Normal file
103
system/repository/role_test.go
Normal file
@ -0,0 +1,103 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"testing"
|
||||
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestRole(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
userRepo := User(context.Background(), factory.Database.MustGet())
|
||||
user := &types.User{
|
||||
Name: "John Doe",
|
||||
Username: "johndoe",
|
||||
}
|
||||
user.GeneratePassword("johndoe")
|
||||
|
||||
{
|
||||
u1, err := userRepo.Create(user)
|
||||
assert(t, err == nil, "Owner.Create error: %+v", err)
|
||||
assert(t, user.ID == u1.ID, "Changes were not stored")
|
||||
}
|
||||
|
||||
roleRepo := Role(context.Background(), factory.Database.MustGet())
|
||||
role := &types.Role{
|
||||
Name: "Test role v1",
|
||||
}
|
||||
|
||||
{
|
||||
t1, err := roleRepo.Create(role)
|
||||
assert(t, err == nil, "Role.Create error: %+v", err)
|
||||
assert(t, role.Name == t1.Name, "Changes were not stored")
|
||||
}
|
||||
|
||||
{
|
||||
role.Name = "Test role v2"
|
||||
t1, err := roleRepo.Update(role)
|
||||
assert(t, err == nil, "Role.Update error: %+v", err)
|
||||
assert(t, role.Name == t1.Name, "Changes were not stored")
|
||||
}
|
||||
|
||||
{
|
||||
t1, err := roleRepo.FindByID(role.ID)
|
||||
assert(t, err == nil, "Role.FindByID error: %+v", err)
|
||||
assert(t, role.Name == t1.Name, "Changes were not stored")
|
||||
}
|
||||
|
||||
{
|
||||
aa, err := roleRepo.Find(&types.RoleFilter{Query: role.Name})
|
||||
assert(t, err == nil, "Role.Find error: %+v", err)
|
||||
assert(t, len(aa) > 0, "No results found")
|
||||
}
|
||||
|
||||
{
|
||||
err := roleRepo.ArchiveByID(role.ID)
|
||||
assert(t, err == nil, "Role.ArchiveByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := roleRepo.UnarchiveByID(role.ID)
|
||||
assert(t, err == nil, "Role.UnarchiveByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := roleRepo.MemberAddByID(role.ID, user.ID)
|
||||
assert(t, err == nil, "Role.MemberAddByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
roles, err := roleRepo.FindByMemberID(user.ID)
|
||||
assert(t, err == nil, "Role.FindByMemberID error: %+v", err)
|
||||
assert(t, len(roles) > 0, "No results found")
|
||||
}
|
||||
|
||||
{
|
||||
roles, err := roleRepo.FindByMemberID(0)
|
||||
assert(t, err == nil, "Role.FindByMemberID error: %+v", err)
|
||||
assert(t, len(roles) == 0, "Results found")
|
||||
}
|
||||
|
||||
{
|
||||
err := roleRepo.MemberRemoveByID(role.ID, user.ID)
|
||||
assert(t, err == nil, "Role.MemberRemoveByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := roleRepo.DeleteByID(role.ID)
|
||||
assert(t, err == nil, "Role.DeleteByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := userRepo.DeleteByID(user.ID)
|
||||
assert(t, err == nil, "Owner.DeleteByID error: %+v", err)
|
||||
}
|
||||
}
|
||||
@ -1,157 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
type (
|
||||
TeamRepository interface {
|
||||
With(ctx context.Context, db *factory.DB) TeamRepository
|
||||
|
||||
FindByID(id uint64) (*types.Team, error)
|
||||
FindByMemberID(userID uint64) ([]*types.Team, error)
|
||||
Find(filter *types.TeamFilter) ([]*types.Team, error)
|
||||
|
||||
Create(mod *types.Team) (*types.Team, error)
|
||||
Update(mod *types.Team) (*types.Team, error)
|
||||
|
||||
ArchiveByID(id uint64) error
|
||||
UnarchiveByID(id uint64) error
|
||||
DeleteByID(id uint64) error
|
||||
|
||||
MergeByID(id, targetTeamID uint64) error
|
||||
MoveByID(id, targetOrganisationID uint64) error
|
||||
|
||||
MemberAddByID(id, userID uint64) error
|
||||
MemberRemoveByID(id, userID uint64) error
|
||||
}
|
||||
|
||||
team struct {
|
||||
*repository
|
||||
|
||||
// sql table reference
|
||||
teams string
|
||||
members string
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
sqlTeamScope = "deleted_at IS NULL AND archived_at IS NULL"
|
||||
|
||||
ErrTeamNotFound = repositoryError("TeamNotFound")
|
||||
)
|
||||
|
||||
func Team(ctx context.Context, db *factory.DB) TeamRepository {
|
||||
return (&team{}).With(ctx, db)
|
||||
}
|
||||
|
||||
func (r *team) With(ctx context.Context, db *factory.DB) TeamRepository {
|
||||
return &team{
|
||||
repository: r.repository.With(ctx, db),
|
||||
teams: "sys_team",
|
||||
members: "sys_team_member",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *team) FindByID(id uint64) (*types.Team, error) {
|
||||
sql := "SELECT * FROM " + r.teams + " WHERE id = ? AND " + sqlTeamScope
|
||||
mod := &types.Team{}
|
||||
|
||||
return mod, isFound(r.db().Get(mod, sql, id), mod.ID > 0, ErrTeamNotFound)
|
||||
}
|
||||
|
||||
func (r *team) FindByMemberID(userID uint64) ([]*types.Team, error) {
|
||||
ids := make([]uint64, 0)
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
sql := "SELECT DISTINCT rel_team FROM " + r.members + " "
|
||||
sql += "WHERE rel_user = ?"
|
||||
params = append(params, userID)
|
||||
|
||||
if err := r.db().Select(&ids, sql, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rval := make([]*types.Team, 0)
|
||||
for _, id := range ids {
|
||||
mod, err := r.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rval = append(rval, mod)
|
||||
}
|
||||
|
||||
return rval, nil
|
||||
}
|
||||
|
||||
func (r *team) Find(filter *types.TeamFilter) ([]*types.Team, error) {
|
||||
rval := make([]*types.Team, 0)
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
sql := "SELECT * FROM " + r.teams + " WHERE " + sqlTeamScope
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += " AND name LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
|
||||
sql += " ORDER BY name ASC"
|
||||
|
||||
return rval, r.db().Select(&rval, sql, params...)
|
||||
}
|
||||
|
||||
func (r *team) Create(mod *types.Team) (*types.Team, error) {
|
||||
mod.ID = factory.Sonyflake.NextID()
|
||||
mod.CreatedAt = time.Now()
|
||||
|
||||
return mod, r.db().Insert(r.teams, mod)
|
||||
}
|
||||
|
||||
func (r *team) Update(mod *types.Team) (*types.Team, error) {
|
||||
mod.UpdatedAt = timeNowPtr()
|
||||
|
||||
return mod, r.db().Replace(r.teams, mod)
|
||||
}
|
||||
|
||||
func (r *team) ArchiveByID(id uint64) error {
|
||||
return r.updateColumnByID(r.teams, "archived_at", time.Now(), id)
|
||||
}
|
||||
|
||||
func (r *team) UnarchiveByID(id uint64) error {
|
||||
return r.updateColumnByID(r.teams, "archived_at", nil, id)
|
||||
}
|
||||
|
||||
func (r *team) DeleteByID(id uint64) error {
|
||||
return r.updateColumnByID(r.teams, "deleted_at", time.Now(), id)
|
||||
}
|
||||
|
||||
func (r *team) MergeByID(id, targetTeamID uint64) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (r *team) MoveByID(id, targetOrganisationID uint64) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (r *team) MemberAddByID(id, userID uint64) error {
|
||||
mod := &types.TeamMember{
|
||||
TeamID: id,
|
||||
UserID: userID,
|
||||
}
|
||||
return r.db().Replace(r.members, mod)
|
||||
}
|
||||
|
||||
func (r *team) MemberRemoveByID(id, userID uint64) error {
|
||||
mod := &types.TeamMember{
|
||||
TeamID: id,
|
||||
UserID: userID,
|
||||
}
|
||||
return r.db().Delete(r.members, mod, "rel_team", "rel_user")
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"testing"
|
||||
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestTeam(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
userRepo := User(context.Background(), factory.Database.MustGet())
|
||||
user := &types.User{
|
||||
Name: "John Doe",
|
||||
Username: "johndoe",
|
||||
}
|
||||
user.GeneratePassword("johndoe")
|
||||
|
||||
{
|
||||
u1, err := userRepo.Create(user)
|
||||
assert(t, err == nil, "Owner.Create error: %+v", err)
|
||||
assert(t, user.ID == u1.ID, "Changes were not stored")
|
||||
}
|
||||
|
||||
teamRepo := Team(context.Background(), factory.Database.MustGet())
|
||||
team := &types.Team{
|
||||
Name: "Test team v1",
|
||||
}
|
||||
|
||||
{
|
||||
t1, err := teamRepo.Create(team)
|
||||
assert(t, err == nil, "Team.Create error: %+v", err)
|
||||
assert(t, team.Name == t1.Name, "Changes were not stored")
|
||||
}
|
||||
|
||||
{
|
||||
team.Name = "Test team v2"
|
||||
t1, err := teamRepo.Update(team)
|
||||
assert(t, err == nil, "Team.Update error: %+v", err)
|
||||
assert(t, team.Name == t1.Name, "Changes were not stored")
|
||||
}
|
||||
|
||||
{
|
||||
t1, err := teamRepo.FindByID(team.ID)
|
||||
assert(t, err == nil, "Team.FindByID error: %+v", err)
|
||||
assert(t, team.Name == t1.Name, "Changes were not stored")
|
||||
}
|
||||
|
||||
{
|
||||
aa, err := teamRepo.Find(&types.TeamFilter{Query: team.Name})
|
||||
assert(t, err == nil, "Team.Find error: %+v", err)
|
||||
assert(t, len(aa) > 0, "No results found")
|
||||
}
|
||||
|
||||
{
|
||||
err := teamRepo.ArchiveByID(team.ID)
|
||||
assert(t, err == nil, "Team.ArchiveByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := teamRepo.UnarchiveByID(team.ID)
|
||||
assert(t, err == nil, "Team.UnarchiveByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := teamRepo.MemberAddByID(team.ID, user.ID)
|
||||
assert(t, err == nil, "Team.MemberAddByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
teams, err := teamRepo.FindByMemberID(user.ID)
|
||||
assert(t, err == nil, "Team.FindByMemberID error: %+v", err)
|
||||
assert(t, len(teams) > 0, "No results found")
|
||||
}
|
||||
|
||||
{
|
||||
teams, err := teamRepo.FindByMemberID(0)
|
||||
assert(t, err == nil, "Team.FindByMemberID error: %+v", err)
|
||||
assert(t, len(teams) == 0, "Results found")
|
||||
}
|
||||
|
||||
{
|
||||
err := teamRepo.MemberRemoveByID(team.ID, user.ID)
|
||||
assert(t, err == nil, "Team.MemberRemoveByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := teamRepo.DeleteByID(team.ID)
|
||||
assert(t, err == nil, "Team.DeleteByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
err := userRepo.DeleteByID(user.ID)
|
||||
assert(t, err == nil, "Owner.DeleteByID error: %+v", err)
|
||||
}
|
||||
}
|
||||
@ -86,7 +86,7 @@ func (r *user) FindByID(id uint64) (*types.User, error) {
|
||||
if err := isFound(r.db().Get(mod, sql, id), mod.ID > 0, ErrUserNotFound); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mod, r.prepare(mod, "teams")
|
||||
return mod, r.prepare(mod, "roles")
|
||||
}
|
||||
|
||||
func (r *user) FindByIDs(IDs ...uint64) (uu types.UserSet, err error) {
|
||||
@ -142,7 +142,7 @@ func (r *user) Find(filter *types.UserFilter) ([]*types.User, error) {
|
||||
if err := r.db().Select(&rval, sql, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.prepareAll(rval, "teams"); err != nil {
|
||||
if err := r.prepareAll(rval, "roles"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -182,16 +182,16 @@ func (r *user) prepareAll(users []*types.User, fields ...string) error {
|
||||
}
|
||||
|
||||
func (r *user) prepare(user *types.User, fields ...string) (err error) {
|
||||
api := Team(r.Context(), r.db())
|
||||
api := Role(r.Context(), r.db())
|
||||
for _, field := range fields {
|
||||
switch field {
|
||||
case "teams":
|
||||
case "roles":
|
||||
if user.ID > 0 {
|
||||
teams, err := api.FindByMemberID(user.ID)
|
||||
roles, err := api.FindByMemberID(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.Teams = teams
|
||||
user.Roles = roles
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
@ -29,30 +29,30 @@ func TestUser(t *testing.T) {
|
||||
assert(t, user.ID == uu.ID, "Changes were not stored")
|
||||
}
|
||||
|
||||
teamRepo := Team(context.Background(), factory.Database.MustGet())
|
||||
team := &types.Team{
|
||||
Name: "Test team v1",
|
||||
roleRepo := Role(context.Background(), factory.Database.MustGet())
|
||||
role := &types.Role{
|
||||
Name: "Test role v1",
|
||||
}
|
||||
|
||||
{
|
||||
t1, err := teamRepo.Create(team)
|
||||
assert(t, err == nil, "Team.Create error: %+v", err)
|
||||
assert(t, team.Name == t1.Name, "Changes were not stored")
|
||||
t1, err := roleRepo.Create(role)
|
||||
assert(t, err == nil, "Role.Create error: %+v", err)
|
||||
assert(t, role.Name == t1.Name, "Changes were not stored")
|
||||
|
||||
err = teamRepo.MemberAddByID(t1.ID, user.ID)
|
||||
assert(t, err == nil, "Team.MemberAddByID error: %+v", err)
|
||||
err = roleRepo.MemberAddByID(t1.ID, user.ID)
|
||||
assert(t, err == nil, "Role.MemberAddByID error: %+v", err)
|
||||
}
|
||||
|
||||
{
|
||||
uu, err := userRepo.FindByID(user.ID)
|
||||
assert(t, err == nil, "Owner.FindByID error: %+v", err)
|
||||
assert(t, len(uu.Teams) == 1, "Expected 1 team, got %d", len(uu.Teams))
|
||||
assert(t, len(uu.Roles) == 1, "Expected 1 role, got %d", len(uu.Roles))
|
||||
}
|
||||
|
||||
{
|
||||
users, err := userRepo.Find(&types.UserFilter{Query: ""})
|
||||
assert(t, err == nil, "Owner.Find error: %+v", err)
|
||||
assert(t, len(users) == 1, "Owner.Find: expected 1 user, got %d", len(users))
|
||||
assert(t, len(users[0].Teams) == 1, "Owner.Find: expected 1 team, got %d", len(users[0].Teams))
|
||||
assert(t, len(users[0].Roles) == 1, "Owner.Find: expected 1 role, got %d", len(users[0].Roles))
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,34 +22,25 @@ import (
|
||||
|
||||
"github.com/titpetric/factory/resputil"
|
||||
|
||||
"github.com/crusttech/crust/messaging/rest/request"
|
||||
"github.com/crusttech/crust/system/rest/request"
|
||||
)
|
||||
|
||||
// Internal API interface
|
||||
type PermissionsAPI interface {
|
||||
List(context.Context, *request.PermissionsList) (interface{}, error)
|
||||
Get(context.Context, *request.PermissionsGet) (interface{}, error)
|
||||
Set(context.Context, *request.PermissionsSet) (interface{}, error)
|
||||
Scopes(context.Context, *request.PermissionsScopes) (interface{}, error)
|
||||
Delete(context.Context, *request.PermissionsDelete) (interface{}, error)
|
||||
Update(context.Context, *request.PermissionsUpdate) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type Permissions struct {
|
||||
List func(http.ResponseWriter, *http.Request)
|
||||
Get func(http.ResponseWriter, *http.Request)
|
||||
Set func(http.ResponseWriter, *http.Request)
|
||||
Scopes func(http.ResponseWriter, *http.Request)
|
||||
Delete func(http.ResponseWriter, *http.Request)
|
||||
Update func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewPermissions(ph PermissionsAPI) *Permissions {
|
||||
return &Permissions{
|
||||
List: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewPermissionsList()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return ph.List(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Get: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewPermissionsGet()
|
||||
@ -57,18 +48,18 @@ func NewPermissions(ph PermissionsAPI) *Permissions {
|
||||
return ph.Get(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Set: func(w http.ResponseWriter, r *http.Request) {
|
||||
Delete: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewPermissionsSet()
|
||||
params := request.NewPermissionsDelete()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return ph.Set(r.Context(), params)
|
||||
return ph.Delete(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Scopes: func(w http.ResponseWriter, r *http.Request) {
|
||||
Update: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewPermissionsScopes()
|
||||
params := request.NewPermissionsUpdate()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return ph.Scopes(r.Context(), params)
|
||||
return ph.Update(r.Context(), params)
|
||||
})
|
||||
},
|
||||
}
|
||||
@ -78,10 +69,9 @@ func (ph *Permissions) MountRoutes(r chi.Router, middlewares ...func(http.Handle
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Route("/permissions", func(r chi.Router) {
|
||||
r.Get("/", ph.List)
|
||||
r.Get("/{teamID}", ph.Get)
|
||||
r.Post("/{teamID}", ph.Set)
|
||||
r.Get("/scopes/{scope}", ph.Scopes)
|
||||
r.Get("/{roleID}/rules", ph.Get)
|
||||
r.Delete("/{roleID}/rules", ph.Delete)
|
||||
r.Patch("/{roleID}/rules", ph.Update)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -10,8 +10,8 @@ package handlers
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `team.go`, `team.util.go` or `team_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `team.go`
|
||||
You may edit `role.go`, `role.util.go` or `role_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `role.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
@ -26,21 +26,21 @@ import (
|
||||
)
|
||||
|
||||
// Internal API interface
|
||||
type TeamAPI interface {
|
||||
List(context.Context, *request.TeamList) (interface{}, error)
|
||||
Create(context.Context, *request.TeamCreate) (interface{}, error)
|
||||
Update(context.Context, *request.TeamUpdate) (interface{}, error)
|
||||
Read(context.Context, *request.TeamRead) (interface{}, error)
|
||||
Remove(context.Context, *request.TeamRemove) (interface{}, error)
|
||||
Archive(context.Context, *request.TeamArchive) (interface{}, error)
|
||||
Move(context.Context, *request.TeamMove) (interface{}, error)
|
||||
Merge(context.Context, *request.TeamMerge) (interface{}, error)
|
||||
MemberAdd(context.Context, *request.TeamMemberAdd) (interface{}, error)
|
||||
MemberRemove(context.Context, *request.TeamMemberRemove) (interface{}, error)
|
||||
type RoleAPI interface {
|
||||
List(context.Context, *request.RoleList) (interface{}, error)
|
||||
Create(context.Context, *request.RoleCreate) (interface{}, error)
|
||||
Update(context.Context, *request.RoleUpdate) (interface{}, error)
|
||||
Read(context.Context, *request.RoleRead) (interface{}, error)
|
||||
Remove(context.Context, *request.RoleRemove) (interface{}, error)
|
||||
Archive(context.Context, *request.RoleArchive) (interface{}, error)
|
||||
Move(context.Context, *request.RoleMove) (interface{}, error)
|
||||
Merge(context.Context, *request.RoleMerge) (interface{}, error)
|
||||
MemberAdd(context.Context, *request.RoleMemberAdd) (interface{}, error)
|
||||
MemberRemove(context.Context, *request.RoleMemberRemove) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type Team struct {
|
||||
type Role struct {
|
||||
List func(http.ResponseWriter, *http.Request)
|
||||
Create func(http.ResponseWriter, *http.Request)
|
||||
Update func(http.ResponseWriter, *http.Request)
|
||||
@ -53,95 +53,95 @@ type Team struct {
|
||||
MemberRemove func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewTeam(th TeamAPI) *Team {
|
||||
return &Team{
|
||||
func NewRole(rh RoleAPI) *Role {
|
||||
return &Role{
|
||||
List: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamList()
|
||||
params := request.NewRoleList()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.List(r.Context(), params)
|
||||
return rh.List(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Create: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamCreate()
|
||||
params := request.NewRoleCreate()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Create(r.Context(), params)
|
||||
return rh.Create(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Update: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamUpdate()
|
||||
params := request.NewRoleUpdate()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Update(r.Context(), params)
|
||||
return rh.Update(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Read: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamRead()
|
||||
params := request.NewRoleRead()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Read(r.Context(), params)
|
||||
return rh.Read(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Remove: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamRemove()
|
||||
params := request.NewRoleRemove()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Remove(r.Context(), params)
|
||||
return rh.Remove(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Archive: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamArchive()
|
||||
params := request.NewRoleArchive()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Archive(r.Context(), params)
|
||||
return rh.Archive(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Move: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamMove()
|
||||
params := request.NewRoleMove()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Move(r.Context(), params)
|
||||
return rh.Move(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Merge: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamMerge()
|
||||
params := request.NewRoleMerge()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.Merge(r.Context(), params)
|
||||
return rh.Merge(r.Context(), params)
|
||||
})
|
||||
},
|
||||
MemberAdd: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamMemberAdd()
|
||||
params := request.NewRoleMemberAdd()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.MemberAdd(r.Context(), params)
|
||||
return rh.MemberAdd(r.Context(), params)
|
||||
})
|
||||
},
|
||||
MemberRemove: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewTeamMemberRemove()
|
||||
params := request.NewRoleMemberRemove()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return th.MemberRemove(r.Context(), params)
|
||||
return rh.MemberRemove(r.Context(), params)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (th *Team) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
|
||||
func (rh *Role) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Route("/teams", func(r chi.Router) {
|
||||
r.Get("/", th.List)
|
||||
r.Post("/", th.Create)
|
||||
r.Put("/{teamID}", th.Update)
|
||||
r.Get("/{teamID}", th.Read)
|
||||
r.Delete("/{teamID}", th.Remove)
|
||||
r.Post("/{teamID}/archive", th.Archive)
|
||||
r.Post("/{teamID}/move", th.Move)
|
||||
r.Post("/{teamID}/merge", th.Merge)
|
||||
r.Post("/{teamID}/memberAdd", th.MemberAdd)
|
||||
r.Post("/{teamID}/memberRemove", th.MemberRemove)
|
||||
r.Route("/roles", func(r chi.Router) {
|
||||
r.Get("/", rh.List)
|
||||
r.Post("/", rh.Create)
|
||||
r.Put("/{roleID}", rh.Update)
|
||||
r.Get("/{roleID}", rh.Read)
|
||||
r.Delete("/{roleID}", rh.Remove)
|
||||
r.Post("/{roleID}/archive", rh.Archive)
|
||||
r.Post("/{roleID}/move", rh.Move)
|
||||
r.Post("/{roleID}/merge", rh.Merge)
|
||||
r.Post("/{roleID}/memberAdd", rh.MemberAdd)
|
||||
r.Post("/{roleID}/memberRemove", rh.MemberRemove)
|
||||
})
|
||||
})
|
||||
}
|
||||
36
system/rest/permissions.go
Normal file
36
system/rest/permissions.go
Normal file
@ -0,0 +1,36 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/system/rest/request"
|
||||
"github.com/crusttech/crust/system/service"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Permissions struct {
|
||||
svc struct {
|
||||
perm service.PermissionService
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
func (Permissions) New() *Permissions {
|
||||
return &Permissions{}
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) Get(ctx context.Context, r *request.PermissionsGet) (interface{}, error) {
|
||||
return ctrl.svc.perm.Get(r.RoleID)
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) Delete(ctx context.Context, r *request.PermissionsDelete) (interface{}, error) {
|
||||
return ctrl.svc.perm.Delete(r.RoleID)
|
||||
}
|
||||
|
||||
func (ctrl *Permissions) Update(ctx context.Context, r *request.PermissionsUpdate) (interface{}, error) {
|
||||
return ctrl.svc.perm.Update(r.RoleID, r.Permissions)
|
||||
}
|
||||
@ -37,9 +37,9 @@ func NewAuthCheck() *AuthCheck {
|
||||
return &AuthCheck{}
|
||||
}
|
||||
|
||||
func (a *AuthCheck) Fill(r *http.Request) (err error) {
|
||||
func (au *AuthCheck) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(a)
|
||||
err = json.NewDecoder(r.Body).Decode(au)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -79,9 +79,9 @@ func NewAuthLogin() *AuthLogin {
|
||||
return &AuthLogin{}
|
||||
}
|
||||
|
||||
func (a *AuthLogin) Fill(r *http.Request) (err error) {
|
||||
func (au *AuthLogin) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(a)
|
||||
err = json.NewDecoder(r.Body).Decode(au)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -108,11 +108,11 @@ func (a *AuthLogin) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := post["username"]; ok {
|
||||
|
||||
a.Username = val
|
||||
au.Username = val
|
||||
}
|
||||
if val, ok := post["password"]; ok {
|
||||
|
||||
a.Password = val
|
||||
au.Password = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -128,9 +128,9 @@ func NewAuthLogout() *AuthLogout {
|
||||
return &AuthLogout{}
|
||||
}
|
||||
|
||||
func (a *AuthLogout) Fill(r *http.Request) (err error) {
|
||||
func (au *AuthLogout) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(a)
|
||||
err = json.NewDecoder(r.Body).Decode(au)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
|
||||
@ -38,9 +38,9 @@ func NewOrganisationList() *OrganisationList {
|
||||
return &OrganisationList{}
|
||||
}
|
||||
|
||||
func (o *OrganisationList) Fill(r *http.Request) (err error) {
|
||||
func (or *OrganisationList) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(o)
|
||||
err = json.NewDecoder(r.Body).Decode(or)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -67,7 +67,7 @@ func (o *OrganisationList) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := get["query"]; ok {
|
||||
|
||||
o.Query = val
|
||||
or.Query = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -84,9 +84,9 @@ func NewOrganisationCreate() *OrganisationCreate {
|
||||
return &OrganisationCreate{}
|
||||
}
|
||||
|
||||
func (o *OrganisationCreate) Fill(r *http.Request) (err error) {
|
||||
func (or *OrganisationCreate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(o)
|
||||
err = json.NewDecoder(r.Body).Decode(or)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -113,7 +113,7 @@ func (o *OrganisationCreate) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
o.Name = val
|
||||
or.Name = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -131,9 +131,9 @@ func NewOrganisationUpdate() *OrganisationUpdate {
|
||||
return &OrganisationUpdate{}
|
||||
}
|
||||
|
||||
func (o *OrganisationUpdate) Fill(r *http.Request) (err error) {
|
||||
func (or *OrganisationUpdate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(o)
|
||||
err = json.NewDecoder(r.Body).Decode(or)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -158,10 +158,10 @@ func (o *OrganisationUpdate) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
o.ID = parseUInt64(chi.URLParam(r, "id"))
|
||||
or.ID = parseUInt64(chi.URLParam(r, "id"))
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
o.Name = val
|
||||
or.Name = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -178,9 +178,9 @@ func NewOrganisationRemove() *OrganisationRemove {
|
||||
return &OrganisationRemove{}
|
||||
}
|
||||
|
||||
func (o *OrganisationRemove) Fill(r *http.Request) (err error) {
|
||||
func (or *OrganisationRemove) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(o)
|
||||
err = json.NewDecoder(r.Body).Decode(or)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -205,7 +205,7 @@ func (o *OrganisationRemove) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
o.ID = parseUInt64(chi.URLParam(r, "id"))
|
||||
or.ID = parseUInt64(chi.URLParam(r, "id"))
|
||||
|
||||
return err
|
||||
}
|
||||
@ -221,9 +221,9 @@ func NewOrganisationRead() *OrganisationRead {
|
||||
return &OrganisationRead{}
|
||||
}
|
||||
|
||||
func (o *OrganisationRead) Fill(r *http.Request) (err error) {
|
||||
func (or *OrganisationRead) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(o)
|
||||
err = json.NewDecoder(r.Body).Decode(or)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -250,7 +250,7 @@ func (o *OrganisationRead) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := get["id"]; ok {
|
||||
|
||||
o.ID = parseUInt64(val)
|
||||
or.ID = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
@ -267,9 +267,9 @@ func NewOrganisationArchive() *OrganisationArchive {
|
||||
return &OrganisationArchive{}
|
||||
}
|
||||
|
||||
func (o *OrganisationArchive) Fill(r *http.Request) (err error) {
|
||||
func (or *OrganisationArchive) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(o)
|
||||
err = json.NewDecoder(r.Body).Decode(or)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -294,7 +294,7 @@ func (o *OrganisationArchive) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
o.ID = parseUInt64(chi.URLParam(r, "id"))
|
||||
or.ID = parseUInt64(chi.URLParam(r, "id"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -31,59 +31,18 @@ import (
|
||||
var _ = chi.URLParam
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// Permissions list request parameters
|
||||
type PermissionsList struct {
|
||||
}
|
||||
|
||||
func NewPermissionsList() *PermissionsList {
|
||||
return &PermissionsList{}
|
||||
}
|
||||
|
||||
func (p *PermissionsList) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(p)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewPermissionsList()
|
||||
|
||||
// Permissions get request parameters
|
||||
type PermissionsGet struct {
|
||||
Resource string
|
||||
TeamID uint64 `json:",string"`
|
||||
RoleID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewPermissionsGet() *PermissionsGet {
|
||||
return &PermissionsGet{}
|
||||
}
|
||||
|
||||
func (p *PermissionsGet) Fill(r *http.Request) (err error) {
|
||||
func (pe *PermissionsGet) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(p)
|
||||
err = json.NewDecoder(r.Body).Decode(pe)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -108,30 +67,25 @@ func (p *PermissionsGet) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := get["resource"]; ok {
|
||||
|
||||
p.Resource = val
|
||||
}
|
||||
p.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
pe.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewPermissionsGet()
|
||||
|
||||
// Permissions set request parameters
|
||||
type PermissionsSet struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
Permissions []rules.Rules
|
||||
// Permissions delete request parameters
|
||||
type PermissionsDelete struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewPermissionsSet() *PermissionsSet {
|
||||
return &PermissionsSet{}
|
||||
func NewPermissionsDelete() *PermissionsDelete {
|
||||
return &PermissionsDelete{}
|
||||
}
|
||||
|
||||
func (p *PermissionsSet) Fill(r *http.Request) (err error) {
|
||||
func (pe *PermissionsDelete) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(p)
|
||||
err = json.NewDecoder(r.Body).Decode(pe)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -156,25 +110,26 @@ func (p *PermissionsSet) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
p.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
pe.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewPermissionsSet()
|
||||
var _ RequestFiller = NewPermissionsDelete()
|
||||
|
||||
// Permissions scopes request parameters
|
||||
type PermissionsScopes struct {
|
||||
Scope string
|
||||
// Permissions update request parameters
|
||||
type PermissionsUpdate struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
Permissions []rules.Rule
|
||||
}
|
||||
|
||||
func NewPermissionsScopes() *PermissionsScopes {
|
||||
return &PermissionsScopes{}
|
||||
func NewPermissionsUpdate() *PermissionsUpdate {
|
||||
return &PermissionsUpdate{}
|
||||
}
|
||||
|
||||
func (p *PermissionsScopes) Fill(r *http.Request) (err error) {
|
||||
func (pe *PermissionsUpdate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(p)
|
||||
err = json.NewDecoder(r.Body).Decode(pe)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -199,9 +154,9 @@ func (p *PermissionsScopes) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
p.Scope = chi.URLParam(r, "scope")
|
||||
pe.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewPermissionsScopes()
|
||||
var _ RequestFiller = NewPermissionsUpdate()
|
||||
@ -10,8 +10,8 @@ package request
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `team.go`, `team.util.go` or `team_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `team.go`
|
||||
You may edit `role.go`, `role.util.go` or `role_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `role.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
@ -29,18 +29,18 @@ import (
|
||||
var _ = chi.URLParam
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// Team list request parameters
|
||||
type TeamList struct {
|
||||
// Role list request parameters
|
||||
type RoleList struct {
|
||||
Query string
|
||||
}
|
||||
|
||||
func NewTeamList() *TeamList {
|
||||
return &TeamList{}
|
||||
func NewRoleList() *RoleList {
|
||||
return &RoleList{}
|
||||
}
|
||||
|
||||
func (t *TeamList) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleList) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -67,27 +67,27 @@ func (t *TeamList) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := get["query"]; ok {
|
||||
|
||||
t.Query = val
|
||||
ro.Query = val
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamList()
|
||||
var _ RequestFiller = NewRoleList()
|
||||
|
||||
// Team create request parameters
|
||||
type TeamCreate struct {
|
||||
// Role create request parameters
|
||||
type RoleCreate struct {
|
||||
Name string
|
||||
Members []uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamCreate() *TeamCreate {
|
||||
return &TeamCreate{}
|
||||
func NewRoleCreate() *RoleCreate {
|
||||
return &RoleCreate{}
|
||||
}
|
||||
|
||||
func (t *TeamCreate) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleCreate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -114,29 +114,29 @@ func (t *TeamCreate) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
t.Name = val
|
||||
ro.Name = val
|
||||
}
|
||||
t.Members = parseUInt64A(r.Form["members"])
|
||||
ro.Members = parseUInt64A(r.Form["members"])
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamCreate()
|
||||
var _ RequestFiller = NewRoleCreate()
|
||||
|
||||
// Team update request parameters
|
||||
type TeamUpdate struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role update request parameters
|
||||
type RoleUpdate struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
Name string
|
||||
Members []uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamUpdate() *TeamUpdate {
|
||||
return &TeamUpdate{}
|
||||
func NewRoleUpdate() *RoleUpdate {
|
||||
return &RoleUpdate{}
|
||||
}
|
||||
|
||||
func (t *TeamUpdate) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleUpdate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -161,30 +161,30 @@ func (t *TeamUpdate) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
t.Name = val
|
||||
ro.Name = val
|
||||
}
|
||||
t.Members = parseUInt64A(r.Form["members"])
|
||||
ro.Members = parseUInt64A(r.Form["members"])
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamUpdate()
|
||||
var _ RequestFiller = NewRoleUpdate()
|
||||
|
||||
// Team read request parameters
|
||||
type TeamRead struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role read request parameters
|
||||
type RoleRead struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamRead() *TeamRead {
|
||||
return &TeamRead{}
|
||||
func NewRoleRead() *RoleRead {
|
||||
return &RoleRead{}
|
||||
}
|
||||
|
||||
func (t *TeamRead) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleRead) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -209,25 +209,25 @@ func (t *TeamRead) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamRead()
|
||||
var _ RequestFiller = NewRoleRead()
|
||||
|
||||
// Team remove request parameters
|
||||
type TeamRemove struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role remove request parameters
|
||||
type RoleRemove struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamRemove() *TeamRemove {
|
||||
return &TeamRemove{}
|
||||
func NewRoleRemove() *RoleRemove {
|
||||
return &RoleRemove{}
|
||||
}
|
||||
|
||||
func (t *TeamRemove) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleRemove) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -252,25 +252,25 @@ func (t *TeamRemove) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamRemove()
|
||||
var _ RequestFiller = NewRoleRemove()
|
||||
|
||||
// Team archive request parameters
|
||||
type TeamArchive struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role archive request parameters
|
||||
type RoleArchive struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamArchive() *TeamArchive {
|
||||
return &TeamArchive{}
|
||||
func NewRoleArchive() *RoleArchive {
|
||||
return &RoleArchive{}
|
||||
}
|
||||
|
||||
func (t *TeamArchive) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleArchive) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -295,26 +295,26 @@ func (t *TeamArchive) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamArchive()
|
||||
var _ RequestFiller = NewRoleArchive()
|
||||
|
||||
// Team move request parameters
|
||||
type TeamMove struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role move request parameters
|
||||
type RoleMove struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
OrganisationID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamMove() *TeamMove {
|
||||
return &TeamMove{}
|
||||
func NewRoleMove() *RoleMove {
|
||||
return &RoleMove{}
|
||||
}
|
||||
|
||||
func (t *TeamMove) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleMove) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -339,30 +339,30 @@ func (t *TeamMove) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
if val, ok := post["organisationID"]; ok {
|
||||
|
||||
t.OrganisationID = parseUInt64(val)
|
||||
ro.OrganisationID = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamMove()
|
||||
var _ RequestFiller = NewRoleMove()
|
||||
|
||||
// Team merge request parameters
|
||||
type TeamMerge struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role merge request parameters
|
||||
type RoleMerge struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
Destination uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamMerge() *TeamMerge {
|
||||
return &TeamMerge{}
|
||||
func NewRoleMerge() *RoleMerge {
|
||||
return &RoleMerge{}
|
||||
}
|
||||
|
||||
func (t *TeamMerge) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleMerge) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -387,30 +387,30 @@ func (t *TeamMerge) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
if val, ok := post["destination"]; ok {
|
||||
|
||||
t.Destination = parseUInt64(val)
|
||||
ro.Destination = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamMerge()
|
||||
var _ RequestFiller = NewRoleMerge()
|
||||
|
||||
// Team memberAdd request parameters
|
||||
type TeamMemberAdd struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role memberAdd request parameters
|
||||
type RoleMemberAdd struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
UserID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamMemberAdd() *TeamMemberAdd {
|
||||
return &TeamMemberAdd{}
|
||||
func NewRoleMemberAdd() *RoleMemberAdd {
|
||||
return &RoleMemberAdd{}
|
||||
}
|
||||
|
||||
func (t *TeamMemberAdd) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleMemberAdd) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -435,30 +435,30 @@ func (t *TeamMemberAdd) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
if val, ok := post["userID"]; ok {
|
||||
|
||||
t.UserID = parseUInt64(val)
|
||||
ro.UserID = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamMemberAdd()
|
||||
var _ RequestFiller = NewRoleMemberAdd()
|
||||
|
||||
// Team memberRemove request parameters
|
||||
type TeamMemberRemove struct {
|
||||
TeamID uint64 `json:",string"`
|
||||
// Role memberRemove request parameters
|
||||
type RoleMemberRemove struct {
|
||||
RoleID uint64 `json:",string"`
|
||||
UserID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewTeamMemberRemove() *TeamMemberRemove {
|
||||
return &TeamMemberRemove{}
|
||||
func NewRoleMemberRemove() *RoleMemberRemove {
|
||||
return &RoleMemberRemove{}
|
||||
}
|
||||
|
||||
func (t *TeamMemberRemove) Fill(r *http.Request) (err error) {
|
||||
func (ro *RoleMemberRemove) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(t)
|
||||
err = json.NewDecoder(r.Body).Decode(ro)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -483,13 +483,13 @@ func (t *TeamMemberRemove) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
t.TeamID = parseUInt64(chi.URLParam(r, "teamID"))
|
||||
ro.RoleID = parseUInt64(chi.URLParam(r, "roleID"))
|
||||
if val, ok := post["userID"]; ok {
|
||||
|
||||
t.UserID = parseUInt64(val)
|
||||
ro.UserID = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewTeamMemberRemove()
|
||||
var _ RequestFiller = NewRoleMemberRemove()
|
||||
@ -40,9 +40,9 @@ func NewUserList() *UserList {
|
||||
return &UserList{}
|
||||
}
|
||||
|
||||
func (u *UserList) Fill(r *http.Request) (err error) {
|
||||
func (us *UserList) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -69,15 +69,15 @@ func (u *UserList) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := get["query"]; ok {
|
||||
|
||||
u.Query = val
|
||||
us.Query = val
|
||||
}
|
||||
if val, ok := get["username"]; ok {
|
||||
|
||||
u.Username = val
|
||||
us.Username = val
|
||||
}
|
||||
if val, ok := get["email"]; ok {
|
||||
|
||||
u.Email = val
|
||||
us.Email = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -97,9 +97,9 @@ func NewUserCreate() *UserCreate {
|
||||
return &UserCreate{}
|
||||
}
|
||||
|
||||
func (u *UserCreate) Fill(r *http.Request) (err error) {
|
||||
func (us *UserCreate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -126,19 +126,19 @@ func (u *UserCreate) Fill(r *http.Request) (err error) {
|
||||
|
||||
if val, ok := post["email"]; ok {
|
||||
|
||||
u.Email = val
|
||||
us.Email = val
|
||||
}
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
u.Name = val
|
||||
us.Name = val
|
||||
}
|
||||
if val, ok := post["handle"]; ok {
|
||||
|
||||
u.Handle = val
|
||||
us.Handle = val
|
||||
}
|
||||
if val, ok := post["kind"]; ok {
|
||||
|
||||
u.Kind = val
|
||||
us.Kind = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -159,9 +159,9 @@ func NewUserUpdate() *UserUpdate {
|
||||
return &UserUpdate{}
|
||||
}
|
||||
|
||||
func (u *UserUpdate) Fill(r *http.Request) (err error) {
|
||||
func (us *UserUpdate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -186,22 +186,22 @@ func (u *UserUpdate) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
us.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
if val, ok := post["email"]; ok {
|
||||
|
||||
u.Email = val
|
||||
us.Email = val
|
||||
}
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
u.Name = val
|
||||
us.Name = val
|
||||
}
|
||||
if val, ok := post["handle"]; ok {
|
||||
|
||||
u.Handle = val
|
||||
us.Handle = val
|
||||
}
|
||||
if val, ok := post["kind"]; ok {
|
||||
|
||||
u.Kind = val
|
||||
us.Kind = val
|
||||
}
|
||||
|
||||
return err
|
||||
@ -218,9 +218,9 @@ func NewUserRead() *UserRead {
|
||||
return &UserRead{}
|
||||
}
|
||||
|
||||
func (u *UserRead) Fill(r *http.Request) (err error) {
|
||||
func (us *UserRead) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -245,7 +245,7 @@ func (u *UserRead) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
us.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
@ -261,9 +261,9 @@ func NewUserRemove() *UserRemove {
|
||||
return &UserRemove{}
|
||||
}
|
||||
|
||||
func (u *UserRemove) Fill(r *http.Request) (err error) {
|
||||
func (us *UserRemove) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -288,7 +288,7 @@ func (u *UserRemove) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
us.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
@ -304,9 +304,9 @@ func NewUserSuspend() *UserSuspend {
|
||||
return &UserSuspend{}
|
||||
}
|
||||
|
||||
func (u *UserSuspend) Fill(r *http.Request) (err error) {
|
||||
func (us *UserSuspend) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -331,7 +331,7 @@ func (u *UserSuspend) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
us.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
@ -347,9 +347,9 @@ func NewUserUnsuspend() *UserUnsuspend {
|
||||
return &UserUnsuspend{}
|
||||
}
|
||||
|
||||
func (u *UserUnsuspend) Fill(r *http.Request) (err error) {
|
||||
func (us *UserUnsuspend) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
err = json.NewDecoder(r.Body).Decode(us)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
@ -374,7 +374,7 @@ func (u *UserUnsuspend) Fill(r *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
us.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
76
system/rest/role.go
Normal file
76
system/rest/role.go
Normal file
@ -0,0 +1,76 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/system/rest/request"
|
||||
"github.com/crusttech/crust/system/service"
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Role struct {
|
||||
svc struct {
|
||||
role service.RoleService
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
func (Role) New() *Role {
|
||||
ctrl := &Role{}
|
||||
ctrl.svc.role = service.DefaultRole
|
||||
return ctrl
|
||||
}
|
||||
|
||||
func (ctrl *Role) Read(ctx context.Context, r *request.RoleRead) (interface{}, error) {
|
||||
return ctrl.svc.role.With(ctx).FindByID(r.RoleID)
|
||||
}
|
||||
|
||||
func (ctrl *Role) List(ctx context.Context, r *request.RoleList) (interface{}, error) {
|
||||
return ctrl.svc.role.With(ctx).Find(&types.RoleFilter{Query: r.Query})
|
||||
}
|
||||
|
||||
func (ctrl *Role) Create(ctx context.Context, r *request.RoleCreate) (interface{}, error) {
|
||||
org := &types.Role{
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
return ctrl.svc.role.With(ctx).Create(org)
|
||||
}
|
||||
|
||||
func (ctrl *Role) Update(ctx context.Context, r *request.RoleUpdate) (interface{}, error) {
|
||||
org := &types.Role{
|
||||
ID: r.RoleID,
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
return ctrl.svc.role.With(ctx).Update(org)
|
||||
}
|
||||
|
||||
func (ctrl *Role) Remove(ctx context.Context, r *request.RoleRemove) (interface{}, error) {
|
||||
return nil, ctrl.svc.role.With(ctx).Delete(r.RoleID)
|
||||
}
|
||||
|
||||
func (ctrl *Role) Archive(ctx context.Context, r *request.RoleArchive) (interface{}, error) {
|
||||
return nil, ctrl.svc.role.With(ctx).Archive(r.RoleID)
|
||||
}
|
||||
|
||||
func (ctrl *Role) Merge(ctx context.Context, r *request.RoleMerge) (interface{}, error) {
|
||||
return nil, ctrl.svc.role.With(ctx).Merge(r.RoleID, r.Destination)
|
||||
}
|
||||
|
||||
func (ctrl *Role) Move(ctx context.Context, r *request.RoleMove) (interface{}, error) {
|
||||
return nil, ctrl.svc.role.With(ctx).Move(r.RoleID, r.OrganisationID)
|
||||
}
|
||||
|
||||
func (ctrl *Role) MemberAdd(ctx context.Context, r *request.RoleMemberAdd) (interface{}, error) {
|
||||
return nil, ctrl.svc.role.With(ctx).MemberAdd(r.RoleID, r.UserID)
|
||||
}
|
||||
|
||||
func (ctrl *Role) MemberRemove(ctx context.Context, r *request.RoleMemberRemove) (interface{}, error) {
|
||||
return nil, ctrl.svc.role.With(ctx).MemberRemove(r.RoleID, r.UserID)
|
||||
}
|
||||
@ -47,8 +47,9 @@ func MountRoutes(oidcConfig *config.OIDC, socialConfig *config.Social, jwtEncode
|
||||
r.Use(auth.MiddlewareValidOnly)
|
||||
|
||||
handlers.NewUser(User{}.New()).MountRoutes(r)
|
||||
handlers.NewTeam(Team{}.New()).MountRoutes(r)
|
||||
handlers.NewRole(Role{}.New()).MountRoutes(r)
|
||||
handlers.NewOrganisation(Organisation{}.New()).MountRoutes(r)
|
||||
handlers.NewPermissions(Permissions{}.New()).MountRoutes(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,76 +0,0 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/system/rest/request"
|
||||
"github.com/crusttech/crust/system/service"
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Team struct {
|
||||
svc struct {
|
||||
team service.TeamService
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
func (Team) New() *Team {
|
||||
ctrl := &Team{}
|
||||
ctrl.svc.team = service.DefaultTeam
|
||||
return ctrl
|
||||
}
|
||||
|
||||
func (ctrl *Team) Read(ctx context.Context, r *request.TeamRead) (interface{}, error) {
|
||||
return ctrl.svc.team.With(ctx).FindByID(r.TeamID)
|
||||
}
|
||||
|
||||
func (ctrl *Team) List(ctx context.Context, r *request.TeamList) (interface{}, error) {
|
||||
return ctrl.svc.team.With(ctx).Find(&types.TeamFilter{Query: r.Query})
|
||||
}
|
||||
|
||||
func (ctrl *Team) Create(ctx context.Context, r *request.TeamCreate) (interface{}, error) {
|
||||
org := &types.Team{
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
return ctrl.svc.team.With(ctx).Create(org)
|
||||
}
|
||||
|
||||
func (ctrl *Team) Update(ctx context.Context, r *request.TeamUpdate) (interface{}, error) {
|
||||
org := &types.Team{
|
||||
ID: r.TeamID,
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
return ctrl.svc.team.With(ctx).Update(org)
|
||||
}
|
||||
|
||||
func (ctrl *Team) Remove(ctx context.Context, r *request.TeamRemove) (interface{}, error) {
|
||||
return nil, ctrl.svc.team.With(ctx).Delete(r.TeamID)
|
||||
}
|
||||
|
||||
func (ctrl *Team) Archive(ctx context.Context, r *request.TeamArchive) (interface{}, error) {
|
||||
return nil, ctrl.svc.team.With(ctx).Archive(r.TeamID)
|
||||
}
|
||||
|
||||
func (ctrl *Team) Merge(ctx context.Context, r *request.TeamMerge) (interface{}, error) {
|
||||
return nil, ctrl.svc.team.With(ctx).Merge(r.TeamID, r.Destination)
|
||||
}
|
||||
|
||||
func (ctrl *Team) Move(ctx context.Context, r *request.TeamMove) (interface{}, error) {
|
||||
return nil, ctrl.svc.team.With(ctx).Move(r.TeamID, r.OrganisationID)
|
||||
}
|
||||
|
||||
func (ctrl *Team) MemberAdd(ctx context.Context, r *request.TeamMemberAdd) (interface{}, error) {
|
||||
return nil, ctrl.svc.team.With(ctx).MemberAdd(r.TeamID, r.UserID)
|
||||
}
|
||||
|
||||
func (ctrl *Team) MemberRemove(ctx context.Context, r *request.TeamMemberRemove) (interface{}, error) {
|
||||
return nil, ctrl.svc.team.With(ctx).MemberRemove(r.TeamID, r.UserID)
|
||||
}
|
||||
51
system/service/permission.go
Normal file
51
system/service/permission.go
Normal file
@ -0,0 +1,51 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/crusttech/crust/internal/rules"
|
||||
"github.com/crusttech/crust/system/repository"
|
||||
)
|
||||
|
||||
type (
|
||||
permission struct {
|
||||
db db
|
||||
ctx context.Context
|
||||
|
||||
resources rules.ResourcesInterface
|
||||
}
|
||||
|
||||
PermissionService interface {
|
||||
With(ctx context.Context) PermissionService
|
||||
|
||||
Get(roleID uint64) (interface{}, error)
|
||||
Update(roleID uint64, rules []rules.Rule) (interface{}, error)
|
||||
Delete(roleID uint64) (interface{}, error)
|
||||
}
|
||||
)
|
||||
|
||||
func Permission() PermissionService {
|
||||
return (&permission{}).With(context.Background())
|
||||
}
|
||||
|
||||
func (p *permission) With(ctx context.Context) PermissionService {
|
||||
db := repository.DB(ctx)
|
||||
return &permission{
|
||||
db: db,
|
||||
ctx: ctx,
|
||||
|
||||
resources: rules.NewResources(ctx, db),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *permission) Get(roleID uint64) (interface{}, error) {
|
||||
return p.resources.List(roleID)
|
||||
}
|
||||
|
||||
func (p *permission) Update(roleID uint64, rules []rules.Rule) (interface{}, error) {
|
||||
return nil, p.resources.Grant(roleID, rules)
|
||||
}
|
||||
|
||||
func (p *permission) Delete(roleID uint64) (interface{}, error) {
|
||||
return nil, p.resources.Delete(roleID)
|
||||
}
|
||||
95
system/service/permission_test.go
Normal file
95
system/service/permission_test.go
Normal file
@ -0,0 +1,95 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
internalAuth "github.com/crusttech/crust/internal/auth"
|
||||
"github.com/crusttech/crust/internal/rules"
|
||||
. "github.com/crusttech/crust/internal/test"
|
||||
systemRepos "github.com/crusttech/crust/system/repository"
|
||||
systemTypes "github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestPermissions(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
ctx := context.TODO()
|
||||
|
||||
// Create user for test.
|
||||
userRepo := systemRepos.User(ctx, factory.Database.MustGet())
|
||||
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 = userRepo.Create(user)
|
||||
NoError(t, err, "expected no error creating user, got %v", err)
|
||||
|
||||
// Create role for test and add user
|
||||
roleRepo := systemRepos.Role(ctx, factory.Database.MustGet())
|
||||
role := &systemTypes.Role{
|
||||
Name: "Test role v1",
|
||||
}
|
||||
_, err = roleRepo.Create(role)
|
||||
NoError(t, err, "expected no error creating role, got %v", err)
|
||||
|
||||
err = roleRepo.MemberAddByID(role.ID, user.ID)
|
||||
NoError(t, err, "expected no error adding user to role, got %v", err)
|
||||
|
||||
// Set Identity.
|
||||
ctx = internalAuth.SetIdentityToContext(ctx, user)
|
||||
|
||||
// Create permission service.
|
||||
permissionSvc := Permission().With(ctx)
|
||||
|
||||
// Setup rules for test role.
|
||||
{
|
||||
rules := []rules.Rule{
|
||||
rules.Rule{Resource: "messaging:channel:*", Operation: "update", Value: rules.Allow},
|
||||
rules.Rule{Resource: "messaging:channel:1", Operation: "update", Value: rules.Deny},
|
||||
rules.Rule{Resource: "messaging:channel:2", Operation: "update"},
|
||||
rules.Rule{Resource: "system", Operation: "organisation.create", Value: rules.Allow},
|
||||
rules.Rule{Resource: "system:organisation:*", Operation: "update", Value: rules.Allow},
|
||||
rules.Rule{Resource: "system:organisation:*", Operation: "delete", Value: rules.Allow},
|
||||
rules.Rule{Resource: "messaging:channel:*", Operation: "update.name", Value: rules.Allow},
|
||||
rules.Rule{Resource: "messaging:channel:*", Operation: "update.topic", Value: rules.Allow},
|
||||
rules.Rule{Resource: "messaging:channel:*", Operation: "members.manage", Value: rules.Allow},
|
||||
}
|
||||
_, err := permissionSvc.Update(role.ID, rules)
|
||||
NoError(t, err, "expected no error, setting rules")
|
||||
}
|
||||
|
||||
// List rules for test role.
|
||||
{
|
||||
ret, err := permissionSvc.Get(role.ID)
|
||||
NoError(t, err, "expected no error, setting rules")
|
||||
|
||||
rules := ret.([]rules.Rule)
|
||||
|
||||
Assert(t, len(rules) == 8, "expected len(rules) == 8, got %v", len(rules))
|
||||
}
|
||||
|
||||
// Delete rules for test role.
|
||||
{
|
||||
_, err := permissionSvc.Delete(role.ID)
|
||||
NoError(t, err, "expected no error, setting rules")
|
||||
}
|
||||
|
||||
// List rules for test role.
|
||||
{
|
||||
ret, err := permissionSvc.Get(role.ID)
|
||||
NoError(t, err, "expected no error, setting rules")
|
||||
|
||||
rules := ret.([]rules.Rule)
|
||||
|
||||
Assert(t, len(rules) == 0, "expected len(rules) == 0, got %v", len(rules))
|
||||
}
|
||||
}
|
||||
131
system/service/role.go
Normal file
131
system/service/role.go
Normal file
@ -0,0 +1,131 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/system/repository"
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
type (
|
||||
role struct {
|
||||
db *factory.DB
|
||||
ctx context.Context
|
||||
|
||||
role repository.RoleRepository
|
||||
}
|
||||
|
||||
RoleService interface {
|
||||
With(ctx context.Context) RoleService
|
||||
|
||||
FindByID(roleID uint64) (*types.Role, error)
|
||||
Find(filter *types.RoleFilter) ([]*types.Role, error)
|
||||
|
||||
Create(role *types.Role) (*types.Role, error)
|
||||
Update(role *types.Role) (*types.Role, error)
|
||||
Merge(roleID, targetroleID uint64) error
|
||||
Move(roleID, organisationID uint64) error
|
||||
|
||||
Archive(ID uint64) error
|
||||
Unarchive(ID uint64) error
|
||||
Delete(ID uint64) error
|
||||
|
||||
MemberAdd(roleID, userID uint64) error
|
||||
MemberRemove(roleID, userID uint64) error
|
||||
}
|
||||
)
|
||||
|
||||
func Role() RoleService {
|
||||
return (&role{}).With(context.Background())
|
||||
}
|
||||
|
||||
func (svc *role) With(ctx context.Context) RoleService {
|
||||
db := repository.DB(ctx)
|
||||
return &role{
|
||||
db: db,
|
||||
ctx: ctx,
|
||||
role: repository.Role(ctx, db),
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *role) FindByID(id uint64) (*types.Role, error) {
|
||||
// @todo: permission check if current user has access to this role
|
||||
return svc.role.FindByID(id)
|
||||
}
|
||||
|
||||
func (svc *role) Find(filter *types.RoleFilter) ([]*types.Role, error) {
|
||||
// @todo: permission check to return only roles that current user has access to
|
||||
return svc.role.Find(filter)
|
||||
}
|
||||
|
||||
func (svc *role) Create(mod *types.Role) (*types.Role, error) {
|
||||
// @todo: permission check if current user can add/edit role
|
||||
|
||||
return svc.role.Create(mod)
|
||||
}
|
||||
|
||||
func (svc *role) Update(mod *types.Role) (t *types.Role, err error) {
|
||||
// @todo: permission check if current user can add/edit role
|
||||
// @todo: make sure archived & deleted entries can not be edited
|
||||
|
||||
return t, svc.db.Transaction(func() (err error) {
|
||||
if t, err = svc.role.FindByID(mod.ID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Assign changed values
|
||||
t.Name = mod.Name
|
||||
t.Handle = mod.Handle
|
||||
|
||||
if t, err = svc.role.Update(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (svc *role) Delete(id uint64) error {
|
||||
// @todo: make history unavailable
|
||||
// @todo: notify users that role has been removed (remove from web UI)
|
||||
// @todo: permissions check if current user can remove role
|
||||
return svc.role.DeleteByID(id)
|
||||
}
|
||||
|
||||
func (svc *role) Archive(id uint64) error {
|
||||
// @todo: make history unavailable
|
||||
// @todo: notify users that role has been removed (remove from web UI)
|
||||
// @todo: permissions check if current user can remove role
|
||||
return svc.role.ArchiveByID(id)
|
||||
}
|
||||
|
||||
func (svc *role) Unarchive(id uint64) error {
|
||||
// @todo: permissions check if current user can unarchive role
|
||||
// @todo: make history accessible
|
||||
// @todo: notify users that role has been unarchived
|
||||
return svc.role.UnarchiveByID(id)
|
||||
}
|
||||
|
||||
func (svc *role) Merge(id, targetroleID uint64) error {
|
||||
// @todo: permission check if current user can merge role
|
||||
return svc.role.MergeByID(id, targetroleID)
|
||||
}
|
||||
|
||||
func (svc *role) Move(id, targetOrganisationID uint64) error {
|
||||
// @todo: permission check if current user can move role to another organisation
|
||||
return svc.role.MoveByID(id, targetOrganisationID)
|
||||
}
|
||||
|
||||
func (svc *role) MemberAdd(id, userID uint64) error {
|
||||
// @todo: permission check if current user can add user in to a role
|
||||
return svc.role.MemberAddByID(id, userID)
|
||||
}
|
||||
|
||||
func (svc *role) MemberRemove(id, userID uint64) error {
|
||||
// @todo: permission check if current user can remove user from a role
|
||||
return svc.role.MemberRemoveByID(id, userID)
|
||||
}
|
||||
|
||||
var _ RoleService = &role{}
|
||||
183
system/service/role_mock_test.go
Normal file
183
system/service/role_mock_test.go
Normal file
@ -0,0 +1,183 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: system/service/role.go
|
||||
|
||||
// Package service is a generated GoMock package.
|
||||
package service
|
||||
|
||||
import (
|
||||
context "context"
|
||||
types "github.com/crusttech/crust/system/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockRoleService is a mock of RoleService interface
|
||||
type MockRoleService struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockRoleServiceMockRecorder
|
||||
}
|
||||
|
||||
// MockRoleServiceMockRecorder is the mock recorder for MockRoleService
|
||||
type MockRoleServiceMockRecorder struct {
|
||||
mock *MockRoleService
|
||||
}
|
||||
|
||||
// NewMockRoleService creates a new mock instance
|
||||
func NewMockRoleService(ctrl *gomock.Controller) *MockRoleService {
|
||||
mock := &MockRoleService{ctrl: ctrl}
|
||||
mock.recorder = &MockRoleServiceMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockRoleService) EXPECT() *MockRoleServiceMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// With mocks base method
|
||||
func (m *MockRoleService) With(ctx context.Context) RoleService {
|
||||
ret := m.ctrl.Call(m, "With", ctx)
|
||||
ret0, _ := ret[0].(RoleService)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// With indicates an expected call of With
|
||||
func (mr *MockRoleServiceMockRecorder) With(ctx interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "With", reflect.TypeOf((*MockRoleService)(nil).With), ctx)
|
||||
}
|
||||
|
||||
// FindByID mocks base method
|
||||
func (m *MockRoleService) FindByID(roleID uint64) (*types.Role, error) {
|
||||
ret := m.ctrl.Call(m, "FindByID", roleID)
|
||||
ret0, _ := ret[0].(*types.Role)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// FindByID indicates an expected call of FindByID
|
||||
func (mr *MockRoleServiceMockRecorder) FindByID(roleID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockRoleService)(nil).FindByID), roleID)
|
||||
}
|
||||
|
||||
// Find mocks base method
|
||||
func (m *MockRoleService) Find(filter *types.RoleFilter) ([]*types.Role, error) {
|
||||
ret := m.ctrl.Call(m, "Find", filter)
|
||||
ret0, _ := ret[0].([]*types.Role)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Find indicates an expected call of Find
|
||||
func (mr *MockRoleServiceMockRecorder) Find(filter interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Find", reflect.TypeOf((*MockRoleService)(nil).Find), filter)
|
||||
}
|
||||
|
||||
// Create mocks base method
|
||||
func (m *MockRoleService) Create(role *types.Role) (*types.Role, error) {
|
||||
ret := m.ctrl.Call(m, "Create", role)
|
||||
ret0, _ := ret[0].(*types.Role)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create
|
||||
func (mr *MockRoleServiceMockRecorder) Create(role interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockRoleService)(nil).Create), role)
|
||||
}
|
||||
|
||||
// Update mocks base method
|
||||
func (m *MockRoleService) Update(role *types.Role) (*types.Role, error) {
|
||||
ret := m.ctrl.Call(m, "Update", role)
|
||||
ret0, _ := ret[0].(*types.Role)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update
|
||||
func (mr *MockRoleServiceMockRecorder) Update(role interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockRoleService)(nil).Update), role)
|
||||
}
|
||||
|
||||
// Merge mocks base method
|
||||
func (m *MockRoleService) Merge(roleID, targetroleID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Merge", roleID, targetroleID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Merge indicates an expected call of Merge
|
||||
func (mr *MockRoleServiceMockRecorder) Merge(roleID, targetroleID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Merge", reflect.TypeOf((*MockRoleService)(nil).Merge), roleID, targetroleID)
|
||||
}
|
||||
|
||||
// Move mocks base method
|
||||
func (m *MockRoleService) Move(roleID, organisationID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Move", roleID, organisationID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Move indicates an expected call of Move
|
||||
func (mr *MockRoleServiceMockRecorder) Move(roleID, organisationID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Move", reflect.TypeOf((*MockRoleService)(nil).Move), roleID, organisationID)
|
||||
}
|
||||
|
||||
// Archive mocks base method
|
||||
func (m *MockRoleService) Archive(ID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Archive", ID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Archive indicates an expected call of Archive
|
||||
func (mr *MockRoleServiceMockRecorder) Archive(ID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Archive", reflect.TypeOf((*MockRoleService)(nil).Archive), ID)
|
||||
}
|
||||
|
||||
// Unarchive mocks base method
|
||||
func (m *MockRoleService) Unarchive(ID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Unarchive", ID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Unarchive indicates an expected call of Unarchive
|
||||
func (mr *MockRoleServiceMockRecorder) Unarchive(ID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unarchive", reflect.TypeOf((*MockRoleService)(nil).Unarchive), ID)
|
||||
}
|
||||
|
||||
// Delete mocks base method
|
||||
func (m *MockRoleService) Delete(ID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Delete", ID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete
|
||||
func (mr *MockRoleServiceMockRecorder) Delete(ID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockRoleService)(nil).Delete), ID)
|
||||
}
|
||||
|
||||
// MemberAdd mocks base method
|
||||
func (m *MockRoleService) MemberAdd(roleID, userID uint64) error {
|
||||
ret := m.ctrl.Call(m, "MemberAdd", roleID, userID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MemberAdd indicates an expected call of MemberAdd
|
||||
func (mr *MockRoleServiceMockRecorder) MemberAdd(roleID, userID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MemberAdd", reflect.TypeOf((*MockRoleService)(nil).MemberAdd), roleID, userID)
|
||||
}
|
||||
|
||||
// MemberRemove mocks base method
|
||||
func (m *MockRoleService) MemberRemove(roleID, userID uint64) error {
|
||||
ret := m.ctrl.Call(m, "MemberRemove", roleID, userID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MemberRemove indicates an expected call of MemberRemove
|
||||
func (mr *MockRoleServiceMockRecorder) MemberRemove(roleID, userID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MemberRemove", reflect.TypeOf((*MockRoleService)(nil).MemberRemove), roleID, userID)
|
||||
}
|
||||
@ -14,7 +14,8 @@ var (
|
||||
o sync.Once
|
||||
DefaultAuth AuthService
|
||||
DefaultUser UserService
|
||||
DefaultTeam TeamService
|
||||
DefaultRole RoleService
|
||||
DefaultPermission PermissionService
|
||||
DefaultOrganisation OrganisationService
|
||||
)
|
||||
|
||||
@ -22,7 +23,8 @@ func Init() {
|
||||
o.Do(func() {
|
||||
DefaultAuth = Auth()
|
||||
DefaultUser = User()
|
||||
DefaultTeam = Team()
|
||||
DefaultRole = Role()
|
||||
DefaultPermission = Permission()
|
||||
DefaultOrganisation = Organisation()
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/system/repository"
|
||||
"github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
type (
|
||||
team struct {
|
||||
db *factory.DB
|
||||
ctx context.Context
|
||||
|
||||
team repository.TeamRepository
|
||||
}
|
||||
|
||||
TeamService interface {
|
||||
With(ctx context.Context) TeamService
|
||||
|
||||
FindByID(teamID uint64) (*types.Team, error)
|
||||
Find(filter *types.TeamFilter) ([]*types.Team, error)
|
||||
|
||||
Create(team *types.Team) (*types.Team, error)
|
||||
Update(team *types.Team) (*types.Team, error)
|
||||
Merge(teamID, targetTeamID uint64) error
|
||||
Move(teamID, organisationID uint64) error
|
||||
|
||||
Archive(ID uint64) error
|
||||
Unarchive(ID uint64) error
|
||||
Delete(ID uint64) error
|
||||
|
||||
MemberAdd(teamID, userID uint64) error
|
||||
MemberRemove(teamID, userID uint64) error
|
||||
}
|
||||
)
|
||||
|
||||
func Team() TeamService {
|
||||
return (&team{}).With(context.Background())
|
||||
}
|
||||
|
||||
func (svc *team) With(ctx context.Context) TeamService {
|
||||
db := repository.DB(ctx)
|
||||
return &team{
|
||||
db: db,
|
||||
ctx: ctx,
|
||||
team: repository.Team(ctx, db),
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *team) FindByID(id uint64) (*types.Team, error) {
|
||||
// @todo: permission check if current user has access to this team
|
||||
return svc.team.FindByID(id)
|
||||
}
|
||||
|
||||
func (svc *team) Find(filter *types.TeamFilter) ([]*types.Team, error) {
|
||||
// @todo: permission check to return only teams that current user has access to
|
||||
return svc.team.Find(filter)
|
||||
}
|
||||
|
||||
func (svc *team) Create(mod *types.Team) (*types.Team, error) {
|
||||
// @todo: permission check if current user can add/edit team
|
||||
|
||||
return svc.team.Create(mod)
|
||||
}
|
||||
|
||||
func (svc *team) Update(mod *types.Team) (t *types.Team, err error) {
|
||||
// @todo: permission check if current user can add/edit team
|
||||
// @todo: make sure archived & deleted entries can not be edited
|
||||
|
||||
return t, svc.db.Transaction(func() (err error) {
|
||||
if t, err = svc.team.FindByID(mod.ID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Assign changed values
|
||||
t.Name = mod.Name
|
||||
t.Handle = mod.Handle
|
||||
|
||||
if t, err = svc.team.Update(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (svc *team) Delete(id uint64) error {
|
||||
// @todo: make history unavailable
|
||||
// @todo: notify users that team has been removed (remove from web UI)
|
||||
// @todo: permissions check if current user can remove team
|
||||
return svc.team.DeleteByID(id)
|
||||
}
|
||||
|
||||
func (svc *team) Archive(id uint64) error {
|
||||
// @todo: make history unavailable
|
||||
// @todo: notify users that team has been removed (remove from web UI)
|
||||
// @todo: permissions check if current user can remove team
|
||||
return svc.team.ArchiveByID(id)
|
||||
}
|
||||
|
||||
func (svc *team) Unarchive(id uint64) error {
|
||||
// @todo: permissions check if current user can unarchive team
|
||||
// @todo: make history accessible
|
||||
// @todo: notify users that team has been unarchived
|
||||
return svc.team.UnarchiveByID(id)
|
||||
}
|
||||
|
||||
func (svc *team) Merge(id, targetTeamID uint64) error {
|
||||
// @todo: permission check if current user can merge team
|
||||
return svc.team.MergeByID(id, targetTeamID)
|
||||
}
|
||||
|
||||
func (svc *team) Move(id, targetOrganisationID uint64) error {
|
||||
// @todo: permission check if current user can move team to another organisation
|
||||
return svc.team.MoveByID(id, targetOrganisationID)
|
||||
}
|
||||
|
||||
func (svc *team) MemberAdd(id, userID uint64) error {
|
||||
// @todo: permission check if current user can add user in to a team
|
||||
return svc.team.MemberAddByID(id, userID)
|
||||
}
|
||||
|
||||
func (svc *team) MemberRemove(id, userID uint64) error {
|
||||
// @todo: permission check if current user can remove user from a team
|
||||
return svc.team.MemberRemoveByID(id, userID)
|
||||
}
|
||||
|
||||
var _ TeamService = &team{}
|
||||
@ -1,183 +0,0 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: system/service/team.go
|
||||
|
||||
// Package service is a generated GoMock package.
|
||||
package service
|
||||
|
||||
import (
|
||||
context "context"
|
||||
types "github.com/crusttech/crust/system/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockTeamService is a mock of TeamService interface
|
||||
type MockTeamService struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockTeamServiceMockRecorder
|
||||
}
|
||||
|
||||
// MockTeamServiceMockRecorder is the mock recorder for MockTeamService
|
||||
type MockTeamServiceMockRecorder struct {
|
||||
mock *MockTeamService
|
||||
}
|
||||
|
||||
// NewMockTeamService creates a new mock instance
|
||||
func NewMockTeamService(ctrl *gomock.Controller) *MockTeamService {
|
||||
mock := &MockTeamService{ctrl: ctrl}
|
||||
mock.recorder = &MockTeamServiceMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockTeamService) EXPECT() *MockTeamServiceMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// With mocks base method
|
||||
func (m *MockTeamService) With(ctx context.Context) TeamService {
|
||||
ret := m.ctrl.Call(m, "With", ctx)
|
||||
ret0, _ := ret[0].(TeamService)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// With indicates an expected call of With
|
||||
func (mr *MockTeamServiceMockRecorder) With(ctx interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "With", reflect.TypeOf((*MockTeamService)(nil).With), ctx)
|
||||
}
|
||||
|
||||
// FindByID mocks base method
|
||||
func (m *MockTeamService) FindByID(teamID uint64) (*types.Team, error) {
|
||||
ret := m.ctrl.Call(m, "FindByID", teamID)
|
||||
ret0, _ := ret[0].(*types.Team)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// FindByID indicates an expected call of FindByID
|
||||
func (mr *MockTeamServiceMockRecorder) FindByID(teamID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockTeamService)(nil).FindByID), teamID)
|
||||
}
|
||||
|
||||
// Find mocks base method
|
||||
func (m *MockTeamService) Find(filter *types.TeamFilter) ([]*types.Team, error) {
|
||||
ret := m.ctrl.Call(m, "Find", filter)
|
||||
ret0, _ := ret[0].([]*types.Team)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Find indicates an expected call of Find
|
||||
func (mr *MockTeamServiceMockRecorder) Find(filter interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Find", reflect.TypeOf((*MockTeamService)(nil).Find), filter)
|
||||
}
|
||||
|
||||
// Create mocks base method
|
||||
func (m *MockTeamService) Create(team *types.Team) (*types.Team, error) {
|
||||
ret := m.ctrl.Call(m, "Create", team)
|
||||
ret0, _ := ret[0].(*types.Team)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create
|
||||
func (mr *MockTeamServiceMockRecorder) Create(team interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockTeamService)(nil).Create), team)
|
||||
}
|
||||
|
||||
// Update mocks base method
|
||||
func (m *MockTeamService) Update(team *types.Team) (*types.Team, error) {
|
||||
ret := m.ctrl.Call(m, "Update", team)
|
||||
ret0, _ := ret[0].(*types.Team)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update
|
||||
func (mr *MockTeamServiceMockRecorder) Update(team interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockTeamService)(nil).Update), team)
|
||||
}
|
||||
|
||||
// Merge mocks base method
|
||||
func (m *MockTeamService) Merge(teamID, targetTeamID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Merge", teamID, targetTeamID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Merge indicates an expected call of Merge
|
||||
func (mr *MockTeamServiceMockRecorder) Merge(teamID, targetTeamID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Merge", reflect.TypeOf((*MockTeamService)(nil).Merge), teamID, targetTeamID)
|
||||
}
|
||||
|
||||
// Move mocks base method
|
||||
func (m *MockTeamService) Move(teamID, organisationID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Move", teamID, organisationID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Move indicates an expected call of Move
|
||||
func (mr *MockTeamServiceMockRecorder) Move(teamID, organisationID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Move", reflect.TypeOf((*MockTeamService)(nil).Move), teamID, organisationID)
|
||||
}
|
||||
|
||||
// Archive mocks base method
|
||||
func (m *MockTeamService) Archive(ID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Archive", ID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Archive indicates an expected call of Archive
|
||||
func (mr *MockTeamServiceMockRecorder) Archive(ID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Archive", reflect.TypeOf((*MockTeamService)(nil).Archive), ID)
|
||||
}
|
||||
|
||||
// Unarchive mocks base method
|
||||
func (m *MockTeamService) Unarchive(ID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Unarchive", ID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Unarchive indicates an expected call of Unarchive
|
||||
func (mr *MockTeamServiceMockRecorder) Unarchive(ID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unarchive", reflect.TypeOf((*MockTeamService)(nil).Unarchive), ID)
|
||||
}
|
||||
|
||||
// Delete mocks base method
|
||||
func (m *MockTeamService) Delete(ID uint64) error {
|
||||
ret := m.ctrl.Call(m, "Delete", ID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete
|
||||
func (mr *MockTeamServiceMockRecorder) Delete(ID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockTeamService)(nil).Delete), ID)
|
||||
}
|
||||
|
||||
// MemberAdd mocks base method
|
||||
func (m *MockTeamService) MemberAdd(teamID, userID uint64) error {
|
||||
ret := m.ctrl.Call(m, "MemberAdd", teamID, userID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MemberAdd indicates an expected call of MemberAdd
|
||||
func (mr *MockTeamServiceMockRecorder) MemberAdd(teamID, userID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MemberAdd", reflect.TypeOf((*MockTeamService)(nil).MemberAdd), teamID, userID)
|
||||
}
|
||||
|
||||
// MemberRemove mocks base method
|
||||
func (m *MockTeamService) MemberRemove(teamID, userID uint64) error {
|
||||
ret := m.ctrl.Call(m, "MemberRemove", teamID, userID)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MemberRemove indicates an expected call of MemberRemove
|
||||
func (mr *MockTeamServiceMockRecorder) MemberRemove(teamID, userID interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MemberRemove", reflect.TypeOf((*MockTeamService)(nil).MemberRemove), teamID, userID)
|
||||
}
|
||||
@ -8,16 +8,16 @@ import (
|
||||
|
||||
type (
|
||||
|
||||
// TeamSet slice of Team
|
||||
// RoleSet slice of Role
|
||||
//
|
||||
// This type is auto-generated.
|
||||
TeamSet []*Team
|
||||
RoleSet []*Role
|
||||
)
|
||||
|
||||
// Walk iterates through every slice item and calls w(Team) err
|
||||
// Walk iterates through every slice item and calls w(Role) err
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func (set TeamSet) Walk(w func(*Team) error) (err error) {
|
||||
func (set RoleSet) Walk(w func(*Role) error) (err error) {
|
||||
for i := range set {
|
||||
if err = w(set[i]); err != nil {
|
||||
return
|
||||
@ -27,12 +27,12 @@ func (set TeamSet) Walk(w func(*Team) error) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Filter iterates through every slice item, calls f(Team) (bool, err) and return filtered slice
|
||||
// Filter iterates through every slice item, calls f(Role) (bool, err) and return filtered slice
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func (set TeamSet) Filter(f func(*Team) (bool, error)) (out TeamSet, err error) {
|
||||
func (set RoleSet) Filter(f func(*Role) (bool, error)) (out RoleSet, err error) {
|
||||
var ok bool
|
||||
out = TeamSet{}
|
||||
out = RoleSet{}
|
||||
for i := range set {
|
||||
if ok, err = f(set[i]); err != nil {
|
||||
return
|
||||
@ -47,7 +47,7 @@ func (set TeamSet) Filter(f func(*Team) (bool, error)) (out TeamSet, err error)
|
||||
// FindByID finds items from slice by its ID property
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func (set TeamSet) FindByID(ID uint64) *Team {
|
||||
func (set RoleSet) FindByID(ID uint64) *Role {
|
||||
for i := range set {
|
||||
if set[i].ID == ID {
|
||||
return set[i]
|
||||
@ -60,7 +60,7 @@ func (set TeamSet) FindByID(ID uint64) *Team {
|
||||
// IDs returns a slice of uint64s from all items in the set
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func (set TeamSet) IDs() (IDs []uint64) {
|
||||
func (set RoleSet) IDs() (IDs []uint64) {
|
||||
IDs = make([]uint64, len(set))
|
||||
|
||||
for i := range set {
|
||||
@ -73,7 +73,7 @@ func (set TeamSet) IDs() (IDs []uint64) {
|
||||
// Resources returns a slice of types.Resource from all items in the set
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func (set TeamSet) Resources() (Resources []rules.Resource) {
|
||||
func (set RoleSet) Resources() (Resources []rules.Resource) {
|
||||
Resources = make([]rules.Resource, len(set))
|
||||
|
||||
for i := range set {
|
||||
@ -7,9 +7,9 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// Teams - An organisation may have many teams. Teams may have many channels available. Access to channels may be shared between teams.
|
||||
Team struct {
|
||||
ID uint64 `json:"teamID,string" db:"id"`
|
||||
// Role - An organisation may have many roles. Roles may have many channels available. Access to channels may be shared between roles.
|
||||
Role struct {
|
||||
ID uint64 `json:"roleID,string" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Handle string `json:"handle" db:"handle"`
|
||||
CreatedAt time.Time `json:"createdAt,omitempty" db:"created_at"`
|
||||
@ -18,13 +18,13 @@ type (
|
||||
DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"`
|
||||
}
|
||||
|
||||
TeamFilter struct {
|
||||
RoleFilter struct {
|
||||
Query string
|
||||
}
|
||||
)
|
||||
|
||||
// Resource returns a system resource ID for this type
|
||||
func (r *Team) Resource() rules.Resource {
|
||||
func (r *Role) Resource() rules.Resource {
|
||||
resource := rules.Resource{
|
||||
Scope: "team",
|
||||
}
|
||||
12
system/types/role_members.go
Normal file
12
system/types/role_members.go
Normal file
@ -0,0 +1,12 @@
|
||||
package types
|
||||
|
||||
type (
|
||||
RoleMember struct {
|
||||
RoleID uint64 `db:"rel_role"`
|
||||
UserID uint64 `db:"rel_user"`
|
||||
}
|
||||
|
||||
RoleMemberFilter struct {
|
||||
Query string
|
||||
}
|
||||
)
|
||||
@ -1,12 +0,0 @@
|
||||
package types
|
||||
|
||||
type (
|
||||
TeamMember struct {
|
||||
TeamID uint64 `db:"rel_team"`
|
||||
UserID uint64 `db:"rel_user"`
|
||||
}
|
||||
|
||||
TeamMemberFilter struct {
|
||||
Query string
|
||||
}
|
||||
)
|
||||
@ -29,7 +29,7 @@ type (
|
||||
SuspendedAt *time.Time `json:"suspendedAt,omitempty" db:"suspended_at"`
|
||||
DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"`
|
||||
|
||||
Teams []*Team `json:"teams,omitempty" db:"-"`
|
||||
Roles []*Role `json:"roles,omitempty" db:"-"`
|
||||
}
|
||||
|
||||
UserFilter struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user