mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
SMQ 2667 - List all the users who can access the entity (#2673)
Signed-off-by: Arvindh <arvindh91@gmail.com>
This commit is contained in:
+57
-60
@@ -20,62 +20,63 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
MemberKindKey = "member_kind"
|
||||
PermissionKey = "permission"
|
||||
RelationKey = "relation"
|
||||
StatusKey = "status"
|
||||
OffsetKey = "offset"
|
||||
OrderKey = "order"
|
||||
LimitKey = "limit"
|
||||
MetadataKey = "metadata"
|
||||
ParentKey = "parent_id"
|
||||
OwnerKey = "owner_id"
|
||||
ClientKey = "client"
|
||||
UsernameKey = "username"
|
||||
NameKey = "name"
|
||||
GroupKey = "group"
|
||||
ActionKey = "action"
|
||||
ActionsKey = "actions"
|
||||
RoleIDKey = "role_id"
|
||||
RoleNameKey = "role_name"
|
||||
AccessTypeKey = "access_type"
|
||||
TagKey = "tag"
|
||||
FirstNameKey = "first_name"
|
||||
LastNameKey = "last_name"
|
||||
TotalKey = "total"
|
||||
SubjectKey = "subject"
|
||||
ObjectKey = "object"
|
||||
LevelKey = "level"
|
||||
StartLevelKey = "start_level"
|
||||
EndLevelKey = "end_level"
|
||||
TreeKey = "tree"
|
||||
DirKey = "dir"
|
||||
ListPerms = "list_perms"
|
||||
VisibilityKey = "visibility"
|
||||
EmailKey = "email"
|
||||
SharedByKey = "shared_by"
|
||||
TokenKey = "token"
|
||||
UserKey = "user"
|
||||
DomainKey = "domain"
|
||||
ChannelKey = "channel"
|
||||
ConnTypeKey = "connection_type"
|
||||
DefPermission = "read_permission"
|
||||
DefTotal = uint64(100)
|
||||
DefOffset = 0
|
||||
DefOrder = "updated_at"
|
||||
DefDir = "asc"
|
||||
DefLimit = 10
|
||||
DefLevel = 0
|
||||
DefStartLevel = 1
|
||||
DefEndLevel = 0
|
||||
DefStatus = "enabled"
|
||||
DefClientStatus = clients.Enabled
|
||||
DefUserStatus = users.Enabled
|
||||
DefGroupStatus = groups.Enabled
|
||||
DefListPerms = false
|
||||
SharedVisibility = "shared"
|
||||
MyVisibility = "mine"
|
||||
AllVisibility = "all"
|
||||
OffsetKey = "offset"
|
||||
DirKey = "dir"
|
||||
OrderKey = "order"
|
||||
LimitKey = "limit"
|
||||
|
||||
NameOrder = "name"
|
||||
IDOrder = "id"
|
||||
AscDir = "asc"
|
||||
DescDir = "desc"
|
||||
|
||||
MetadataKey = "metadata"
|
||||
NameKey = "name"
|
||||
TagKey = "tag"
|
||||
StatusKey = "status"
|
||||
|
||||
ClientKey = "client"
|
||||
ChannelKey = "channel"
|
||||
ConnTypeKey = "connection_type"
|
||||
GroupKey = "group"
|
||||
DomainKey = "domain"
|
||||
|
||||
StartLevelKey = "start_level"
|
||||
EndLevelKey = "end_level"
|
||||
TreeKey = "tree"
|
||||
ParentKey = "parent_id"
|
||||
LevelKey = "level"
|
||||
|
||||
TokenKey = "token"
|
||||
SubjectKey = "subject"
|
||||
ObjectKey = "object"
|
||||
|
||||
ActionKey = "action"
|
||||
ActionsKey = "actions"
|
||||
RoleIDKey = "role_id"
|
||||
RoleNameKey = "role_name"
|
||||
AccessProviderIDKey = "access_provider_id"
|
||||
AccessTypeKey = "access_type"
|
||||
|
||||
UsernameKey = "username"
|
||||
UserKey = "user"
|
||||
EmailKey = "email"
|
||||
FirstNameKey = "first_name"
|
||||
LastNameKey = "last_name"
|
||||
|
||||
DefTotal = uint64(100)
|
||||
DefOffset = 0
|
||||
DefOrder = "updated_at"
|
||||
DefDir = "asc"
|
||||
DefLimit = 10
|
||||
DefLevel = 0
|
||||
DefStartLevel = 1
|
||||
DefEndLevel = 0
|
||||
DefStatus = "enabled"
|
||||
DefClientStatus = clients.Enabled
|
||||
DefUserStatus = users.Enabled
|
||||
DefGroupStatus = groups.Enabled
|
||||
|
||||
// ContentType represents JSON content type.
|
||||
ContentType = "application/json"
|
||||
|
||||
@@ -83,10 +84,6 @@ const (
|
||||
MaxLimitSize = 100
|
||||
MaxNameSize = 1024
|
||||
MaxIDSize = 36
|
||||
NameOrder = "name"
|
||||
IDOrder = "id"
|
||||
AscDir = "asc"
|
||||
DescDir = "desc"
|
||||
)
|
||||
|
||||
// ValidateUUID validates UUID format.
|
||||
|
||||
@@ -141,6 +141,9 @@ var (
|
||||
// ErrInvalidComparator indicates an invalid comparator.
|
||||
ErrInvalidComparator = errors.New("invalid comparator")
|
||||
|
||||
// ErrMissingMemberIDs indicates missing member ids.
|
||||
ErrMissingMemberIDs = errors.New("missing member ids")
|
||||
|
||||
// ErrMissingMemberType indicates missing group member type.
|
||||
ErrMissingMemberType = errors.New("missing group member type")
|
||||
|
||||
|
||||
@@ -520,6 +520,36 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/clients/{clientID}/roles/members:
|
||||
get:
|
||||
operationId: getClientMembers
|
||||
tags:
|
||||
- Roles
|
||||
summary: Retrieves client members from all roles.
|
||||
description: |
|
||||
Retrieves members from role for the specific client.
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/clientID"
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
$ref: "./schemas/roles.yml#/components/responses/ListEntityMembersRes"
|
||||
"400":
|
||||
description: Failed due to malformed query parameters.
|
||||
"401":
|
||||
description: |
|
||||
Missing or invalid access token provided.
|
||||
"403":
|
||||
description: Failed to perform authorization over the entity.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/clients/{clientID}/roles/{roleID}:
|
||||
get:
|
||||
operationId: getClientRole
|
||||
|
||||
@@ -379,6 +379,35 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/domain/{domainID}/roles/members:
|
||||
get:
|
||||
operationId: getDomainMembers
|
||||
tags:
|
||||
- Roles
|
||||
summary: Retrieves domain members from all roles.
|
||||
description: |
|
||||
Retrieves members from role for the specific domain.
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
$ref: "./schemas/roles.yml#/components/responses/ListEntityMembersRes"
|
||||
"400":
|
||||
description: Failed due to malformed query parameters.
|
||||
"401":
|
||||
description: |
|
||||
Missing or invalid access token provided.
|
||||
"403":
|
||||
description: Failed to perform authorization over the entity.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/domains/{domainID}/roles/{roleID}/actions:
|
||||
post:
|
||||
operationId: addDomainRoleAction
|
||||
|
||||
@@ -564,6 +564,36 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/groups/{groupID}/roles/members:
|
||||
get:
|
||||
operationId: getGroupMembers
|
||||
tags:
|
||||
- Roles
|
||||
summary: Retrieves group members from all roles.
|
||||
description: |
|
||||
Retrieves members from role for the specific group.
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/GroupID"
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
$ref: "./schemas/roles.yml#/components/responses/ListEntityMembersRes"
|
||||
"400":
|
||||
description: Failed due to malformed query parameters.
|
||||
"401":
|
||||
description: |
|
||||
Missing or invalid access token provided.
|
||||
"403":
|
||||
description: Failed to perform authorization over the entity.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/groups/{groupID}/roles/{roleID}:
|
||||
get:
|
||||
operationId: getGroupRole
|
||||
|
||||
@@ -135,6 +135,31 @@ components:
|
||||
example: 10
|
||||
description: Maximum number of items to return in one page.
|
||||
|
||||
EntityMembersPage:
|
||||
type: object
|
||||
properties:
|
||||
groups:
|
||||
type: array
|
||||
minItems: 0
|
||||
uniqueItems: true
|
||||
items:
|
||||
$ref: "#/components/schemas/EntityMembersObj"
|
||||
total:
|
||||
type: integer
|
||||
example: 1
|
||||
description: Total number of items.
|
||||
offset:
|
||||
type: integer
|
||||
description: Number of items to skip during retrieval.
|
||||
limit:
|
||||
type: integer
|
||||
example: 10
|
||||
description: Maximum number of items to return in one page.
|
||||
required:
|
||||
- groups
|
||||
- total
|
||||
- offset
|
||||
|
||||
RoleActionsObj:
|
||||
type: object
|
||||
properties:
|
||||
@@ -163,6 +188,57 @@ components:
|
||||
"c01ed106-e52d-4aa4-bed3-39f360177cfa",
|
||||
]
|
||||
|
||||
EntityMembersObj:
|
||||
type: object
|
||||
properties:
|
||||
members:
|
||||
type: array
|
||||
description: List of members with assigned roles and actions.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique identifier of the member.
|
||||
roles:
|
||||
type: array
|
||||
description: List of roles assigned to the member.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique identifier of the role.
|
||||
name:
|
||||
type: string
|
||||
description: Name of the role.
|
||||
actions:
|
||||
type: array
|
||||
description: List of actions the member can perform.
|
||||
items:
|
||||
type: string
|
||||
access_type:
|
||||
type: string
|
||||
description: Type of access granted.
|
||||
enum: [read, write, admin] # Adjust based on your actual access types.
|
||||
example:
|
||||
members:
|
||||
- id: "5dc1ce4b-7cc9-4f12-98a6-9d74cc4980bb"
|
||||
roles:
|
||||
- id: "a1b2c3d4-e5f6-7890-1234-56789abcdef0"
|
||||
name: "Admin"
|
||||
actions: ["create", "update", "delete"]
|
||||
access_type: "admin"
|
||||
- id: "c01ed106-e52d-4aa4-bed3-39f360177cfa"
|
||||
roles:
|
||||
- id: "b2c3d4e5-f678-9012-3456-789abcdef012"
|
||||
name: "Editor"
|
||||
actions: ["read", "update"]
|
||||
access_type: "write"
|
||||
|
||||
|
||||
AvailableActionsObj:
|
||||
type: object
|
||||
properties:
|
||||
@@ -284,3 +360,11 @@ components:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AvailableActionsObj'
|
||||
|
||||
|
||||
ListEntityMembersRes:
|
||||
description: Entity members retrieved successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/EntityMembersObj'
|
||||
|
||||
+1
-182
@@ -550,155 +550,6 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/groups/{groupID}/users:
|
||||
get:
|
||||
operationId: listUsersInGroup
|
||||
tags:
|
||||
- Users
|
||||
summary: List users in a group
|
||||
description: |
|
||||
Retrieves a list of users in a group. Due to performance concerns, data
|
||||
is retrieved in subsets. The API must ensure that the entire
|
||||
dataset is consumed either by making subsequent requests, or by
|
||||
increasing the subset size of the initial request.
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/GroupID"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
- $ref: "#/components/parameters/Offset"
|
||||
- $ref: "#/components/parameters/Level"
|
||||
- $ref: "#/components/parameters/Tree"
|
||||
- $ref: "#/components/parameters/Metadata"
|
||||
- $ref: "#/components/parameters/GroupName"
|
||||
- $ref: "#/components/parameters/ParentID"
|
||||
responses:
|
||||
"200":
|
||||
$ref: "#/components/responses/MembersPageRes"
|
||||
"400":
|
||||
description: Failed due to malformed query parameters.
|
||||
"401":
|
||||
description: |
|
||||
Missing or invalid access token provided.
|
||||
This endpoint is available only for administrators.
|
||||
"403":
|
||||
description: Failed to perform authorization over the entity.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/channels/{channelID}/users:
|
||||
get:
|
||||
operationId: listUsersInChannel
|
||||
tags:
|
||||
- Users
|
||||
summary: List users in a channel
|
||||
description: |
|
||||
Retrieves a list of users in a channel. Due to performance concerns, data
|
||||
is retrieved in subsets. The API must ensure that the entire
|
||||
dataset is consumed either by making subsequent requests, or by
|
||||
increasing the subset size of the initial request.
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/ChannelID"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
- $ref: "#/components/parameters/Offset"
|
||||
- $ref: "#/components/parameters/Level"
|
||||
- $ref: "#/components/parameters/Tree"
|
||||
- $ref: "#/components/parameters/Metadata"
|
||||
- $ref: "#/components/parameters/ChannelName"
|
||||
- $ref: "#/components/parameters/ParentID"
|
||||
responses:
|
||||
"200":
|
||||
$ref: "#/components/responses/MembersPageRes"
|
||||
"400":
|
||||
description: Failed due to malformed query parameters.
|
||||
"401":
|
||||
description: |
|
||||
Missing or invalid access token provided.
|
||||
This endpoint is available only for administrators.
|
||||
"403":
|
||||
description: Failed to perform authorization over the entity.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/clients/{clientID}/users:
|
||||
get:
|
||||
operationId: listUsersInClient
|
||||
tags:
|
||||
- Users
|
||||
summary: List users associated with a client
|
||||
description: |
|
||||
Retrieves a list of users associated with a client. Due to performance concerns, data
|
||||
is retrieved in subsets. The API must ensure that the entire
|
||||
dataset is consumed either by making subsequent requests, or by
|
||||
increasing the subset size of the initial request.
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/ClientID"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
- $ref: "#/components/parameters/Offset"
|
||||
- $ref: "#/components/parameters/Level"
|
||||
- $ref: "#/components/parameters/Tree"
|
||||
- $ref: "#/components/parameters/Metadata"
|
||||
- $ref: "#/components/parameters/ChannelName"
|
||||
- $ref: "#/components/parameters/ParentID"
|
||||
responses:
|
||||
"200":
|
||||
$ref: "#/components/responses/MembersPageRes"
|
||||
"400":
|
||||
description: Failed due to malformed query parameters.
|
||||
"401":
|
||||
description: |
|
||||
Missing or invalid access token provided.
|
||||
This endpoint is available only for administrators.
|
||||
"403":
|
||||
description: Failed to perform authorization over the entity.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/{domainID}/users:
|
||||
get:
|
||||
summary: List users assigned to domain
|
||||
description: |
|
||||
List users assigned to domain that is identified by the domain ID.
|
||||
tags:
|
||||
- Users
|
||||
parameters:
|
||||
- $ref: "auth.yml#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
- $ref: "#/components/parameters/Offset"
|
||||
- $ref: "#/components/parameters/Metadata"
|
||||
- $ref: "#/components/parameters/Status"
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
$ref: "#/components/responses/UserPageRes"
|
||||
description: List of users assigned to domain.
|
||||
"400":
|
||||
description: Failed due to malformed domain's ID.
|
||||
"401":
|
||||
description: Missing or invalid access token provided.
|
||||
"403":
|
||||
description: Unauthorized access the domain ID.
|
||||
"404":
|
||||
description: A non-existent entity request.
|
||||
"422":
|
||||
description: Database can't process request.
|
||||
"500":
|
||||
$ref: "#/components/responses/ServiceError"
|
||||
|
||||
/users/tokens/issue:
|
||||
post:
|
||||
operationId: issueToken
|
||||
@@ -963,31 +814,6 @@ components:
|
||||
- total
|
||||
- offset
|
||||
|
||||
MembersPage:
|
||||
type: object
|
||||
properties:
|
||||
members:
|
||||
type: array
|
||||
minItems: 0
|
||||
uniqueItems: true
|
||||
items:
|
||||
$ref: "#/components/schemas/Members"
|
||||
total:
|
||||
type: integer
|
||||
example: 1
|
||||
description: Total number of items.
|
||||
offset:
|
||||
type: integer
|
||||
description: Number of items to skip during retrieval.
|
||||
limit:
|
||||
type: integer
|
||||
example: 10
|
||||
description: Maximum number of items to return in one page.
|
||||
required:
|
||||
- members
|
||||
- total
|
||||
- level
|
||||
|
||||
UserUpdate:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1310,7 +1136,7 @@ components:
|
||||
pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$"
|
||||
required: true
|
||||
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
|
||||
|
||||
|
||||
ClientID:
|
||||
name: clientID
|
||||
description: Unique client identifier.
|
||||
@@ -1629,13 +1455,6 @@ components:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UsersPage"
|
||||
|
||||
MembersPageRes:
|
||||
description: Group members retrieved.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MembersPage"
|
||||
|
||||
TokenRes:
|
||||
description: JSON-formated document describing the user access token used for authenticating into the syetem and refresh token used for generating another access token
|
||||
content:
|
||||
|
||||
@@ -187,6 +187,34 @@ func (_m *Repository) DoesChannelHaveConnections(ctx context.Context, id string)
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, entityID, pageQuery
|
||||
func (_m *Repository) ListEntityMembers(ctx context.Context, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, entityID, pageQuery)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, entityID, pageQuery)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Remove provides a mock function with given fields: ctx, ids
|
||||
func (_m *Repository) Remove(ctx context.Context, ids ...string) error {
|
||||
_va := make([]interface{}, len(ids))
|
||||
@@ -266,6 +294,24 @@ func (_m *Repository) RemoveConnections(ctx context.Context, conns []channels.Co
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, entityID, members
|
||||
func (_m *Repository) RemoveEntityMembers(ctx context.Context, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok {
|
||||
r0 = rf(ctx, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, memberID
|
||||
func (_m *Repository) RemoveMemberFromAllRoles(ctx context.Context, memberID string) error {
|
||||
ret := _m.Called(ctx, memberID)
|
||||
|
||||
@@ -246,6 +246,34 @@ func (_m *Service) ListChannels(ctx context.Context, session authn.Session, pm c
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, session, entityID, pq
|
||||
func (_m *Service) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pq roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, session, entityID, pq)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, session, entityID, pq)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListUserChannels provides a mock function with given fields: ctx, session, userID, pm
|
||||
func (_m *Service) ListUserChannels(ctx context.Context, session authn.Session, userID string, pm channels.PageMetadata) (channels.Page, error) {
|
||||
ret := _m.Called(ctx, session, userID, pm)
|
||||
@@ -292,6 +320,24 @@ func (_m *Service) RemoveChannel(ctx context.Context, session authn.Session, id
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, session, entityID, members
|
||||
func (_m *Service) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, session, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, []string) error); ok {
|
||||
r0 = rf(ctx, session, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, session, memberID
|
||||
func (_m *Service) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) error {
|
||||
ret := _m.Called(ctx, session, memberID)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/connections"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
"github.com/jackc/pgtype"
|
||||
@@ -40,7 +41,7 @@ type channelRepository struct {
|
||||
// NewChannelRepository instantiates a PostgreSQL implementation of channel
|
||||
// repository.
|
||||
func NewRepository(db postgres.Database) channels.Repository {
|
||||
rolesRepo := rolesPostgres.NewRepository(db, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
rolesRepo := rolesPostgres.NewRepository(db, policies.ChannelType, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
return &channelRepository{
|
||||
db: db,
|
||||
Repository: rolesRepo,
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ var cmdChannels = []cobra.Command{
|
||||
Offset: Offset,
|
||||
Limit: Limit,
|
||||
}
|
||||
ul, err := sdk.ListChannelUsers(args[0], args[1], pm, args[2])
|
||||
ul, err := sdk.ListChannelMembers(args[0], args[1], pm, args[2])
|
||||
if err != nil {
|
||||
logErrorCmd(*cmd, err)
|
||||
return
|
||||
|
||||
+1
-1
@@ -275,7 +275,7 @@ var cmdClients = []cobra.Command{
|
||||
Offset: Offset,
|
||||
Limit: Limit,
|
||||
}
|
||||
ul, err := sdk.ListClientUsers(args[0], args[1], pm, args[2])
|
||||
ul, err := sdk.ListClientMembers(args[0], args[1], pm, args[2])
|
||||
if err != nil {
|
||||
logErrorCmd(*cmd, err)
|
||||
return
|
||||
|
||||
+5
-95
@@ -23,12 +23,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
token = "valid" + "domaintoken"
|
||||
domainID = "domain-id"
|
||||
tokenWithoutDomain = "valid"
|
||||
relation = "administrator"
|
||||
all = "all"
|
||||
conntype = `["publish","subscribe"]`
|
||||
token = "valid" + "domaintoken"
|
||||
domainID = "domain-id"
|
||||
relation = "administrator"
|
||||
all = "all"
|
||||
conntype = `["publish","subscribe"]`
|
||||
)
|
||||
|
||||
var client = smqsdk.Client{
|
||||
@@ -711,95 +710,6 @@ func TestDisableclientCmd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsersClientCmd(t *testing.T) {
|
||||
sdkMock := new(sdkmocks.SDK)
|
||||
cli.SetSDK(sdkMock)
|
||||
clientsCmd := cli.NewClientsCmd()
|
||||
rootCmd := setFlags(clientsCmd)
|
||||
|
||||
page := smqsdk.UsersPage{}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
args []string
|
||||
logType outputLog
|
||||
errLogMessage string
|
||||
page smqsdk.UsersPage
|
||||
sdkErr errors.SDKError
|
||||
}{
|
||||
{
|
||||
desc: "get client's users successfully",
|
||||
args: []string{
|
||||
client.ID,
|
||||
domainID,
|
||||
token,
|
||||
},
|
||||
page: smqsdk.UsersPage{
|
||||
PageRes: smqsdk.PageRes{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
},
|
||||
Users: []smqsdk.User{user},
|
||||
},
|
||||
logType: entityLog,
|
||||
},
|
||||
{
|
||||
desc: "list client users' with invalid args",
|
||||
args: []string{
|
||||
client.ID,
|
||||
domainID,
|
||||
token,
|
||||
extraArg,
|
||||
},
|
||||
logType: usageLog,
|
||||
},
|
||||
{
|
||||
desc: "list client users' with invalid domain",
|
||||
args: []string{
|
||||
client.ID,
|
||||
invalidID,
|
||||
token,
|
||||
},
|
||||
sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden),
|
||||
errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)),
|
||||
logType: errLog,
|
||||
},
|
||||
{
|
||||
desc: "list client users with invalid id",
|
||||
args: []string{
|
||||
invalidID,
|
||||
domainID,
|
||||
token,
|
||||
},
|
||||
sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
|
||||
errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)),
|
||||
logType: errLog,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
sdkCall := sdkMock.On("ListClientUsers", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr)
|
||||
out := executeCommand(t, rootCmd, append([]string{usrCmd}, tc.args...)...)
|
||||
|
||||
switch tc.logType {
|
||||
case entityLog:
|
||||
err := json.Unmarshal([]byte(out), &page)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unmarshal JSON: %v", err)
|
||||
}
|
||||
assert.Equal(t, tc.page, page, fmt.Sprintf("%v unexpected response, expected: %v, got: %v", tc.desc, tc.page, page))
|
||||
case usageLog:
|
||||
assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out))
|
||||
case errLog:
|
||||
assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out))
|
||||
}
|
||||
sdkCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectClientCmd(t *testing.T) {
|
||||
sdkMock := new(sdkmocks.SDK)
|
||||
cli.SetSDK(sdkMock)
|
||||
|
||||
@@ -37,17 +37,6 @@ const (
|
||||
unshrCmd = "unshare"
|
||||
)
|
||||
|
||||
// Groups and channels commands
|
||||
const (
|
||||
chansCmd = "channels"
|
||||
grpCmd = "groups"
|
||||
childCmd = "children"
|
||||
parentCmd = "parents"
|
||||
usrCmd = "users"
|
||||
assignCmd = "assign"
|
||||
unassignCmd = "unassign"
|
||||
)
|
||||
|
||||
// Certs commands
|
||||
const (
|
||||
revokeCmd = "revoke"
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ var cmdDomains = []cobra.Command{
|
||||
Status: Status,
|
||||
}
|
||||
|
||||
l, err := sdk.ListDomainUsers(args[0], pageMetadata, args[1])
|
||||
l, err := sdk.ListDomainMembers(args[0], pageMetadata, args[1])
|
||||
if err != nil {
|
||||
logErrorCmd(*cmd, err)
|
||||
return
|
||||
|
||||
@@ -197,91 +197,6 @@ func TestGetDomainsCmd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListDomainUsers(t *testing.T) {
|
||||
sdkMock := new(sdkmocks.SDK)
|
||||
cli.SetSDK(sdkMock)
|
||||
domainsCmd := cli.NewDomainsCmd()
|
||||
rootCmd := setFlags(domainsCmd)
|
||||
|
||||
page := smqsdk.UsersPage{}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
args []string
|
||||
logType outputLog
|
||||
errLogMessage string
|
||||
page smqsdk.UsersPage
|
||||
sdkErr errors.SDKError
|
||||
}{
|
||||
{
|
||||
desc: "list domain users successfully",
|
||||
args: []string{
|
||||
domain.ID,
|
||||
token,
|
||||
},
|
||||
page: smqsdk.UsersPage{
|
||||
PageRes: smqsdk.PageRes{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
},
|
||||
Users: []smqsdk.User{user},
|
||||
},
|
||||
logType: entityLog,
|
||||
},
|
||||
{
|
||||
desc: "list domain users with invalid args",
|
||||
args: []string{
|
||||
domain.ID,
|
||||
token,
|
||||
extraArg,
|
||||
},
|
||||
logType: usageLog,
|
||||
},
|
||||
{
|
||||
desc: "list domain users without domain token",
|
||||
args: []string{
|
||||
domain.ID,
|
||||
tokenWithoutDomain,
|
||||
},
|
||||
sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden),
|
||||
errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)),
|
||||
logType: errLog,
|
||||
},
|
||||
{
|
||||
desc: "list domain users with invalid id",
|
||||
args: []string{
|
||||
invalidID,
|
||||
token,
|
||||
},
|
||||
sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
|
||||
errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)),
|
||||
logType: errLog,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
sdkCall := sdkMock.On("ListDomainUsers", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr)
|
||||
out := executeCommand(t, rootCmd, append([]string{usrCmd}, tc.args...)...)
|
||||
|
||||
switch tc.logType {
|
||||
case entityLog:
|
||||
err := json.Unmarshal([]byte(out), &page)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unmarshal JSON: %v", err)
|
||||
}
|
||||
assert.Equal(t, tc.page, page, fmt.Sprintf("%v unexpected response, expected: %v, got: %v", tc.desc, tc.page, page))
|
||||
case usageLog:
|
||||
assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out))
|
||||
case errLog:
|
||||
assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out))
|
||||
}
|
||||
sdkCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateDomainCmd(t *testing.T) {
|
||||
sdkMock := new(sdkmocks.SDK)
|
||||
cli.SetSDK(sdkMock)
|
||||
|
||||
@@ -176,6 +176,34 @@ func (_m *Repository) DoesClientHaveConnections(ctx context.Context, id string)
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, entityID, pageQuery
|
||||
func (_m *Repository) ListEntityMembers(ctx context.Context, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, entityID, pageQuery)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, entityID, pageQuery)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveChannelConnections provides a mock function with given fields: ctx, channelID
|
||||
func (_m *Repository) RemoveChannelConnections(ctx context.Context, channelID string) error {
|
||||
ret := _m.Called(ctx, channelID)
|
||||
@@ -230,6 +258,24 @@ func (_m *Repository) RemoveConnections(ctx context.Context, conns []clients.Con
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, entityID, members
|
||||
func (_m *Repository) RemoveEntityMembers(ctx context.Context, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok {
|
||||
r0 = rf(ctx, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, memberID
|
||||
func (_m *Repository) RemoveMemberFromAllRoles(ctx context.Context, memberID string) error {
|
||||
ret := _m.Called(ctx, memberID)
|
||||
|
||||
@@ -226,6 +226,34 @@ func (_m *Service) ListClients(ctx context.Context, session authn.Session, pm cl
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, session, entityID, pq
|
||||
func (_m *Service) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pq roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, session, entityID, pq)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, session, entityID, pq)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListUserClients provides a mock function with given fields: ctx, session, userID, pm
|
||||
func (_m *Service) ListUserClients(ctx context.Context, session authn.Session, userID string, pm clients.Page) (clients.ClientsPage, error) {
|
||||
ret := _m.Called(ctx, session, userID, pm)
|
||||
@@ -254,6 +282,24 @@ func (_m *Service) ListUserClients(ctx context.Context, session authn.Session, u
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, session, entityID, members
|
||||
func (_m *Service) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, session, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, []string) error); ok {
|
||||
r0 = rf(ctx, session, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, session, memberID
|
||||
func (_m *Service) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) error {
|
||||
ret := _m.Called(ctx, session, memberID)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/connections"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
"github.com/jackc/pgtype"
|
||||
@@ -39,7 +40,7 @@ type clientRepo struct {
|
||||
// NewRepository instantiates a PostgreSQL
|
||||
// implementation of Clients repository.
|
||||
func NewRepository(db postgres.Database) clients.Repository {
|
||||
repo := rolesPostgres.NewRepository(db, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
repo := rolesPostgres.NewRepository(db, policies.ClientType, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
|
||||
return &clientRepo{
|
||||
DB: db,
|
||||
|
||||
@@ -13,8 +13,6 @@ import (
|
||||
var (
|
||||
_ supermq.Response = (*createDomainRes)(nil)
|
||||
_ supermq.Response = (*retrieveDomainRes)(nil)
|
||||
_ supermq.Response = (*assignUsersRes)(nil)
|
||||
_ supermq.Response = (*unassignUsersRes)(nil)
|
||||
_ supermq.Response = (*listDomainsRes)(nil)
|
||||
)
|
||||
|
||||
@@ -123,31 +121,3 @@ func (res freezeDomainRes) Headers() map[string]string {
|
||||
func (res freezeDomainRes) Empty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type assignUsersRes struct{}
|
||||
|
||||
func (res assignUsersRes) Code() int {
|
||||
return http.StatusCreated
|
||||
}
|
||||
|
||||
func (res assignUsersRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res assignUsersRes) Empty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type unassignUsersRes struct{}
|
||||
|
||||
func (res unassignUsersRes) Code() int {
|
||||
return http.StatusNoContent
|
||||
}
|
||||
|
||||
func (res unassignUsersRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res unassignUsersRes) Empty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -94,6 +94,52 @@ func (_m *Repository) ListDomains(ctx context.Context, pm domains.Page) (domains
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, entityID, pageQuery
|
||||
func (_m *Repository) ListEntityMembers(ctx context.Context, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, entityID, pageQuery)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, entityID, pageQuery)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, entityID, members
|
||||
func (_m *Repository) RemoveEntityMembers(ctx context.Context, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok {
|
||||
r0 = rf(ctx, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, memberID
|
||||
func (_m *Repository) RemoveMemberFromAllRoles(ctx context.Context, memberID string) error {
|
||||
ret := _m.Called(ctx, memberID)
|
||||
|
||||
@@ -228,6 +228,52 @@ func (_m *Service) ListDomains(ctx context.Context, sesssion authn.Session, page
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, session, entityID, pq
|
||||
func (_m *Service) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pq roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, session, entityID, pq)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, session, entityID, pq)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, session, entityID, members
|
||||
func (_m *Service) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, session, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, []string) error); ok {
|
||||
r0 = rf(ctx, session, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, session, memberID
|
||||
func (_m *Service) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) error {
|
||||
ret := _m.Called(ctx, session, memberID)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/absmach/supermq/domains"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
"github.com/jackc/pgtype"
|
||||
@@ -38,7 +39,7 @@ type domainRepo struct {
|
||||
// New instantiates a PostgreSQL
|
||||
// implementation of Domain repository.
|
||||
func New(db postgres.Database) domains.Repository {
|
||||
rmsvcRepo := rolesPostgres.NewRepository(db, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
rmsvcRepo := rolesPostgres.NewRepository(db, policies.DomainType, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
return &domainRepo{
|
||||
db: db,
|
||||
Repository: rmsvcRepo,
|
||||
|
||||
@@ -112,6 +112,52 @@ func (_m *Repository) Delete(ctx context.Context, groupID string) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, entityID, pageQuery
|
||||
func (_m *Repository) ListEntityMembers(ctx context.Context, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, entityID, pageQuery)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, entityID, pageQuery)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, entityID, members
|
||||
func (_m *Repository) RemoveEntityMembers(ctx context.Context, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok {
|
||||
r0 = rf(ctx, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, memberID
|
||||
func (_m *Repository) RemoveMemberFromAllRoles(ctx context.Context, memberID string) error {
|
||||
ret := _m.Called(ctx, memberID)
|
||||
|
||||
@@ -254,6 +254,34 @@ func (_m *Service) ListChildrenGroups(ctx context.Context, session authn.Session
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, session, entityID, pq
|
||||
func (_m *Service) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pq roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, session, entityID, pq)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, session, entityID, pq)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListGroups provides a mock function with given fields: ctx, session, pm
|
||||
func (_m *Service) ListGroups(ctx context.Context, session authn.Session, pm groups.PageMeta) (groups.Page, error) {
|
||||
ret := _m.Called(ctx, session, pm)
|
||||
@@ -346,6 +374,24 @@ func (_m *Service) RemoveChildrenGroups(ctx context.Context, session authn.Sessi
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, session, entityID, members
|
||||
func (_m *Service) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, session, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, []string) error); ok {
|
||||
r0 = rf(ctx, session, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, session, memberID
|
||||
func (_m *Service) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) error {
|
||||
ret := _m.Called(ctx, session, memberID)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
groups "github.com/absmach/supermq/groups"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
"github.com/jmoiron/sqlx"
|
||||
@@ -42,7 +43,7 @@ type groupRepository struct {
|
||||
// New instantiates a PostgreSQL implementation of group
|
||||
// repository.
|
||||
func New(db postgres.Database) groups.Repository {
|
||||
roleRepo := rolesPostgres.NewRepository(db, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
roleRepo := rolesPostgres.NewRepository(db, policies.GroupType, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
|
||||
return &groupRepository{
|
||||
db: db,
|
||||
|
||||
@@ -19,23 +19,13 @@ import (
|
||||
const (
|
||||
stream = "events.supermq.domains"
|
||||
|
||||
create = "domain.create"
|
||||
update = "domain.update"
|
||||
enable = "domain.enable"
|
||||
disable = "domain.disable"
|
||||
freeze = "domain.freeze"
|
||||
delete = "domain.delete"
|
||||
userDelete = "domain.user_delete"
|
||||
addRole = "domain.role.add"
|
||||
removeRole = "domain.role.remove"
|
||||
updateRole = "domain.role.update"
|
||||
addRoleActions = "domain.role.actions.add"
|
||||
removeRoleActions = "domain.role.actions.remove"
|
||||
removeAllRoleActions = "domain.role.actions.remove_all"
|
||||
addRoleMembers = "domain.role.members.add"
|
||||
removeRoleMembers = "domain.role.members.remove"
|
||||
removeRoleAllMembers = "domain.role.members.remove_all"
|
||||
removeMemberFromAllRoles = "domain.role.members.remove_from_all_roles"
|
||||
create = "domain.create"
|
||||
update = "domain.update"
|
||||
enable = "domain.enable"
|
||||
disable = "domain.disable"
|
||||
freeze = "domain.freeze"
|
||||
delete = "domain.delete"
|
||||
userDelete = "domain.user_delete"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -105,28 +95,9 @@ func (es *eventHandler) Handle(ctx context.Context, event events.Event) error {
|
||||
return es.userDeleteDomainHandler(ctx, msg)
|
||||
case delete:
|
||||
return es.deleteDomainHandler(ctx, msg)
|
||||
case addRole:
|
||||
return es.rolesEventHandler.AddEntityRoleHandler(ctx, msg)
|
||||
case updateRole:
|
||||
return es.rolesEventHandler.UpdateEntityRoleHandler(ctx, msg)
|
||||
case removeRole:
|
||||
return es.rolesEventHandler.RemoveEntityRoleHandler(ctx, msg)
|
||||
case addRoleActions:
|
||||
return es.rolesEventHandler.AddEntityRoleActionsHandler(ctx, msg)
|
||||
case removeRoleActions:
|
||||
return es.rolesEventHandler.RemoveEntityRoleActionsHandler(ctx, msg)
|
||||
case removeAllRoleActions:
|
||||
return es.rolesEventHandler.RemoveAllEntityRoleActionsHandler(ctx, msg)
|
||||
case addRoleMembers:
|
||||
return es.rolesEventHandler.AddEntityRoleMembersHandler(ctx, msg)
|
||||
case removeRoleMembers:
|
||||
return es.rolesEventHandler.RemoveEntityRoleMembersHandler(ctx, msg)
|
||||
case removeRoleAllMembers:
|
||||
return es.rolesEventHandler.RemoveAllEntityRoleMembersHandler(ctx, msg)
|
||||
case removeMemberFromAllRoles:
|
||||
return es.rolesEventHandler.RemoveMemberFromAllEntityHandler(ctx, msg)
|
||||
}
|
||||
return nil
|
||||
|
||||
return es.rolesEventHandler.Handle(ctx, op, msg)
|
||||
}
|
||||
|
||||
func (es *eventHandler) createDomainHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
|
||||
@@ -18,25 +18,15 @@ import (
|
||||
const (
|
||||
stream = "events.supermq.groups"
|
||||
|
||||
create = "group.create"
|
||||
update = "group.update"
|
||||
changeStatus = "group.change_status"
|
||||
remove = "group.remove"
|
||||
addParentGroup = "group.add_parent_group"
|
||||
removeParentGroup = "group.remove_parent_group"
|
||||
addChildrenGroups = "group.add_children_groups"
|
||||
removeChildrenGroups = "group.remove_children_groups"
|
||||
removeAllChildrenGroups = "group.remove_all_children_groups"
|
||||
addRole = "group.role.add"
|
||||
removeRole = "group.role.remove"
|
||||
updateRole = "group.role.update"
|
||||
addRoleActions = "group.role.actions.add"
|
||||
removeRoleActions = "group.role.actions.remove"
|
||||
removeAllRoleActions = "group.role.actions.remove_all"
|
||||
addRoleMembers = "group.role.members.add"
|
||||
removeRoleMembers = "group.role.members.remove"
|
||||
removeRoleAllMembers = "group.role.members.remove_all"
|
||||
removeMemberFromAllRoles = "group.role.members.remove_from_all_roles"
|
||||
create = "group.create"
|
||||
update = "group.update"
|
||||
changeStatus = "group.change_status"
|
||||
remove = "group.remove"
|
||||
addParentGroup = "group.add_parent_group"
|
||||
removeParentGroup = "group.remove_parent_group"
|
||||
addChildrenGroups = "group.add_children_groups"
|
||||
removeChildrenGroups = "group.remove_children_groups"
|
||||
removeAllChildrenGroups = "group.remove_all_children_groups"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -111,28 +101,9 @@ func (es *eventHandler) Handle(ctx context.Context, event events.Event) error {
|
||||
return es.removeChildrenGroupsHandler(ctx, msg)
|
||||
case removeAllChildrenGroups:
|
||||
return es.removeAllChildrenGroupsHandler(ctx, msg)
|
||||
case addRole:
|
||||
return es.rolesEventHandler.AddEntityRoleHandler(ctx, msg)
|
||||
case updateRole:
|
||||
return es.rolesEventHandler.UpdateEntityRoleHandler(ctx, msg)
|
||||
case removeRole:
|
||||
return es.rolesEventHandler.RemoveEntityRoleHandler(ctx, msg)
|
||||
case addRoleActions:
|
||||
return es.rolesEventHandler.AddEntityRoleActionsHandler(ctx, msg)
|
||||
case removeRoleActions:
|
||||
return es.rolesEventHandler.RemoveEntityRoleActionsHandler(ctx, msg)
|
||||
case removeAllRoleActions:
|
||||
return es.rolesEventHandler.RemoveAllEntityRoleActionsHandler(ctx, msg)
|
||||
case addRoleMembers:
|
||||
return es.rolesEventHandler.AddEntityRoleMembersHandler(ctx, msg)
|
||||
case removeRoleMembers:
|
||||
return es.rolesEventHandler.RemoveEntityRoleMembersHandler(ctx, msg)
|
||||
case removeRoleAllMembers:
|
||||
return es.rolesEventHandler.RemoveAllEntityRoleMembersHandler(ctx, msg)
|
||||
case removeMemberFromAllRoles:
|
||||
return es.rolesEventHandler.RemoveMemberFromAllEntityHandler(ctx, msg)
|
||||
}
|
||||
return nil
|
||||
|
||||
return es.rolesEventHandler.Handle(ctx, op, msg)
|
||||
}
|
||||
|
||||
func (es *eventHandler) createGroupHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
|
||||
@@ -77,6 +77,52 @@ func (_m *RoleManager) ListAvailableActions(ctx context.Context, session authn.S
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, session, entityID, pq
|
||||
func (_m *RoleManager) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pq roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, session, entityID, pq)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, session, entityID, pq)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, session, entityID, pq)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, session, entityID, members
|
||||
func (_m *RoleManager) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, session, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, []string) error); ok {
|
||||
r0 = rf(ctx, session, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, session, memberID
|
||||
func (_m *RoleManager) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) error {
|
||||
ret := _m.Called(ctx, session, memberID)
|
||||
|
||||
@@ -46,6 +46,52 @@ func (_m *Repository) AddRoles(ctx context.Context, rps []roles.RoleProvision) (
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityMembers provides a mock function with given fields: ctx, entityID, pageQuery
|
||||
func (_m *Repository) ListEntityMembers(ctx context.Context, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
ret := _m.Called(ctx, entityID, pageQuery)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityMembers")
|
||||
}
|
||||
|
||||
var r0 roles.MembersRolePage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) (roles.MembersRolePage, error)); ok {
|
||||
return rf(ctx, entityID, pageQuery)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, roles.MembersRolePageQuery) roles.MembersRolePage); ok {
|
||||
r0 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r0 = ret.Get(0).(roles.MembersRolePage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, roles.MembersRolePageQuery) error); ok {
|
||||
r1 = rf(ctx, entityID, pageQuery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveEntityMembers provides a mock function with given fields: ctx, entityID, members
|
||||
func (_m *Repository) RemoveEntityMembers(ctx context.Context, entityID string, members []string) error {
|
||||
ret := _m.Called(ctx, entityID, members)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityMembers")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok {
|
||||
r0 = rf(ctx, entityID, members)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveMemberFromAllRoles provides a mock function with given fields: ctx, memberID
|
||||
func (_m *Repository) RemoveMemberFromAllRoles(ctx context.Context, memberID string) error {
|
||||
ret := _m.Called(ctx, memberID)
|
||||
|
||||
@@ -579,7 +579,7 @@ func (r ProvisionManageService) RoleRemoveMembers(ctx context.Context, session a
|
||||
}
|
||||
|
||||
ro.UpdatedAt = time.Now()
|
||||
// ro.UpdatedBy = userID
|
||||
ro.UpdatedBy = session.UserID
|
||||
if err := r.repo.RoleRemoveMembers(ctx, ro, members); err != nil {
|
||||
return errors.Wrap(svcerr.ErrRemoveEntity, err)
|
||||
}
|
||||
@@ -611,6 +611,21 @@ func (r ProvisionManageService) RoleRemoveAllMembers(ctx context.Context, sessio
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r ProvisionManageService) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pageQuery MembersRolePageQuery) (MembersRolePage, error) {
|
||||
mp, err := r.repo.ListEntityMembers(ctx, entityID, pageQuery)
|
||||
if err != nil {
|
||||
return MembersRolePage{}, err
|
||||
}
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
func (r ProvisionManageService) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
if err := r.repo.RemoveEntityMembers(ctx, entityID, members); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r ProvisionManageService) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, member string) (err error) {
|
||||
if err := r.repo.RemoveMemberFromAllRoles(ctx, member); err != nil {
|
||||
return errors.Wrap(svcerr.ErrRemoveEntity, err)
|
||||
|
||||
@@ -29,29 +29,30 @@ func Migration(rolesTableNamePrefix, entityTableName, entityIDColumnName string)
|
||||
updated_at TIMESTAMP,
|
||||
updated_by VARCHAR(254),
|
||||
created_by VARCHAR(254),
|
||||
CONSTRAINT %s_roles_unique_role_name_entity_id_constraint UNIQUE ( name, entity_id),
|
||||
CONSTRAINT %s_roles_unique_role_name_entity_id_constraint UNIQUE (name, entity_id),
|
||||
CONSTRAINT %s_roles_fk_entity_id FOREIGN KEY(entity_id) REFERENCES %s(%s) ON DELETE CASCADE
|
||||
);`, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix, entityTableName, entityIDColumnName),
|
||||
|
||||
fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s_role_actions (
|
||||
role_id VARCHAR(254) NOT NULL,
|
||||
action VARCHAR(254) NOT NULL,
|
||||
CONSTRAINT %s_role_actions_unique_role_action_constraint UNIQUE ( role_id, action),
|
||||
action VARCHAR(254) NOT NULL,
|
||||
CONSTRAINT %s_role_actions_unique_role_action_constraint UNIQUE (role_id, action),
|
||||
CONSTRAINT %s_role_actions_fk_roles_id FOREIGN KEY(role_id) REFERENCES %s_roles(id) ON DELETE CASCADE
|
||||
|
||||
);`, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix),
|
||||
|
||||
fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s_role_members (
|
||||
role_id VARCHAR(254) NOT NULL,
|
||||
member_id VARCHAR(254) NOT NULL,
|
||||
entity_id VARCHAR(36) NOT NULL,
|
||||
CONSTRAINT %s_role_members_unique_role_member_constraint UNIQUE (role_id, member_id),
|
||||
CONSTRAINT %s_role_members_unique_entity_member_constraint UNIQUE (member_id, entity_id),
|
||||
CONSTRAINT %s_role_members_fk_roles_id FOREIGN KEY(role_id) REFERENCES %s_roles(id) ON DELETE CASCADE
|
||||
);`, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix),
|
||||
);`, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix, rolesTableNamePrefix),
|
||||
},
|
||||
Down: []string{
|
||||
fmt.Sprintf(`DROP TABLE IF EXISTS %s_roles`, rolesTableNamePrefix),
|
||||
fmt.Sprintf(`DROP TABLE IF EXISTS %s_roles_actions`, rolesTableNamePrefix),
|
||||
fmt.Sprintf(`DROP TABLE IF EXISTS %s_roles_members`, rolesTableNamePrefix),
|
||||
fmt.Sprintf(`DROP TABLE IF EXISTS %s_role_actions`, rolesTableNamePrefix),
|
||||
fmt.Sprintf(`DROP TABLE IF EXISTS %s_role_members`, rolesTableNamePrefix),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,13 +6,16 @@ package postgres
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
api "github.com/absmach/supermq/api/http"
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
)
|
||||
@@ -20,20 +23,35 @@ import (
|
||||
var _ roles.Repository = (*Repository)(nil)
|
||||
|
||||
type Repository struct {
|
||||
db postgres.Database
|
||||
tableNamePrefix string
|
||||
entityTableName string
|
||||
entityIDColumnName string
|
||||
db postgres.Database
|
||||
tableNamePrefix string
|
||||
entityTableName string
|
||||
entityIDColumnName string
|
||||
membersListBaseQuery string
|
||||
}
|
||||
|
||||
// NewRepository instantiates a PostgreSQL
|
||||
// implementation of Roles repository.
|
||||
func NewRepository(db postgres.Database, tableNamePrefix, entityTableName, entityIDColumnName string) Repository {
|
||||
func NewRepository(db postgres.Database, entityType, tableNamePrefix, entityTableName, entityIDColumnName string) Repository {
|
||||
var membersListBaseQuery string
|
||||
|
||||
switch entityType {
|
||||
case policies.ChannelType:
|
||||
membersListBaseQuery = channelMembersListBaseQuery()
|
||||
case policies.ClientType:
|
||||
membersListBaseQuery = clientMembersListBaseQuery()
|
||||
case policies.GroupType:
|
||||
membersListBaseQuery = groupMembersListBaseQuery()
|
||||
case policies.DomainType:
|
||||
membersListBaseQuery = domainMembersListBaseQuery()
|
||||
}
|
||||
|
||||
return Repository{
|
||||
db: db,
|
||||
tableNamePrefix: tableNamePrefix,
|
||||
entityTableName: entityTableName,
|
||||
entityIDColumnName: entityIDColumnName,
|
||||
db: db,
|
||||
tableNamePrefix: tableNamePrefix,
|
||||
entityTableName: entityTableName,
|
||||
entityIDColumnName: entityIDColumnName,
|
||||
membersListBaseQuery: membersListBaseQuery,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +73,11 @@ type dbRole struct {
|
||||
UpdatedAt sql.NullTime `db:"updated_at"`
|
||||
}
|
||||
|
||||
type dbMemberRoles struct {
|
||||
MemberID string `db:"member_id,omitempty"`
|
||||
Roles json.RawMessage `db:"roles,omitempty"`
|
||||
}
|
||||
|
||||
type dbEntityActionRole struct {
|
||||
EntityID string `db:"entity_id"`
|
||||
Action string `db:"action"`
|
||||
@@ -97,6 +120,7 @@ type dbRoleAction struct {
|
||||
|
||||
type dbRoleMember struct {
|
||||
RoleID string `db:"role_id"`
|
||||
EntityID string `db:"entity_id"`
|
||||
MemberID string `db:"member_id"`
|
||||
}
|
||||
|
||||
@@ -199,15 +223,16 @@ func (repo *Repository) AddRoles(ctx context.Context, rps []roles.RoleProvision)
|
||||
}
|
||||
|
||||
if len(rp.OptionalMembers) > 0 {
|
||||
mq := fmt.Sprintf(`INSERT INTO %s_role_members (role_id, member_id)
|
||||
VALUES (:role_id, :member_id)
|
||||
RETURNING role_id, member_id`, repo.tableNamePrefix)
|
||||
mq := fmt.Sprintf(`INSERT INTO %s_role_members (role_id, entity_id, member_id)
|
||||
VALUES (:role_id, :entity_id, :member_id)
|
||||
RETURNING role_id, entity_id, member_id`, repo.tableNamePrefix)
|
||||
|
||||
rMems := []dbRoleMember{}
|
||||
for _, m := range rp.OptionalMembers {
|
||||
rMems = append(rMems, dbRoleMember{
|
||||
RoleID: rp.ID,
|
||||
MemberID: m,
|
||||
EntityID: rp.EntityID,
|
||||
})
|
||||
}
|
||||
if _, err := tx.NamedExec(mq, rMems); err != nil {
|
||||
@@ -533,9 +558,9 @@ func (repo *Repository) RoleRemoveAllActions(ctx context.Context, role roles.Rol
|
||||
}
|
||||
|
||||
func (repo *Repository) RoleAddMembers(ctx context.Context, role roles.Role, members []string) ([]string, error) {
|
||||
mq := fmt.Sprintf(`INSERT INTO %s_role_members (role_id, member_id)
|
||||
VALUES (:role_id, :member_id)
|
||||
RETURNING role_id, member_id`, repo.tableNamePrefix)
|
||||
mq := fmt.Sprintf(`INSERT INTO %s_role_members (role_id, entity_id, member_id)
|
||||
VALUES (:role_id, :entity_id, :member_id)
|
||||
RETURNING role_id, :entity_id, member_id`, repo.tableNamePrefix)
|
||||
|
||||
tx, err := repo.db.BeginTxx(ctx, nil)
|
||||
if err != nil {
|
||||
@@ -553,6 +578,7 @@ func (repo *Repository) RoleAddMembers(ctx context.Context, role roles.Role, mem
|
||||
for _, m := range members {
|
||||
rMems = append(rMems, dbRoleMember{
|
||||
RoleID: role.ID,
|
||||
EntityID: role.EntityID,
|
||||
MemberID: m,
|
||||
})
|
||||
}
|
||||
@@ -757,6 +783,602 @@ func (repo *Repository) RetrieveEntitiesRolesActionsMembers(ctx context.Context,
|
||||
return dbToEntityActionRole(dbears), dbToEntityMemberRole(dbemrs), nil
|
||||
}
|
||||
|
||||
func (repo *Repository) ListEntityMembers(ctx context.Context, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
dbPageQuery, err := toDBMembersRolePageQuery(pageQuery)
|
||||
if err != nil {
|
||||
return roles.MembersRolePage{}, err
|
||||
}
|
||||
dbPageQuery.EntityID = entityID
|
||||
|
||||
entityMembersQuery := fmt.Sprintf(`
|
||||
%s
|
||||
SELECT
|
||||
member_id,
|
||||
roles
|
||||
FROM
|
||||
members
|
||||
`, repo.membersListBaseQuery)
|
||||
|
||||
entityMembersQuery = applyConditions(entityMembersQuery, pageQuery)
|
||||
entityMembersQuery = applyOrdering(entityMembersQuery, pageQuery)
|
||||
entityMembersQuery = applyLimitOffset(entityMembersQuery)
|
||||
|
||||
rows, err := repo.db.NamedQueryContext(ctx, entityMembersQuery, dbPageQuery)
|
||||
if err != nil {
|
||||
return roles.MembersRolePage{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
mems := []roles.MemberRoles{}
|
||||
for rows.Next() {
|
||||
var dbmr dbMemberRoles
|
||||
if err = rows.StructScan(&dbmr); err != nil {
|
||||
return roles.MembersRolePage{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
var roleActions []roles.MemberRoleActions
|
||||
if err := json.Unmarshal(dbmr.Roles, &roleActions); err != nil {
|
||||
return roles.MembersRolePage{}, fmt.Errorf("failed to unmarshal roles JSON: %w", err)
|
||||
}
|
||||
mems = append(mems, roles.MemberRoles{MemberID: dbmr.MemberID, Roles: roleActions})
|
||||
}
|
||||
|
||||
entityMembersCountQuery := fmt.Sprintf(`
|
||||
%s
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
members
|
||||
`, repo.membersListBaseQuery)
|
||||
|
||||
entityMembersCountQuery = applyConditions(entityMembersCountQuery, pageQuery)
|
||||
|
||||
total, err := postgres.Total(ctx, repo.db, entityMembersCountQuery, dbPageQuery)
|
||||
if err != nil {
|
||||
return roles.MembersRolePage{}, err
|
||||
}
|
||||
|
||||
return roles.MembersRolePage{
|
||||
Total: total,
|
||||
Limit: pageQuery.Limit,
|
||||
Offset: pageQuery.Offset,
|
||||
Members: mems,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) RemoveEntityMembers(ctx context.Context, entityID string, memberIDs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repo *Repository) RemoveMemberFromAllRoles(ctx context.Context, memberID string) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyConditions(query string, pageQuery roles.MembersRolePageQuery) string {
|
||||
var whereClause []string
|
||||
|
||||
if pageQuery.RoleID != "" {
|
||||
whereClause = append(whereClause, " roles @> :role_id ")
|
||||
}
|
||||
if pageQuery.RoleName != "" {
|
||||
whereClause = append(whereClause, " roles @> :role_name ")
|
||||
}
|
||||
if len(pageQuery.Actions) != 0 {
|
||||
whereClause = append(whereClause, " roles @> :actions ")
|
||||
}
|
||||
if pageQuery.AccessType != "" {
|
||||
whereClause = append(whereClause, " roles @> :access_type ")
|
||||
}
|
||||
if pageQuery.AccessProviderID != "" {
|
||||
whereClause = append(whereClause, " roles @> :access_provider_id ")
|
||||
}
|
||||
|
||||
var whereCondition string
|
||||
if len(whereClause) != 0 {
|
||||
whereCondition = "WHERE " + strings.Join(whereClause, " AND ")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`%s
|
||||
%s`, query, whereCondition)
|
||||
}
|
||||
|
||||
func applyOrdering(query string, pageQuery roles.MembersRolePageQuery) string {
|
||||
switch pageQuery.Order {
|
||||
case "access_provider_id", "role_name", "role_id", "access_type":
|
||||
query = fmt.Sprintf("%s ORDER BY %s", query, pageQuery.Order)
|
||||
if pageQuery.Dir == api.AscDir || pageQuery.Dir == api.DescDir {
|
||||
query = fmt.Sprintf("%s %s", query, pageQuery.Dir)
|
||||
}
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func applyLimitOffset(query string) string {
|
||||
return fmt.Sprintf(`%s
|
||||
LIMIT :limit OFFSET :offset`, query)
|
||||
}
|
||||
|
||||
type dbMembersRolePageQuery struct {
|
||||
Offset uint64 `db:"offset"`
|
||||
Limit uint64 `db:"limit"`
|
||||
OrderBy string `db:"order_by"`
|
||||
Direction string `db:"dir"`
|
||||
AccessProviderID json.RawMessage `db:"access_provider_id"`
|
||||
RoleId json.RawMessage `db:"role_id"`
|
||||
RoleName json.RawMessage `db:"role_name"`
|
||||
Actions json.RawMessage `db:"actions"`
|
||||
AccessType json.RawMessage `db:"access_type"`
|
||||
EntityID string `db:"entity_id"`
|
||||
}
|
||||
|
||||
func toDBMembersRolePageQuery(pageQuery roles.MembersRolePageQuery) (dbMembersRolePageQuery, error) {
|
||||
actions := []byte("{}")
|
||||
if len(pageQuery.Actions) != 0 {
|
||||
var err error
|
||||
jactions := []struct {
|
||||
Actions []string `json:"actions"`
|
||||
}{
|
||||
{
|
||||
Actions: pageQuery.Actions,
|
||||
},
|
||||
}
|
||||
actions, err = json.Marshal(jactions)
|
||||
if err != nil {
|
||||
return dbMembersRolePageQuery{}, err
|
||||
}
|
||||
}
|
||||
|
||||
accessProviderID := []byte("{}")
|
||||
if pageQuery.AccessProviderID != "" {
|
||||
accessProviderID = []byte(fmt.Sprintf("[{\"access_provider_id\" : \"%s\"}]", pageQuery.AccessProviderID))
|
||||
}
|
||||
|
||||
roleID := []byte("{}")
|
||||
if pageQuery.RoleID != "" {
|
||||
roleID = []byte(fmt.Sprintf("[{\"role_id\" : \"%s\"}]", pageQuery.RoleID))
|
||||
}
|
||||
|
||||
roleName := []byte("{}")
|
||||
if pageQuery.RoleName != "" {
|
||||
roleName = []byte(fmt.Sprintf("[{\"role_name\" : \"%s\"}]", pageQuery.RoleName))
|
||||
}
|
||||
|
||||
accessType := []byte("{}")
|
||||
if pageQuery.AccessType != "" {
|
||||
accessType = []byte(fmt.Sprintf("[{\"access_type\" : \"%s\"}]", pageQuery.AccessType))
|
||||
}
|
||||
|
||||
return dbMembersRolePageQuery{
|
||||
Offset: pageQuery.Offset,
|
||||
Limit: pageQuery.Limit,
|
||||
OrderBy: pageQuery.Order,
|
||||
Direction: pageQuery.Dir,
|
||||
AccessProviderID: accessProviderID,
|
||||
RoleId: roleID,
|
||||
RoleName: roleName,
|
||||
Actions: actions,
|
||||
AccessType: accessType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func domainMembersListBaseQuery() string {
|
||||
return `
|
||||
WITH ungrouped_members AS (
|
||||
SELECT
|
||||
dr.id,
|
||||
dr.name,
|
||||
drm.member_id,
|
||||
ARRAY_AGG(DISTINCT all_actions.action) AS actions,
|
||||
'direct' AS access_type,
|
||||
'' AS access_provider_id
|
||||
FROM
|
||||
domains_role_members drm
|
||||
JOIN domains_roles dr ON
|
||||
dr.id = drm.role_id
|
||||
JOIN domains_role_actions dra ON
|
||||
dra.role_id = dr.id
|
||||
JOIN domains_role_actions all_actions ON
|
||||
all_actions.role_id = drm.role_id
|
||||
WHERE
|
||||
dr.entity_id = :entity_id
|
||||
GROUP BY
|
||||
dr.id,
|
||||
drm.member_id
|
||||
),
|
||||
members AS (
|
||||
SELECT
|
||||
um.member_id,
|
||||
JSONB_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'role_id', um.id,
|
||||
'role_name', um.name,
|
||||
'actions', um.actions,
|
||||
'access_type', um.access_type,
|
||||
'access_provider_id', um.access_provider_id
|
||||
)
|
||||
) AS roles
|
||||
FROM
|
||||
ungrouped_members um
|
||||
GROUP BY
|
||||
um.member_id
|
||||
)
|
||||
`
|
||||
}
|
||||
|
||||
func groupMembersListBaseQuery() string {
|
||||
return `
|
||||
WITH ungrouped_members AS (
|
||||
SELECT
|
||||
gr."name",
|
||||
gr.id,
|
||||
grm.member_id,
|
||||
ARRAY_AGG(DISTINCT agg_gra."action") AS actions,
|
||||
CASE
|
||||
WHEN g.id = :entity_id THEN 'direct'
|
||||
ELSE 'indirect_group'
|
||||
END AS access_type,
|
||||
CASE
|
||||
WHEN g.id = :entity_id THEN ''
|
||||
ELSE g.id
|
||||
END AS access_provider_id
|
||||
FROM
|
||||
"groups" g
|
||||
JOIN
|
||||
groups_roles gr ON
|
||||
gr.entity_id = g.id
|
||||
JOIN
|
||||
groups_role_members grm ON
|
||||
grm.role_id = gr.id
|
||||
JOIN
|
||||
groups_role_actions gra ON
|
||||
gra.role_id = gr.id
|
||||
JOIN
|
||||
groups_role_actions agg_gra ON
|
||||
agg_gra.role_id = gr.id
|
||||
WHERE
|
||||
g.path @> (
|
||||
SELECT
|
||||
"path"
|
||||
FROM
|
||||
"groups"
|
||||
WHERE
|
||||
id = :entity_id
|
||||
LIMIT 1
|
||||
)
|
||||
AND (
|
||||
g.id = :entity_id
|
||||
OR gra."action" LIKE 'subgroup%'
|
||||
) -- -- If g.id = <entity_id>, it allows all actions. If g.id <> <entity_id>, it only allows actions matching 'subgroup%'.
|
||||
GROUP BY
|
||||
gr.id,
|
||||
grm.member_id,
|
||||
g.id
|
||||
UNION
|
||||
SELECT
|
||||
dr."name",
|
||||
dr.id,
|
||||
drm.member_id,
|
||||
ARRAY_AGG(DISTINCT agg_dra."action") AS actions,
|
||||
'domain' AS access_type,
|
||||
d.id AS access_provider_id
|
||||
FROM
|
||||
"groups" g
|
||||
JOIN
|
||||
domains d ON
|
||||
d.id = g.domain_id
|
||||
JOIN
|
||||
domains_roles dr ON
|
||||
dr.entity_id = d.id
|
||||
JOIN
|
||||
domains_role_members drm ON
|
||||
dr.id = drm.role_id
|
||||
JOIN
|
||||
domains_role_actions dra ON
|
||||
dr.id = dra.role_id
|
||||
JOIN
|
||||
domains_role_actions agg_dra ON
|
||||
agg_dra.role_id = dr.id
|
||||
WHERE
|
||||
g.id = :entity_id
|
||||
AND
|
||||
dra."action" LIKE 'group%'
|
||||
GROUP BY
|
||||
dr.id,
|
||||
drm.member_id,
|
||||
d.id
|
||||
),
|
||||
members AS (
|
||||
SELECT
|
||||
um.member_id,
|
||||
JSONB_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'role_id', um.id,
|
||||
'role_name', um.name,
|
||||
'actions', um.actions,
|
||||
'access_type', um.access_type,
|
||||
'access_provider_id', um.access_provider_id
|
||||
)
|
||||
) AS roles
|
||||
FROM
|
||||
ungrouped_members um
|
||||
GROUP BY
|
||||
um.member_id
|
||||
)
|
||||
`
|
||||
}
|
||||
|
||||
func clientMembersListBaseQuery() string {
|
||||
return `
|
||||
WITH client_group AS (
|
||||
SELECT
|
||||
c.id,
|
||||
c.parent_group_id,
|
||||
c.domain_id,
|
||||
g."path" AS parent_group_path
|
||||
FROM
|
||||
clients c
|
||||
LEFT JOIN
|
||||
"groups" g ON
|
||||
g.id = c.parent_group_id
|
||||
WHERE
|
||||
c.id = :entity_id
|
||||
LIMIT 1
|
||||
),
|
||||
ungrouped_members AS (
|
||||
SELECT
|
||||
cr."name",
|
||||
cr.id,
|
||||
crm.member_id,
|
||||
ARRAY_AGG(DISTINCT cra."action") AS actions,
|
||||
'direct' AS access_type,
|
||||
'' AS access_provider_id,
|
||||
''::::LTREE AS access_provider_path
|
||||
FROM
|
||||
client_group cg
|
||||
JOIN
|
||||
clients_roles cr ON
|
||||
cr.entity_id = cg.id
|
||||
JOIN
|
||||
clients_role_members crm ON
|
||||
crm.role_id = cr.id
|
||||
JOIN
|
||||
clients_role_actions cra ON
|
||||
cra.role_id = cr.id
|
||||
GROUP BY
|
||||
cr.id,
|
||||
crm.member_id
|
||||
UNION
|
||||
SELECT
|
||||
gr."name",
|
||||
gr.id,
|
||||
grm.member_id,
|
||||
ARRAY_AGG(DISTINCT agg_gra."action") AS actions,
|
||||
CASE
|
||||
WHEN g.id = cg.parent_group_id THEN 'direct_group'
|
||||
ELSE 'indirect_group'
|
||||
END AS access_type,
|
||||
g.id AS access_provider_id,
|
||||
g.path AS access_provider_path
|
||||
FROM
|
||||
client_group cg
|
||||
JOIN
|
||||
"groups" g ON
|
||||
g.PATH @> cg.parent_group_path
|
||||
JOIN
|
||||
groups_roles gr ON
|
||||
g.id = gr.entity_id
|
||||
JOIN
|
||||
groups_role_members grm ON
|
||||
grm.role_id = gr.id
|
||||
JOIN
|
||||
groups_role_actions gra ON
|
||||
gra.role_id = gr.id
|
||||
JOIN
|
||||
groups_role_actions agg_gra ON
|
||||
agg_gra.role_id = gr.id
|
||||
WHERE
|
||||
(
|
||||
gra."action" LIKE 'client%%'
|
||||
AND g.id = cg.parent_group_id
|
||||
)
|
||||
OR
|
||||
(
|
||||
gra."action" LIKE 'subgroup_client%%'
|
||||
AND g.id <> cg.parent_group_id
|
||||
)
|
||||
GROUP BY
|
||||
gr.id,
|
||||
grm.member_id,
|
||||
g.id,
|
||||
cg.parent_group_id
|
||||
UNION
|
||||
SELECT
|
||||
dr."name",
|
||||
dr.id,
|
||||
drm.member_id,
|
||||
ARRAY_AGG(DISTINCT agg_dra."action") AS actions,
|
||||
'domain' AS access_type,
|
||||
d.id AS access_provider_id,
|
||||
''::::LTREE AS access_provider_path
|
||||
FROM
|
||||
client_group cg
|
||||
JOIN
|
||||
domains d ON
|
||||
d.id = cg.domain_id
|
||||
JOIN
|
||||
domains_roles dr ON
|
||||
dr.entity_id = d.id
|
||||
JOIN
|
||||
domains_role_members drm ON
|
||||
dr.id = drm.role_id
|
||||
JOIN
|
||||
domains_role_actions dra ON
|
||||
dr.id = dra.role_id
|
||||
JOIN
|
||||
domains_role_actions agg_dra ON
|
||||
agg_dra.role_id = dr.id
|
||||
WHERE
|
||||
dra."action" LIKE 'client%'
|
||||
GROUP BY
|
||||
dr.id,
|
||||
drm.member_id,
|
||||
d.id
|
||||
),
|
||||
members AS (
|
||||
SELECT
|
||||
um.member_id,
|
||||
JSONB_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'role_id', um.id,
|
||||
'role_name', um.name,
|
||||
'actions', um.actions,
|
||||
'access_type', um.access_type,
|
||||
'access_provider_id', um.access_provider_id,
|
||||
'access_provider_path', um.access_provider_path
|
||||
)
|
||||
) AS roles
|
||||
FROM
|
||||
ungrouped_members um
|
||||
GROUP BY
|
||||
um.member_id
|
||||
)
|
||||
`
|
||||
}
|
||||
|
||||
func channelMembersListBaseQuery() string {
|
||||
return `
|
||||
WITH channel_group AS (
|
||||
SELECT
|
||||
c.id,
|
||||
c.parent_group_id,
|
||||
c.domain_id,
|
||||
g."path" AS parent_group_path
|
||||
FROM
|
||||
channels c
|
||||
LEFT JOIN
|
||||
"groups" g ON
|
||||
g.id = c.parent_group_id
|
||||
WHERE
|
||||
c.id = :entity_id
|
||||
LIMIT 1
|
||||
),
|
||||
ungrouped_members AS (
|
||||
SELECT
|
||||
cr."name",
|
||||
cr.id,
|
||||
crm.member_id,
|
||||
ARRAY_AGG(DISTINCT cra."action") AS actions,
|
||||
'direct' AS access_type,
|
||||
'' AS access_provider_id,
|
||||
''::::LTREE AS access_provider_path
|
||||
FROM
|
||||
channel_group cg
|
||||
JOIN
|
||||
channels_roles cr ON
|
||||
cr.entity_id = cg.id
|
||||
JOIN
|
||||
channels_role_members crm ON
|
||||
crm.role_id = cr.id
|
||||
JOIN
|
||||
channels_role_actions cra ON
|
||||
cra.role_id = cr.id
|
||||
GROUP BY
|
||||
cr.id,
|
||||
crm.member_id
|
||||
UNION
|
||||
SELECT
|
||||
gr."name",
|
||||
gr.id,
|
||||
grm.member_id,
|
||||
ARRAY_AGG(DISTINCT agg_gra."action") AS actions,
|
||||
CASE
|
||||
WHEN g.id = cg.parent_group_id THEN 'direct_group'
|
||||
ELSE 'indirect_group'
|
||||
END AS access_type,
|
||||
g.id AS access_provider_id,
|
||||
g.path AS access_provider_path
|
||||
FROM
|
||||
channel_group cg
|
||||
JOIN
|
||||
"groups" g ON
|
||||
g.PATH @> cg.parent_group_path
|
||||
JOIN
|
||||
groups_roles gr ON
|
||||
g.id = gr.entity_id
|
||||
JOIN
|
||||
groups_role_members grm ON
|
||||
grm.role_id = gr.id
|
||||
JOIN
|
||||
groups_role_actions gra ON
|
||||
gra.role_id = gr.id
|
||||
JOIN
|
||||
groups_role_actions agg_gra ON
|
||||
agg_gra.role_id = gr.id
|
||||
WHERE
|
||||
(
|
||||
gra."action" LIKE 'channel%%'
|
||||
AND g.id = cg.parent_group_id
|
||||
)
|
||||
OR
|
||||
(
|
||||
gra."action" LIKE 'subgroup_channel%%'
|
||||
AND g.id <> cg.parent_group_id
|
||||
)
|
||||
GROUP BY
|
||||
gr.id,
|
||||
grm.member_id,
|
||||
g.id,
|
||||
cg.parent_group_id
|
||||
UNION
|
||||
SELECT
|
||||
dr."name",
|
||||
dr.id,
|
||||
drm.member_id,
|
||||
ARRAY_AGG(DISTINCT agg_dra."action") AS actions,
|
||||
'domain' AS access_type,
|
||||
d.id AS access_provider_id,
|
||||
''::::LTREE AS access_provider_path
|
||||
FROM
|
||||
channel_group cg
|
||||
JOIN
|
||||
domains d ON
|
||||
d.id = cg.domain_id
|
||||
JOIN
|
||||
domains_roles dr ON
|
||||
dr.entity_id = d.id
|
||||
JOIN
|
||||
domains_role_members drm ON
|
||||
dr.id = drm.role_id
|
||||
JOIN
|
||||
domains_role_actions dra ON
|
||||
dr.id = dra.role_id
|
||||
JOIN
|
||||
domains_role_actions agg_dra ON
|
||||
agg_dra.role_id = dr.id
|
||||
WHERE
|
||||
dra."action" LIKE 'channel%'
|
||||
GROUP BY
|
||||
dr.id,
|
||||
drm.member_id,
|
||||
d.id
|
||||
),
|
||||
members AS (
|
||||
SELECT
|
||||
um.member_id,
|
||||
JSONB_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'role_id', um.id,
|
||||
'role_name', um.name,
|
||||
'actions', um.actions,
|
||||
'access_type', um.access_type,
|
||||
'access_provider_id', um.access_provider_id,
|
||||
'access_provider_path', um.access_provider_path
|
||||
)
|
||||
) AS roles
|
||||
FROM
|
||||
ungrouped_members um
|
||||
GROUP BY
|
||||
um.member_id
|
||||
)
|
||||
`
|
||||
}
|
||||
|
||||
@@ -55,6 +55,91 @@ func (d Decoder) DecodeListRoles(_ context.Context, r *http.Request) (interface{
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (d Decoder) DecodeListEntityMembers(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
l, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
order, err := apiutil.ReadStringQuery(r, api.OrderKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
dir, err := apiutil.ReadStringQuery(r, api.LimitKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
accessProviderID, err := apiutil.ReadStringQuery(r, api.AccessProviderIDKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
accessType, err := apiutil.ReadStringQuery(r, api.AccessTypeKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
roleId, err := apiutil.ReadStringQuery(r, api.RoleIDKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
roleName, err := apiutil.ReadStringQuery(r, api.RoleNameKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
allActions, err := apiutil.ReadStringQuery(r, api.ActionsKey, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
actions := []string{}
|
||||
|
||||
allActions = strings.TrimSpace(allActions)
|
||||
if allActions != "" {
|
||||
actions = strings.Split(allActions, ",")
|
||||
}
|
||||
|
||||
req := listEntityMembersReq{
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
entityID: chi.URLParam(r, d.entityIDTemplate),
|
||||
limit: l,
|
||||
offset: o,
|
||||
order: order,
|
||||
dir: dir,
|
||||
accessProviderID: accessProviderID,
|
||||
roleId: roleId,
|
||||
roleName: roleName,
|
||||
actions: actions,
|
||||
accessType: accessType,
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (d Decoder) DecodeRemoveEntityMembers(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType)
|
||||
}
|
||||
|
||||
req := removeEntityMembersReq{
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
entityID: chi.URLParam(r, d.entityIDTemplate),
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(errors.ErrMalformedEntity, err))
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (d Decoder) DecodeViewRole(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
req := viewRoleReq{
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
|
||||
@@ -55,6 +55,57 @@ func ListRolesEndpoint(svc roles.RoleManager) endpoint.Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
func ListEntityMembersEndpoint(svc roles.RoleManager) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(listEntityMembersReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
session, ok := ctx.Value(api.SessionKey).(authn.Session)
|
||||
if !ok {
|
||||
return nil, svcerr.ErrAuthentication
|
||||
}
|
||||
|
||||
pageQuery := roles.MembersRolePageQuery{
|
||||
Offset: req.offset,
|
||||
Limit: req.limit,
|
||||
AccessProviderID: req.accessProviderID,
|
||||
Order: req.order,
|
||||
Dir: req.dir,
|
||||
RoleID: req.roleId,
|
||||
RoleName: req.roleName,
|
||||
Actions: req.actions,
|
||||
AccessType: req.accessType,
|
||||
}
|
||||
|
||||
mems, err := svc.ListEntityMembers(ctx, session, req.entityID, pageQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return listEntityMembersRes{mems}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func RemoveEntityMembersEndpoint(svc roles.RoleManager) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(removeEntityMembersReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
session, ok := ctx.Value(api.SessionKey).(authn.Session)
|
||||
if !ok {
|
||||
return nil, svcerr.ErrAuthentication
|
||||
}
|
||||
|
||||
if err := svc.RemoveEntityMembers(ctx, session, req.entityID, req.MemberIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return deleteEntityMembersRes{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ViewRoleEndpoint(svc roles.RoleManager) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(viewRoleReq)
|
||||
|
||||
@@ -53,6 +53,52 @@ func (req listRolesReq) validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type listEntityMembersReq struct {
|
||||
token string
|
||||
entityID string
|
||||
limit uint64
|
||||
offset uint64
|
||||
dir string
|
||||
order string
|
||||
accessProviderID string
|
||||
roleId string
|
||||
roleName string
|
||||
actions []string
|
||||
accessType string
|
||||
}
|
||||
|
||||
func (req listEntityMembersReq) validate() error {
|
||||
if req.token == "" {
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.entityID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
if req.limit > api.MaxLimitSize || req.limit < 1 {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type removeEntityMembersReq struct {
|
||||
token string
|
||||
entityID string
|
||||
MemberIDs []string `json:"member_ids"`
|
||||
}
|
||||
|
||||
func (req removeEntityMembersReq) validate() error {
|
||||
if req.token == "" {
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.entityID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
if len(req.MemberIDs) == 0 {
|
||||
return apiutil.ErrMissingMemberIDs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type viewRoleReq struct {
|
||||
token string
|
||||
entityID string
|
||||
|
||||
@@ -59,6 +59,36 @@ func (res listRolesRes) Empty() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type listEntityMembersRes struct {
|
||||
roles.MembersRolePage
|
||||
}
|
||||
|
||||
func (res listEntityMembersRes) Code() int {
|
||||
return http.StatusOK
|
||||
}
|
||||
|
||||
func (res listEntityMembersRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res listEntityMembersRes) Empty() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type deleteEntityMembersRes struct{}
|
||||
|
||||
func (res deleteEntityMembersRes) Code() int {
|
||||
return http.StatusNoContent
|
||||
}
|
||||
|
||||
func (res deleteEntityMembersRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res deleteEntityMembersRes) Empty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type viewRoleRes struct {
|
||||
roles.Role
|
||||
}
|
||||
|
||||
@@ -27,6 +27,20 @@ func EntityRoleMangerRouter(svc roles.RoleManager, d Decoder, r chi.Router, opts
|
||||
opts...,
|
||||
), "list_roles").ServeHTTP)
|
||||
|
||||
r.Get("/members", otelhttp.NewHandler(kithttp.NewServer(
|
||||
ListEntityMembersEndpoint(svc),
|
||||
d.DecodeListEntityMembers,
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "list_entity_members").ServeHTTP)
|
||||
|
||||
r.Delete("/", otelhttp.NewHandler(kithttp.NewServer(
|
||||
RemoveEntityMembersEndpoint(svc),
|
||||
d.DecodeListEntityMembers,
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "delete_entity_members").ServeHTTP)
|
||||
|
||||
r.Route("/{roleID}", func(r chi.Router) {
|
||||
r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
|
||||
ViewRoleEndpoint(svc),
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
"github.com/absmach/supermq/pkg/roles/rolemanager/events"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,17 +26,67 @@ const (
|
||||
)
|
||||
|
||||
type EventHandler struct {
|
||||
entityType string
|
||||
repo roles.Repository
|
||||
entityType string
|
||||
repo roles.Repository
|
||||
addRole string
|
||||
removeRole string
|
||||
updateRole string
|
||||
addRoleActions string
|
||||
removeRoleActions string
|
||||
removeAllRoleActions string
|
||||
addRoleMembers string
|
||||
removeRoleMembers string
|
||||
removeRoleAllMembers string
|
||||
removeMemberFromAllRoles string
|
||||
removeEntityMembers string
|
||||
}
|
||||
|
||||
func NewEventHandler(entityType string, repo roles.Repository) EventHandler {
|
||||
return EventHandler{
|
||||
entityType: entityType,
|
||||
repo: repo,
|
||||
entityType: entityType,
|
||||
repo: repo,
|
||||
addRole: entityType + "." + events.AddRole,
|
||||
removeRole: entityType + "." + events.RemoveRole,
|
||||
updateRole: entityType + "." + events.UpdateRole,
|
||||
addRoleActions: entityType + "." + events.AddRoleActions,
|
||||
removeRoleActions: entityType + "." + events.RemoveRoleActions,
|
||||
removeAllRoleActions: entityType + "." + events.RemoveAllRoleActions,
|
||||
addRoleMembers: entityType + "." + events.AddRoleMembers,
|
||||
removeRoleMembers: entityType + "." + events.RemoveRoleMembers,
|
||||
removeRoleAllMembers: entityType + "." + events.RemoveRoleAllMembers,
|
||||
removeMemberFromAllRoles: entityType + "." + events.RemoveMemberFromAllRoles,
|
||||
removeEntityMembers: entityType + "." + events.RemoveEntityMembers,
|
||||
}
|
||||
}
|
||||
|
||||
func (es *EventHandler) Handle(ctx context.Context, op interface{}, msg map[string]interface{}) error {
|
||||
switch op {
|
||||
case es.addRole:
|
||||
return es.AddEntityRoleHandler(ctx, msg)
|
||||
case es.removeRole:
|
||||
return es.RemoveEntityRoleHandler(ctx, msg)
|
||||
case es.updateRole:
|
||||
return es.UpdateEntityRoleHandler(ctx, msg)
|
||||
case es.addRoleActions:
|
||||
return es.AddEntityRoleActionsHandler(ctx, msg)
|
||||
case es.removeRoleActions:
|
||||
return es.RemoveEntityRoleActionsHandler(ctx, msg)
|
||||
case es.removeAllRoleActions:
|
||||
return es.RemoveAllEntityRoleActionsHandler(ctx, msg)
|
||||
case es.addRoleMembers:
|
||||
return es.AddEntityRoleMembersHandler(ctx, msg)
|
||||
case es.removeRoleMembers:
|
||||
return es.RemoveEntityRoleMembersHandler(ctx, msg)
|
||||
case es.removeRoleAllMembers:
|
||||
return es.RemoveAllMembersFromEntityRoleHandler(ctx, msg)
|
||||
case es.removeEntityMembers:
|
||||
return es.RemoveEntityMembersHandler(ctx, msg)
|
||||
case es.removeMemberFromAllRoles:
|
||||
return es.RemoveMemberFromAllEntityHandler(ctx, msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *EventHandler) AddEntityRoleHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
rps, err := ToRoleProvision(data)
|
||||
if err != nil {
|
||||
@@ -171,7 +222,7 @@ func (es *EventHandler) RemoveEntityRoleMembersHandler(ctx context.Context, data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *EventHandler) RemoveAllEntityRoleMembersHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
func (es *EventHandler) RemoveAllMembersFromEntityRoleHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
id, ok := data["role_id"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf(errRemoveEntityRoleAllMembersEvent, es.entityType, errRoleID)
|
||||
@@ -183,6 +234,26 @@ func (es *EventHandler) RemoveAllEntityRoleMembersHandler(ctx context.Context, d
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *EventHandler) RemoveEntityMembersHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
entityID, ok := data["entity_id"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf(errRemoveEntityRoleAllMembersEvent, es.entityType, errEntityID)
|
||||
}
|
||||
imems, ok := data["members"].([]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf(errRemoveEntityRoleMembersEvent, es.entityType, errMembers)
|
||||
}
|
||||
mems, err := ToStrings(imems)
|
||||
if err != nil {
|
||||
return fmt.Errorf(errRemoveEntityRoleMembersEvent, es.entityType, err)
|
||||
}
|
||||
|
||||
// added when repo is implemented.
|
||||
_ = entityID
|
||||
_ = mems
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *EventHandler) RemoveMemberFromAllEntityHandler(ctx context.Context, data map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,23 +9,25 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
addRole = "role.add"
|
||||
removeRole = "role.remove"
|
||||
updateRole = "role.update"
|
||||
viewRole = "role.view"
|
||||
viewAllRole = "role.view_all"
|
||||
listAvailableActions = "role.list_available_actions"
|
||||
addRoleActions = "role.actions.add"
|
||||
listRoleActions = "role.actions.ist"
|
||||
checkRoleActions = "role.actions.check"
|
||||
removeRoleActions = "role.actions.remove"
|
||||
removeAllRoleActions = "role.actions.remove_all"
|
||||
addRoleMembers = "role.members.add"
|
||||
listRoleMembers = "role.members.list"
|
||||
checkRoleMembers = "role.members.check"
|
||||
removeRoleMembers = "role.members.remove"
|
||||
removeRoleAllMembers = "role.members.remove_all"
|
||||
removeMemberFromAllRoles = "role.members.remove_from_all_roles"
|
||||
AddRole = "role.add"
|
||||
RemoveRole = "role.remove"
|
||||
UpdateRole = "role.update"
|
||||
ViewRole = "role.view"
|
||||
ViewAllRole = "role.view_all"
|
||||
ListAvailableActions = "role.list_available_actions"
|
||||
AddRoleActions = "role.actions.add"
|
||||
ListRoleActions = "role.actions.ist"
|
||||
CheckRoleActions = "role.actions.check"
|
||||
RemoveRoleActions = "role.actions.remove"
|
||||
RemoveAllRoleActions = "role.actions.remove_all"
|
||||
AddRoleMembers = "role.members.add"
|
||||
ListRoleMembers = "role.members.list"
|
||||
CheckRoleMembers = "role.members.check"
|
||||
RemoveRoleMembers = "role.members.remove"
|
||||
RemoveRoleAllMembers = "role.members.remove_all"
|
||||
ListEntityMembers = "members.list"
|
||||
RemoveEntityMembers = "members.remove"
|
||||
RemoveMemberFromAllRoles = "role.members.remove_from_all_roles"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -45,6 +47,8 @@ var (
|
||||
_ events.Event = (*roleCheckMembersExistsEvent)(nil)
|
||||
_ events.Event = (*roleRemoveMembersEvent)(nil)
|
||||
_ events.Event = (*roleRemoveAllMembersEvent)(nil)
|
||||
_ events.Event = (*listEntityMembersEvent)(nil)
|
||||
_ events.Event = (*removeEntityMembersEvent)(nil)
|
||||
_ events.Event = (*removeMemberFromAllRolesEvent)(nil)
|
||||
)
|
||||
|
||||
@@ -55,7 +59,7 @@ type addRoleEvent struct {
|
||||
|
||||
func (are addRoleEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": are.operationPrefix + addRole,
|
||||
"operation": are.operationPrefix + AddRole,
|
||||
"id": are.ID,
|
||||
"name": are.Name,
|
||||
"entity_id": are.EntityID,
|
||||
@@ -77,7 +81,7 @@ type removeRoleEvent struct {
|
||||
|
||||
func (rre removeRoleEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rre.operationPrefix + removeRole,
|
||||
"operation": rre.operationPrefix + RemoveRole,
|
||||
"entity_id": rre.entityID,
|
||||
"role_id": rre.roleID,
|
||||
}
|
||||
@@ -91,7 +95,7 @@ type updateRoleEvent struct {
|
||||
|
||||
func (ure updateRoleEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": ure.operationPrefix + updateRole,
|
||||
"operation": ure.operationPrefix + UpdateRole,
|
||||
"id": ure.ID,
|
||||
"name": ure.Name,
|
||||
"entity_id": ure.EntityID,
|
||||
@@ -110,7 +114,7 @@ type retrieveRoleEvent struct {
|
||||
|
||||
func (rre retrieveRoleEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rre.operationPrefix + viewRole,
|
||||
"operation": rre.operationPrefix + ViewRole,
|
||||
"id": rre.ID,
|
||||
"name": rre.Name,
|
||||
"entity_id": rre.EntityID,
|
||||
@@ -131,7 +135,7 @@ type retrieveAllRolesEvent struct {
|
||||
|
||||
func (rare retrieveAllRolesEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rare.operationPrefix + viewAllRole,
|
||||
"operation": rare.operationPrefix + ViewAllRole,
|
||||
"entity_id": rare.entityID,
|
||||
"limit": rare.limit,
|
||||
"offset": rare.offset,
|
||||
@@ -145,7 +149,7 @@ type listAvailableActionsEvent struct {
|
||||
|
||||
func (laae listAvailableActionsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": laae.operationPrefix + listAvailableActions,
|
||||
"operation": laae.operationPrefix + ListAvailableActions,
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
@@ -159,7 +163,7 @@ type roleAddActionsEvent struct {
|
||||
|
||||
func (raae roleAddActionsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": raae.operationPrefix + addRoleActions,
|
||||
"operation": raae.operationPrefix + AddRoleActions,
|
||||
"entity_id": raae.entityID,
|
||||
"role_id": raae.roleID,
|
||||
"actions": raae.actions,
|
||||
@@ -175,7 +179,7 @@ type roleListActionsEvent struct {
|
||||
|
||||
func (rlae roleListActionsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rlae.operationPrefix + listRoleActions,
|
||||
"operation": rlae.operationPrefix + ListRoleActions,
|
||||
"entity_id": rlae.entityID,
|
||||
"role_id": rlae.roleID,
|
||||
}
|
||||
@@ -192,7 +196,7 @@ type roleCheckActionsExistsEvent struct {
|
||||
|
||||
func (rcaee roleCheckActionsExistsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rcaee.operationPrefix + checkRoleActions,
|
||||
"operation": rcaee.operationPrefix + CheckRoleActions,
|
||||
"entity_id": rcaee.entityID,
|
||||
"role_id": rcaee.roleID,
|
||||
"actions": rcaee.actions,
|
||||
@@ -210,7 +214,7 @@ type roleRemoveActionsEvent struct {
|
||||
|
||||
func (rrae roleRemoveActionsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rrae.operationPrefix + removeRoleActions,
|
||||
"operation": rrae.operationPrefix + RemoveRoleActions,
|
||||
"entity_id": rrae.entityID,
|
||||
"role_id": rrae.roleID,
|
||||
"actions": rrae.actions,
|
||||
@@ -226,7 +230,7 @@ type roleRemoveAllActionsEvent struct {
|
||||
|
||||
func (rraae roleRemoveAllActionsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rraae.operationPrefix + removeAllRoleActions,
|
||||
"operation": rraae.operationPrefix + RemoveAllRoleActions,
|
||||
"entity_id": rraae.entityID,
|
||||
"role_id": rraae.roleID,
|
||||
}
|
||||
@@ -242,7 +246,7 @@ type roleAddMembersEvent struct {
|
||||
|
||||
func (rame roleAddMembersEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rame.operationPrefix + addRoleMembers,
|
||||
"operation": rame.operationPrefix + AddRoleMembers,
|
||||
"entity_id": rame.entityID,
|
||||
"role_id": rame.roleID,
|
||||
"members": rame.members,
|
||||
@@ -260,7 +264,7 @@ type roleListMembersEvent struct {
|
||||
|
||||
func (rlme roleListMembersEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rlme.operationPrefix + listRoleMembers,
|
||||
"operation": rlme.operationPrefix + ListRoleMembers,
|
||||
"entity_id": rlme.entityID,
|
||||
"role_id": rlme.roleID,
|
||||
"limit": rlme.limit,
|
||||
@@ -278,7 +282,7 @@ type roleCheckMembersExistsEvent struct {
|
||||
|
||||
func (rcmee roleCheckMembersExistsEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rcmee.operationPrefix + checkRoleMembers,
|
||||
"operation": rcmee.operationPrefix + CheckRoleMembers,
|
||||
"entity_id": rcmee.entityID,
|
||||
"role_id": rcmee.roleID,
|
||||
"members": rcmee.members,
|
||||
@@ -295,7 +299,7 @@ type roleRemoveMembersEvent struct {
|
||||
|
||||
func (rrme roleRemoveMembersEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rrme.operationPrefix + removeRoleMembers,
|
||||
"operation": rrme.operationPrefix + RemoveRoleMembers,
|
||||
"entity_id": rrme.entityID,
|
||||
"role_id": rrme.roleID,
|
||||
"members": rrme.members,
|
||||
@@ -311,13 +315,45 @@ type roleRemoveAllMembersEvent struct {
|
||||
|
||||
func (rrame roleRemoveAllMembersEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rrame.operationPrefix + removeRoleAllMembers,
|
||||
"operation": rrame.operationPrefix + RemoveRoleAllMembers,
|
||||
"entity_id": rrame.entityID,
|
||||
"role_id": rrame.roleID,
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
type listEntityMembersEvent struct {
|
||||
operationPrefix string
|
||||
entityID string
|
||||
limit uint64
|
||||
offset uint64
|
||||
}
|
||||
|
||||
func (leme listEntityMembersEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": leme.operationPrefix + ListEntityMembers,
|
||||
"entity_id": leme.entityID,
|
||||
"limit": leme.limit,
|
||||
"offset": leme.offset,
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
type removeEntityMembersEvent struct {
|
||||
operationPrefix string
|
||||
entityID string
|
||||
members []string
|
||||
}
|
||||
|
||||
func (reme removeEntityMembersEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": reme.operationPrefix + RemoveEntityMembers,
|
||||
"entity_id": reme.entityID,
|
||||
"members": reme.members,
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
type removeMemberFromAllRolesEvent struct {
|
||||
operationPrefix string
|
||||
memberID string
|
||||
@@ -325,7 +361,7 @@ type removeMemberFromAllRolesEvent struct {
|
||||
|
||||
func (rmare removeMemberFromAllRolesEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": rmare.operationPrefix + removeMemberFromAllRoles,
|
||||
"operation": rmare.operationPrefix + RemoveMemberFromAllRoles,
|
||||
"member_id": rmare.memberID,
|
||||
}
|
||||
return val, nil
|
||||
|
||||
@@ -299,6 +299,40 @@ func (rmes *RoleManagerEventStore) RoleRemoveAllMembers(ctx context.Context, ses
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rmes *RoleManagerEventStore) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
mems, err := rmes.svc.ListEntityMembers(ctx, session, entityID, pageQuery)
|
||||
if err != nil {
|
||||
return mems, err
|
||||
}
|
||||
|
||||
e := listEntityMembersEvent{
|
||||
operationPrefix: rmes.operationPrefix,
|
||||
entityID: entityID,
|
||||
limit: pageQuery.Limit,
|
||||
offset: pageQuery.Offset,
|
||||
}
|
||||
if err := rmes.Publish(ctx, e); err != nil {
|
||||
return mems, err
|
||||
}
|
||||
return mems, nil
|
||||
}
|
||||
|
||||
func (rmes *RoleManagerEventStore) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
if err := rmes.svc.RemoveEntityMembers(ctx, session, entityID, members); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e := removeEntityMembersEvent{
|
||||
operationPrefix: rmes.operationPrefix,
|
||||
entityID: entityID,
|
||||
members: members,
|
||||
}
|
||||
if err := rmes.Publish(ctx, e); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rmes *RoleManagerEventStore) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) (err error) {
|
||||
if err := rmes.svc.RemoveMemberFromAllRoles(ctx, session, memberID); err != nil {
|
||||
return err
|
||||
|
||||
@@ -240,20 +240,6 @@ func (ram RoleManagerAuthorizationMiddleware) RoleCheckMembersExists(ctx context
|
||||
return ram.svc.RoleCheckMembersExists(ctx, session, entityID, roleID, members)
|
||||
}
|
||||
|
||||
func (ram RoleManagerAuthorizationMiddleware) RoleRemoveMembers(ctx context.Context, session authn.Session, entityID, roleID string, members []string) (err error) {
|
||||
if err := ram.authorize(ctx, roles.OpRoleRemoveMembers, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
Subject: session.DomainUserID,
|
||||
SubjectType: policies.UserType,
|
||||
SubjectKind: policies.UsersKind,
|
||||
Object: entityID,
|
||||
ObjectType: ram.entityType,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return ram.svc.RoleRemoveMembers(ctx, session, entityID, roleID, members)
|
||||
}
|
||||
|
||||
func (ram RoleManagerAuthorizationMiddleware) RoleRemoveAllMembers(ctx context.Context, session authn.Session, entityID, roleID string) (err error) {
|
||||
if err := ram.authorize(ctx, roles.OpRoleRemoveAllMembers, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
@@ -268,6 +254,48 @@ func (ram RoleManagerAuthorizationMiddleware) RoleRemoveAllMembers(ctx context.C
|
||||
return ram.svc.RoleRemoveAllMembers(ctx, session, entityID, roleID)
|
||||
}
|
||||
|
||||
func (ram RoleManagerAuthorizationMiddleware) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
if err := ram.authorize(ctx, roles.OpRoleListMembers, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
Subject: session.DomainUserID,
|
||||
SubjectType: policies.UserType,
|
||||
SubjectKind: policies.UsersKind,
|
||||
Object: entityID,
|
||||
ObjectType: ram.entityType,
|
||||
}); err != nil {
|
||||
return roles.MembersRolePage{}, err
|
||||
}
|
||||
return ram.svc.ListEntityMembers(ctx, session, entityID, pageQuery)
|
||||
}
|
||||
|
||||
func (ram RoleManagerAuthorizationMiddleware) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
if err := ram.authorize(ctx, roles.OpRoleRemoveAllMembers, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
Subject: session.DomainUserID,
|
||||
SubjectType: policies.UserType,
|
||||
SubjectKind: policies.UsersKind,
|
||||
Object: entityID,
|
||||
ObjectType: ram.entityType,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return ram.svc.RemoveEntityMembers(ctx, session, entityID, members)
|
||||
}
|
||||
|
||||
func (ram RoleManagerAuthorizationMiddleware) RoleRemoveMembers(ctx context.Context, session authn.Session, entityID, roleID string, members []string) (err error) {
|
||||
if err := ram.authorize(ctx, roles.OpRoleRemoveMembers, smqauthz.PolicyReq{
|
||||
Domain: session.DomainID,
|
||||
Subject: session.DomainUserID,
|
||||
SubjectType: policies.UserType,
|
||||
SubjectKind: policies.UsersKind,
|
||||
Object: entityID,
|
||||
ObjectType: ram.entityType,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return ram.svc.RoleRemoveMembers(ctx, session, entityID, roleID, members)
|
||||
}
|
||||
|
||||
func (ram RoleManagerAuthorizationMiddleware) authorize(ctx context.Context, op svcutil.Operation, pr smqauthz.PolicyReq) error {
|
||||
perm, err := ram.opp.GetPermission(op)
|
||||
if err != nil {
|
||||
|
||||
@@ -326,6 +326,47 @@ func (lm *RoleManagerLoggingMiddleware) RoleRemoveAllMembers(ctx context.Context
|
||||
return lm.svc.RoleRemoveAllMembers(ctx, session, entityID, roleID)
|
||||
}
|
||||
|
||||
func (lm *RoleManagerLoggingMiddleware) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pageQuery roles.MembersRolePageQuery) (mems roles.MembersRolePage, err error) {
|
||||
prefix := fmt.Sprintf("%s list entity members", lm.svcName)
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.Group(lm.svcName+"_remove_entity_members",
|
||||
slog.String("entity_id", entityID),
|
||||
slog.Uint64("limit", pageQuery.Limit),
|
||||
slog.Uint64("offset", pageQuery.Offset),
|
||||
),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.String("error", err.Error()))
|
||||
lm.logger.Warn(prefix+" failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info(prefix+" completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.ListEntityMembers(ctx, session, entityID, pageQuery)
|
||||
}
|
||||
|
||||
func (lm *RoleManagerLoggingMiddleware) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) (err error) {
|
||||
prefix := fmt.Sprintf("%s remove entity members", lm.svcName)
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.Group(lm.svcName+"_remove_entity_members",
|
||||
slog.String("entity_id", entityID),
|
||||
slog.Any("member_ids", members),
|
||||
),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.String("error", err.Error()))
|
||||
lm.logger.Warn(prefix+" failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info(prefix+" completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.RemoveEntityMembers(ctx, session, entityID, members)
|
||||
}
|
||||
|
||||
func (lm *RoleManagerLoggingMiddleware) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) (err error) {
|
||||
prefix := fmt.Sprintf("%s remove members from all roles", lm.svcName)
|
||||
defer func(begin time.Time) {
|
||||
|
||||
@@ -95,6 +95,14 @@ func (rmm *RoleManagerMetricsMiddleware) RoleRemoveAllMembers(ctx context.Contex
|
||||
return rmm.svc.RoleRemoveAllMembers(ctx, session, entityID, roleID)
|
||||
}
|
||||
|
||||
func (rmm *RoleManagerMetricsMiddleware) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
return rmm.svc.ListEntityMembers(ctx, session, entityID, pageQuery)
|
||||
}
|
||||
|
||||
func (rmm *RoleManagerMetricsMiddleware) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
return rmm.svc.RemoveEntityMembers(ctx, session, entityID, members)
|
||||
}
|
||||
|
||||
func (rmm *RoleManagerMetricsMiddleware) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) (err error) {
|
||||
return rmm.svc.RemoveMemberFromAllRoles(ctx, session, memberID)
|
||||
}
|
||||
|
||||
@@ -87,6 +87,14 @@ func (rtm *RoleManagerTracing) RoleRemoveAllMembers(ctx context.Context, session
|
||||
return rtm.roles.RoleRemoveAllMembers(ctx, session, entityID, roleID)
|
||||
}
|
||||
|
||||
func (rtm *RoleManagerTracing) ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pageQuery roles.MembersRolePageQuery) (roles.MembersRolePage, error) {
|
||||
return rtm.roles.ListEntityMembers(ctx, session, entityID, pageQuery)
|
||||
}
|
||||
|
||||
func (rtm *RoleManagerTracing) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
|
||||
return rtm.roles.RemoveEntityMembers(ctx, session, entityID, members)
|
||||
}
|
||||
|
||||
func (rtm *RoleManagerTracing) RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) (err error) {
|
||||
return rtm.roles.RemoveMemberFromAllRoles(ctx, session, memberID)
|
||||
}
|
||||
|
||||
@@ -63,6 +63,39 @@ type RolePage struct {
|
||||
Roles []Role `json:"roles"`
|
||||
}
|
||||
|
||||
type MemberRoleActions struct {
|
||||
RoleID string `json:"role_id"`
|
||||
RoleName string `json:"role_name"`
|
||||
Actions []string `json:"actions,omitempty"`
|
||||
AccessProviderID string `json:"access_provider_id,omitempty"`
|
||||
AccessProviderPath string `json:"access_provider_path,omitempty"`
|
||||
AccessType string `json:"access_type,omitempty"`
|
||||
}
|
||||
type MemberRoles struct {
|
||||
MemberID string `json:"member_id,omitempty"`
|
||||
Roles []MemberRoleActions `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
type MembersRolePage struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Members []MemberRoles `json:"members"`
|
||||
}
|
||||
|
||||
type MembersRolePageQuery struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Order string `json:"order_by"`
|
||||
Dir string `json:"dir"`
|
||||
AccessProviderID string `json:"access_provider_id"`
|
||||
RoleID string `json:"role_id"`
|
||||
RoleName string `json:"role_name"`
|
||||
Actions []string `json:"actions"`
|
||||
AccessType string `json:"access_type"`
|
||||
}
|
||||
|
||||
type MembersPage struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
@@ -124,6 +157,10 @@ type RoleManager interface {
|
||||
|
||||
RoleRemoveAllMembers(ctx context.Context, session authn.Session, entityID, roleID string) (err error)
|
||||
|
||||
ListEntityMembers(ctx context.Context, session authn.Session, entityID string, pq MembersRolePageQuery) (MembersRolePage, error)
|
||||
|
||||
RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) (err error)
|
||||
|
||||
RemoveMemberFromAllRoles(ctx context.Context, session authn.Session, memberID string) (err error)
|
||||
}
|
||||
|
||||
@@ -146,6 +183,8 @@ type Repository interface {
|
||||
RoleRemoveMembers(ctx context.Context, role Role, members []string) (err error)
|
||||
RoleRemoveAllMembers(ctx context.Context, role Role) (err error)
|
||||
RetrieveEntitiesRolesActionsMembers(ctx context.Context, entityIDs []string) ([]EntityActionRole, []EntityMemberRole, error)
|
||||
ListEntityMembers(ctx context.Context, entityID string, pageQuery MembersRolePageQuery) (MembersRolePage, error)
|
||||
RemoveEntityMembers(ctx context.Context, entityID string, members []string) error
|
||||
RemoveMemberFromAllRoles(ctx context.Context, memberID string) (err error)
|
||||
}
|
||||
|
||||
|
||||
@@ -276,3 +276,7 @@ func (sdk mgSDK) RemoveChannelParent(id, domainID, groupID, token string) errors
|
||||
|
||||
return sdkerr
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListChannelMembers(channelID, domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError) {
|
||||
return sdk.listEntityMembers(sdk.channelsURL, domainID, channelsEndpoint, channelID, token, pm)
|
||||
}
|
||||
|
||||
@@ -307,3 +307,7 @@ func (sdk mgSDK) RemoveAllClientRoleMembers(id, roleID, domainID, token string)
|
||||
func (sdk mgSDK) AvailableClientRoleActions(domainID, token string) ([]string, errors.SDKError) {
|
||||
return sdk.listAvailableRoleActions(sdk.clientsURL, clientsEndpoint, domainID, token)
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListClientMembers(clientID, domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError) {
|
||||
return sdk.listEntityMembers(sdk.clientsURL, domainID, clientsEndpoint, clientID, token, pm)
|
||||
}
|
||||
|
||||
@@ -188,3 +188,7 @@ func (sdk mgSDK) RemoveAllDomainRoleMembers(id, roleID, token string) errors.SDK
|
||||
func (sdk mgSDK) AvailableDomainRoleActions(token string) ([]string, errors.SDKError) {
|
||||
return sdk.listAvailableRoleActions(sdk.domainsURL, domainsEndpoint, "", token)
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListDomainMembers(domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError) {
|
||||
return sdk.listEntityMembers(sdk.domainsURL, domainID, domainsEndpoint, domainID, token, pm)
|
||||
}
|
||||
|
||||
@@ -318,3 +318,7 @@ func (sdk mgSDK) RemoveAllGroupRoleMembers(id, roleID, domainID, token string) e
|
||||
func (sdk mgSDK) AvailableGroupRoleActions(domainID, token string) ([]string, errors.SDKError) {
|
||||
return sdk.listAvailableRoleActions(sdk.groupsURL, groupsEndpoint, domainID, token)
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListGroupMembers(groupID, domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError) {
|
||||
return sdk.listEntityMembers(sdk.groupsURL, domainID, groupsEndpoint, groupID, token, pm)
|
||||
}
|
||||
|
||||
+60
-60
@@ -4211,23 +4211,23 @@ func (_c *SDK_Journal_Call) RunAndReturn(run func(string, string, string, sdk.Pa
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListChannelUsers provides a mock function with given fields: channelID, domainID, pm, token
|
||||
func (_m *SDK) ListChannelUsers(channelID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) {
|
||||
// ListChannelMembers provides a mock function with given fields: channelID, domainID, pm, token
|
||||
func (_m *SDK) ListChannelMembers(channelID string, domainID string, pm sdk.PageMetadata, token string) (sdk.EntityMembersPage, errors.SDKError) {
|
||||
ret := _m.Called(channelID, domainID, pm, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListChannelUsers")
|
||||
panic("no return value specified for ListChannelMembers")
|
||||
}
|
||||
|
||||
var r0 sdk.UsersPage
|
||||
var r0 sdk.EntityMembersPage
|
||||
var r1 errors.SDKError
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)); ok {
|
||||
return rf(channelID, domainID, pm, token)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.UsersPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.EntityMembersPage); ok {
|
||||
r0 = rf(channelID, domainID, pm, token)
|
||||
} else {
|
||||
r0 = ret.Get(0).(sdk.UsersPage)
|
||||
r0 = ret.Get(0).(sdk.EntityMembersPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string, string, sdk.PageMetadata, string) errors.SDKError); ok {
|
||||
@@ -4241,54 +4241,54 @@ func (_m *SDK) ListChannelUsers(channelID string, domainID string, pm sdk.PageMe
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SDK_ListChannelUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListChannelUsers'
|
||||
type SDK_ListChannelUsers_Call struct {
|
||||
// SDK_ListChannelMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListChannelMembers'
|
||||
type SDK_ListChannelMembers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListChannelUsers is a helper method to define mock.On call
|
||||
// ListChannelMembers is a helper method to define mock.On call
|
||||
// - channelID string
|
||||
// - domainID string
|
||||
// - pm sdk.PageMetadata
|
||||
// - token string
|
||||
func (_e *SDK_Expecter) ListChannelUsers(channelID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListChannelUsers_Call {
|
||||
return &SDK_ListChannelUsers_Call{Call: _e.mock.On("ListChannelUsers", channelID, domainID, pm, token)}
|
||||
func (_e *SDK_Expecter) ListChannelMembers(channelID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListChannelMembers_Call {
|
||||
return &SDK_ListChannelMembers_Call{Call: _e.mock.On("ListChannelMembers", channelID, domainID, pm, token)}
|
||||
}
|
||||
|
||||
func (_c *SDK_ListChannelUsers_Call) Run(run func(channelID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListChannelUsers_Call {
|
||||
func (_c *SDK_ListChannelMembers_Call) Run(run func(channelID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListChannelMembers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_ListChannelUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_ListChannelUsers_Call {
|
||||
func (_c *SDK_ListChannelMembers_Call) Return(_a0 sdk.EntityMembersPage, _a1 errors.SDKError) *SDK_ListChannelMembers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_ListChannelUsers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_ListChannelUsers_Call {
|
||||
func (_c *SDK_ListChannelMembers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)) *SDK_ListChannelMembers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListClientUsers provides a mock function with given fields: clientID, domainID, pm, token
|
||||
func (_m *SDK) ListClientUsers(clientID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) {
|
||||
// ListClientMembers provides a mock function with given fields: clientID, domainID, pm, token
|
||||
func (_m *SDK) ListClientMembers(clientID string, domainID string, pm sdk.PageMetadata, token string) (sdk.EntityMembersPage, errors.SDKError) {
|
||||
ret := _m.Called(clientID, domainID, pm, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListClientUsers")
|
||||
panic("no return value specified for ListClientMembers")
|
||||
}
|
||||
|
||||
var r0 sdk.UsersPage
|
||||
var r0 sdk.EntityMembersPage
|
||||
var r1 errors.SDKError
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)); ok {
|
||||
return rf(clientID, domainID, pm, token)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.UsersPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.EntityMembersPage); ok {
|
||||
r0 = rf(clientID, domainID, pm, token)
|
||||
} else {
|
||||
r0 = ret.Get(0).(sdk.UsersPage)
|
||||
r0 = ret.Get(0).(sdk.EntityMembersPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string, string, sdk.PageMetadata, string) errors.SDKError); ok {
|
||||
@@ -4302,54 +4302,54 @@ func (_m *SDK) ListClientUsers(clientID string, domainID string, pm sdk.PageMeta
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SDK_ListClientUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListClientUsers'
|
||||
type SDK_ListClientUsers_Call struct {
|
||||
// SDK_ListClientMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListClientMembers'
|
||||
type SDK_ListClientMembers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListClientUsers is a helper method to define mock.On call
|
||||
// ListClientMembers is a helper method to define mock.On call
|
||||
// - clientID string
|
||||
// - domainID string
|
||||
// - pm sdk.PageMetadata
|
||||
// - token string
|
||||
func (_e *SDK_Expecter) ListClientUsers(clientID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListClientUsers_Call {
|
||||
return &SDK_ListClientUsers_Call{Call: _e.mock.On("ListClientUsers", clientID, domainID, pm, token)}
|
||||
func (_e *SDK_Expecter) ListClientMembers(clientID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListClientMembers_Call {
|
||||
return &SDK_ListClientMembers_Call{Call: _e.mock.On("ListClientMembers", clientID, domainID, pm, token)}
|
||||
}
|
||||
|
||||
func (_c *SDK_ListClientUsers_Call) Run(run func(clientID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListClientUsers_Call {
|
||||
func (_c *SDK_ListClientMembers_Call) Run(run func(clientID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListClientMembers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_ListClientUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_ListClientUsers_Call {
|
||||
func (_c *SDK_ListClientMembers_Call) Return(_a0 sdk.EntityMembersPage, _a1 errors.SDKError) *SDK_ListClientMembers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_ListClientUsers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_ListClientUsers_Call {
|
||||
func (_c *SDK_ListClientMembers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)) *SDK_ListClientMembers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListDomainUsers provides a mock function with given fields: domainID, pm, token
|
||||
func (_m *SDK) ListDomainUsers(domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) {
|
||||
// ListDomainMembers provides a mock function with given fields: domainID, pm, token
|
||||
func (_m *SDK) ListDomainMembers(domainID string, pm sdk.PageMetadata, token string) (sdk.EntityMembersPage, errors.SDKError) {
|
||||
ret := _m.Called(domainID, pm, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListDomainUsers")
|
||||
panic("no return value specified for ListDomainMembers")
|
||||
}
|
||||
|
||||
var r0 sdk.UsersPage
|
||||
var r0 sdk.EntityMembersPage
|
||||
var r1 errors.SDKError
|
||||
if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)); ok {
|
||||
return rf(domainID, pm, token)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string) sdk.UsersPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string) sdk.EntityMembersPage); ok {
|
||||
r0 = rf(domainID, pm, token)
|
||||
} else {
|
||||
r0 = ret.Get(0).(sdk.UsersPage)
|
||||
r0 = ret.Get(0).(sdk.EntityMembersPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string, sdk.PageMetadata, string) errors.SDKError); ok {
|
||||
@@ -4363,53 +4363,53 @@ func (_m *SDK) ListDomainUsers(domainID string, pm sdk.PageMetadata, token strin
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SDK_ListDomainUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListDomainUsers'
|
||||
type SDK_ListDomainUsers_Call struct {
|
||||
// SDK_ListDomainMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListDomainMembers'
|
||||
type SDK_ListDomainMembers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListDomainUsers is a helper method to define mock.On call
|
||||
// ListDomainMembers is a helper method to define mock.On call
|
||||
// - domainID string
|
||||
// - pm sdk.PageMetadata
|
||||
// - token string
|
||||
func (_e *SDK_Expecter) ListDomainUsers(domainID interface{}, pm interface{}, token interface{}) *SDK_ListDomainUsers_Call {
|
||||
return &SDK_ListDomainUsers_Call{Call: _e.mock.On("ListDomainUsers", domainID, pm, token)}
|
||||
func (_e *SDK_Expecter) ListDomainMembers(domainID interface{}, pm interface{}, token interface{}) *SDK_ListDomainMembers_Call {
|
||||
return &SDK_ListDomainMembers_Call{Call: _e.mock.On("ListDomainMembers", domainID, pm, token)}
|
||||
}
|
||||
|
||||
func (_c *SDK_ListDomainUsers_Call) Run(run func(domainID string, pm sdk.PageMetadata, token string)) *SDK_ListDomainUsers_Call {
|
||||
func (_c *SDK_ListDomainMembers_Call) Run(run func(domainID string, pm sdk.PageMetadata, token string)) *SDK_ListDomainMembers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string), args[1].(sdk.PageMetadata), args[2].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_ListDomainUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_ListDomainUsers_Call {
|
||||
func (_c *SDK_ListDomainMembers_Call) Return(_a0 sdk.EntityMembersPage, _a1 errors.SDKError) *SDK_ListDomainMembers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_ListDomainUsers_Call) RunAndReturn(run func(string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_ListDomainUsers_Call {
|
||||
func (_c *SDK_ListDomainMembers_Call) RunAndReturn(run func(string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)) *SDK_ListDomainMembers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Members provides a mock function with given fields: groupID, domainID, pm, token
|
||||
func (_m *SDK) Members(groupID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) {
|
||||
// ListGroupMembers provides a mock function with given fields: groupID, domainID, pm, token
|
||||
func (_m *SDK) ListGroupMembers(groupID string, domainID string, pm sdk.PageMetadata, token string) (sdk.EntityMembersPage, errors.SDKError) {
|
||||
ret := _m.Called(groupID, domainID, pm, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Members")
|
||||
panic("no return value specified for ListGroupMembers")
|
||||
}
|
||||
|
||||
var r0 sdk.UsersPage
|
||||
var r0 sdk.EntityMembersPage
|
||||
var r1 errors.SDKError
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)); ok {
|
||||
return rf(groupID, domainID, pm, token)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.UsersPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.EntityMembersPage); ok {
|
||||
r0 = rf(groupID, domainID, pm, token)
|
||||
} else {
|
||||
r0 = ret.Get(0).(sdk.UsersPage)
|
||||
r0 = ret.Get(0).(sdk.EntityMembersPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string, string, sdk.PageMetadata, string) errors.SDKError); ok {
|
||||
@@ -4423,33 +4423,33 @@ func (_m *SDK) Members(groupID string, domainID string, pm sdk.PageMetadata, tok
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SDK_Members_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Members'
|
||||
type SDK_Members_Call struct {
|
||||
// SDK_ListGroupMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListGroupMembers'
|
||||
type SDK_ListGroupMembers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Members is a helper method to define mock.On call
|
||||
// ListGroupMembers is a helper method to define mock.On call
|
||||
// - groupID string
|
||||
// - domainID string
|
||||
// - pm sdk.PageMetadata
|
||||
// - token string
|
||||
func (_e *SDK_Expecter) Members(groupID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_Members_Call {
|
||||
return &SDK_Members_Call{Call: _e.mock.On("Members", groupID, domainID, pm, token)}
|
||||
func (_e *SDK_Expecter) ListGroupMembers(groupID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListGroupMembers_Call {
|
||||
return &SDK_ListGroupMembers_Call{Call: _e.mock.On("ListGroupMembers", groupID, domainID, pm, token)}
|
||||
}
|
||||
|
||||
func (_c *SDK_Members_Call) Run(run func(groupID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_Members_Call {
|
||||
func (_c *SDK_ListGroupMembers_Call) Run(run func(groupID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListGroupMembers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_Members_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_Members_Call {
|
||||
func (_c *SDK_ListGroupMembers_Call) Return(_a0 sdk.EntityMembersPage, _a1 errors.SDKError) *SDK_ListGroupMembers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_Members_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_Members_Call {
|
||||
func (_c *SDK_ListGroupMembers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.EntityMembersPage, errors.SDKError)) *SDK_ListGroupMembers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
@@ -101,3 +101,22 @@ type RoleMembersPage struct {
|
||||
Limit uint64 `json:"limit"`
|
||||
Members []string `json:"members"`
|
||||
}
|
||||
|
||||
type MemberRole struct {
|
||||
Actions []string `json:"actions,omitempty"`
|
||||
RoleName string `json:"role_name,omitempty"`
|
||||
RoleID string `json:"role_id,omitempty"`
|
||||
AccessType string `json:"access_type,omitempty"`
|
||||
AccessProviderID string `json:"access_provider_id,omitempty"`
|
||||
AccessProviderPath string `json:"access_provider_path,omitempty"`
|
||||
}
|
||||
type MemberRoles struct {
|
||||
MemberID string `json:"member_id"`
|
||||
Roles []MemberRole `json:"roles"`
|
||||
}
|
||||
type EntityMembersPage struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Members []MemberRoles `json:"members"`
|
||||
}
|
||||
|
||||
@@ -266,3 +266,26 @@ func (sdk mgSDK) listAvailableRoleActions(entityURL, entityEndpoint, domainID, t
|
||||
|
||||
return res.AvailableActions, nil
|
||||
}
|
||||
|
||||
func (sdk mgSDK) listEntityMembers(entityURL, domainID, entityEndpoint, id, token string, pm PageMetadata) (EntityMembersPage, errors.SDKError) {
|
||||
ep := fmt.Sprintf("%s/%s/%s/%s/%s", domainID, entityEndpoint, id, rolesEndpoint, membersEndpoint)
|
||||
if entityEndpoint == domainsEndpoint {
|
||||
ep = fmt.Sprintf("%s/%s/%s/%s", entityEndpoint, id, rolesEndpoint, membersEndpoint)
|
||||
}
|
||||
url, err := sdk.withQueryParams(entityURL, ep, pm)
|
||||
if err != nil {
|
||||
return EntityMembersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
_, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK)
|
||||
if sdkerr != nil {
|
||||
return EntityMembersPage{}, sdkerr
|
||||
}
|
||||
|
||||
res := EntityMembersPage{}
|
||||
if err := json.Unmarshal(body, &res); err != nil {
|
||||
return EntityMembersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
+44
-47
@@ -196,17 +196,6 @@ type SDK interface {
|
||||
// fmt.Println(users)
|
||||
Users(pm PageMetadata, token string) (UsersPage, errors.SDKError)
|
||||
|
||||
// Members returns list of users that are members of a group.
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// }
|
||||
// members, _ := sdk.Members("groupID","domainID", pm, "token")
|
||||
// fmt.Println(members)
|
||||
Members(groupID, domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError)
|
||||
|
||||
// UserProfile returns user logged in.
|
||||
//
|
||||
// example:
|
||||
@@ -359,42 +348,6 @@ type SDK interface {
|
||||
// fmt.Println(users)
|
||||
SearchUsers(pm PageMetadata, token string) (UsersPage, errors.SDKError)
|
||||
|
||||
// ListClientUsers all users in a client.
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// Permission: "edit", // available Options: "administrator", "administrator", "delete", edit", "view", "share", "owner", "owner", "admin", "editor", "contributor", "editor", "viewer", "guest", "create"
|
||||
// }
|
||||
// users, _ := sdk.ListClientUsers("client_id", pm, "domainID", "token")
|
||||
// fmt.Println(users)
|
||||
ListClientUsers(clientID, domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError)
|
||||
|
||||
// ListChannelUsers list all users in a channel .
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// Permission: "edit", // available Options: "administrator", "administrator", "delete", edit", "view", "share", "owner", "owner", "admin", "editor", "contributor", "editor", "viewer", "guest", "create"
|
||||
// }
|
||||
// users, _ := sdk.ListChannelUsers("channel_id","domainID", pm, "token")
|
||||
// fmt.Println(users)
|
||||
ListChannelUsers(channelID, domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError)
|
||||
|
||||
// ListDomainUsers returns list of users for the given domain ID and filters.
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// Permission : "view"
|
||||
// }
|
||||
// users, _ := sdk.ListDomainUsers("domainID", pm, "token")
|
||||
// fmt.Println(users)
|
||||
ListDomainUsers(domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError)
|
||||
|
||||
// CreateClient registers new client and returns its id.
|
||||
//
|
||||
// example:
|
||||
@@ -630,6 +583,17 @@ type SDK interface {
|
||||
// fmt.Println(actions)
|
||||
AvailableClientRoleActions(domainID, token string) ([]string, errors.SDKError)
|
||||
|
||||
// ListClientMembers list all members from all roles in a client .
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// }
|
||||
// members, _ := sdk.ListClientMembers("client_id","domainID", pm, "token")
|
||||
// fmt.Println(members)
|
||||
ListClientMembers(clientID, domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError)
|
||||
|
||||
// CreateGroup creates new group and returns its id.
|
||||
//
|
||||
// example:
|
||||
@@ -872,6 +836,17 @@ type SDK interface {
|
||||
// fmt.Println(actions)
|
||||
AvailableGroupRoleActions(id, token string) ([]string, errors.SDKError)
|
||||
|
||||
// ListGroupMembers list all members from all roles in a group .
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// }
|
||||
// members, _ := sdk.ListGroupMembers("group_id","domainID", pm, "token")
|
||||
// fmt.Println(members)
|
||||
ListGroupMembers(groupID, domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError)
|
||||
|
||||
// CreateChannel creates new channel and returns its id.
|
||||
//
|
||||
// example:
|
||||
@@ -1025,6 +1000,17 @@ type SDK interface {
|
||||
// fmt.Println(err)
|
||||
DisconnectClients(channelID string, clientIDs, connTypes []string, domainID, token string) errors.SDKError
|
||||
|
||||
// ListChannelMembers list all members from all roles in a channel .
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// }
|
||||
// members, _ := sdk.ListChannelMembers("channel_id","domainID", pm, "token")
|
||||
// fmt.Println(members)
|
||||
ListChannelMembers(channelID, domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError)
|
||||
|
||||
// SendMessage send message to specified channel.
|
||||
//
|
||||
// example:
|
||||
@@ -1258,6 +1244,17 @@ type SDK interface {
|
||||
// fmt.Println(actions)
|
||||
AvailableDomainRoleActions(token string) ([]string, errors.SDKError)
|
||||
|
||||
// ListDomainUsers returns list of users for the given domain ID and filters.
|
||||
//
|
||||
// example:
|
||||
// pm := sdk.PageMetadata{
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// }
|
||||
// members, _ := sdk.ListDomainMembers("domain_id", pm, "token")
|
||||
// fmt.Println(members)
|
||||
ListDomainMembers(domainID string, pm PageMetadata, token string) (EntityMembersPage, errors.SDKError)
|
||||
|
||||
// SendInvitation sends an invitation to the email address associated with the given user.
|
||||
//
|
||||
// For example:
|
||||
|
||||
@@ -33,7 +33,6 @@ const (
|
||||
contentType = "application/senml+json"
|
||||
invalid = "invalid"
|
||||
wrongID = "wrongID"
|
||||
defPermission = "read_permission"
|
||||
roleName = "roleName"
|
||||
)
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ import (
|
||||
|
||||
const (
|
||||
usersEndpoint = "users"
|
||||
assignEndpoint = "assign"
|
||||
unassignEndpoint = "unassign"
|
||||
enableEndpoint = "enable"
|
||||
disableEndpoint = "disable"
|
||||
issueTokenEndpoint = "tokens/issue"
|
||||
@@ -81,25 +79,6 @@ func (sdk mgSDK) Users(pm PageMetadata, token string) (UsersPage, errors.SDKErro
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
func (sdk mgSDK) Members(groupID, domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) {
|
||||
url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", domainID, groupsEndpoint, groupID, usersEndpoint), pm)
|
||||
if err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
_, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK)
|
||||
if sdkerr != nil {
|
||||
return UsersPage{}, sdkerr
|
||||
}
|
||||
|
||||
var up UsersPage
|
||||
if err := json.Unmarshal(body, &up); err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return up, nil
|
||||
}
|
||||
|
||||
func (sdk mgSDK) User(id, token string) (User, errors.SDKError) {
|
||||
if id == "" {
|
||||
return User{}, errors.NewSDKError(apiutil.ErrMissingID)
|
||||
@@ -372,55 +351,3 @@ func (sdk mgSDK) DeleteUser(id, token string) errors.SDKError {
|
||||
_, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent)
|
||||
return sdkerr
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListClientUsers(clientID, domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) {
|
||||
url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", domainID, clientsEndpoint, clientID, usersEndpoint), pm)
|
||||
if err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
_, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK)
|
||||
if sdkerr != nil {
|
||||
return UsersPage{}, sdkerr
|
||||
}
|
||||
up := UsersPage{}
|
||||
if err := json.Unmarshal(body, &up); err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return up, nil
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListDomainUsers(domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) {
|
||||
url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s", domainID, usersEndpoint), pm)
|
||||
if err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
_, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK)
|
||||
if sdkerr != nil {
|
||||
return UsersPage{}, sdkerr
|
||||
}
|
||||
var up UsersPage
|
||||
if err := json.Unmarshal(body, &up); err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return up, nil
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ListChannelUsers(channelID, domainID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) {
|
||||
url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", domainID, channelsEndpoint, channelID, usersEndpoint), pm)
|
||||
if err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
_, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK)
|
||||
if sdkerr != nil {
|
||||
return UsersPage{}, sdkerr
|
||||
}
|
||||
up := UsersPage{}
|
||||
if err := json.Unmarshal(body, &up); err != nil {
|
||||
return UsersPage{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return up, nil
|
||||
}
|
||||
|
||||
+2
-664
@@ -31,9 +31,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
id = generateUUID(&testing.T{})
|
||||
domainID = "c717fa97-ffd9-40cb-8cf9-7c2859059395"
|
||||
membershipPermission = "membership"
|
||||
id = generateUUID(&testing.T{})
|
||||
domainID = "c717fa97-ffd9-40cb-8cf9-7c2859059395"
|
||||
)
|
||||
|
||||
func setupUsers() (*httptest.Server, *umocks.Service, *authnmocks.Authentication) {
|
||||
@@ -2314,190 +2313,6 @@ func TestDisableUser(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListMembers(t *testing.T) {
|
||||
ts, svc, auth := setupUsers()
|
||||
defer ts.Close()
|
||||
|
||||
member := generateTestUser(t)
|
||||
conf := sdk.Config{
|
||||
UsersURL: ts.URL,
|
||||
}
|
||||
mgsdk := sdk.NewSDK(conf)
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session smqauthn.Session
|
||||
groupID string
|
||||
pageMeta sdk.PageMetadata
|
||||
svcReq users.Page
|
||||
svcRes users.MembersPage
|
||||
svcErr error
|
||||
authenticateErr error
|
||||
response sdk.UsersPage
|
||||
err errors.SDKError
|
||||
}{
|
||||
{
|
||||
desc: "list members successfully",
|
||||
token: validToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{convertUser(member)},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{
|
||||
PageRes: sdk.PageRes{
|
||||
Total: 1,
|
||||
},
|
||||
Users: []sdk.User{member},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "list members with invalid token",
|
||||
token: invalidToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list members with empty token",
|
||||
token: "",
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list members with invalid group id",
|
||||
token: validToken,
|
||||
groupID: wrongID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcErr: svcerr.ErrViewEntity,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrViewEntity, http.StatusBadRequest),
|
||||
},
|
||||
{
|
||||
desc: "list members with empty group id",
|
||||
token: validToken,
|
||||
groupID: "",
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest),
|
||||
},
|
||||
{
|
||||
desc: "list members with page metadata that can't be marshalled",
|
||||
token: validToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
Metadata: map[string]interface{}{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
svcReq: users.Page{},
|
||||
svcRes: users.MembersPage{},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKError(errors.New("json: unsupported type: chan int")),
|
||||
},
|
||||
{
|
||||
desc: "list members with response that can't be unmarshalled",
|
||||
token: validToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{{
|
||||
ID: member.ID,
|
||||
FirstName: member.FirstName,
|
||||
Metadata: map[string]interface{}{
|
||||
"key": make(chan int),
|
||||
},
|
||||
}},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKError(errors.New("unexpected end of JSON input")),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("ListMembers", mock.Anything, tc.session, "groups", tc.groupID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
||||
resp, err := mgsdk.Members(tc.groupID, domainID, tc.pageMeta, tc.token)
|
||||
assert.Equal(t, tc.err, err)
|
||||
assert.Equal(t, tc.response, resp)
|
||||
if tc.err == nil {
|
||||
ok := svcCall.Parent.AssertCalled(t, "ListMembers", mock.Anything, tc.session, "groups", tc.groupID, tc.svcReq)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
svcCall.Unset()
|
||||
authCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteUser(t *testing.T) {
|
||||
ts, svc, auth := setupUsers()
|
||||
defer ts.Close()
|
||||
@@ -2570,480 +2385,3 @@ func TestDeleteUser(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListClientUsers(t *testing.T) {
|
||||
ts, svc, auth := setupUsers()
|
||||
defer ts.Close()
|
||||
|
||||
clientUser := generateTestUser(t)
|
||||
conf := sdk.Config{
|
||||
UsersURL: ts.URL,
|
||||
}
|
||||
mgsdk := sdk.NewSDK(conf)
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session smqauthn.Session
|
||||
clientID string
|
||||
pageMeta sdk.PageMetadata
|
||||
svcReq users.Page
|
||||
svcRes users.MembersPage
|
||||
svcErr error
|
||||
authenticateErr error
|
||||
response sdk.UsersPage
|
||||
err errors.SDKError
|
||||
}{
|
||||
{
|
||||
desc: "list client users successfully",
|
||||
token: validToken,
|
||||
clientID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{convertUser(clientUser)},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{
|
||||
PageRes: sdk.PageRes{
|
||||
Total: 1,
|
||||
},
|
||||
Users: []sdk.User{clientUser},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "list client users with invalid token",
|
||||
token: invalidToken,
|
||||
clientID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list client users with empty token",
|
||||
token: "",
|
||||
clientID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list client users with invalid client id",
|
||||
token: validToken,
|
||||
clientID: wrongID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcErr: svcerr.ErrViewEntity,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrViewEntity, http.StatusBadRequest),
|
||||
},
|
||||
{
|
||||
desc: "list clients users with request that cannot be marshalled",
|
||||
token: validToken,
|
||||
clientID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
Metadata: map[string]interface{}{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
err: errors.NewSDKError(errors.New("json: unsupported type: chan int")),
|
||||
},
|
||||
{
|
||||
desc: "list clients users with response that cannot be unmarshalled",
|
||||
token: validToken,
|
||||
clientID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{{
|
||||
ID: clientUser.ID,
|
||||
FirstName: clientUser.FirstName,
|
||||
Metadata: map[string]interface{}{
|
||||
"key": make(chan int),
|
||||
},
|
||||
}},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKError(errors.New("unexpected end of JSON input")),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("ListMembers", mock.Anything, tc.session, "clients", tc.clientID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
||||
resp, err := mgsdk.ListClientUsers(tc.clientID, domainID, tc.pageMeta, tc.token)
|
||||
assert.Equal(t, tc.err, err)
|
||||
assert.Equal(t, tc.response, resp)
|
||||
if tc.err == nil {
|
||||
ok := svcCall.Parent.AssertCalled(t, "ListMembers", mock.Anything, tc.session, "clients", tc.clientID, tc.svcReq)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
svcCall.Unset()
|
||||
authCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListGroupUsers(t *testing.T) {
|
||||
ts, svc, auth := setupUsers()
|
||||
defer ts.Close()
|
||||
|
||||
groupUser := generateTestUser(t)
|
||||
conf := sdk.Config{
|
||||
UsersURL: ts.URL,
|
||||
}
|
||||
mgsdk := sdk.NewSDK(conf)
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session smqauthn.Session
|
||||
groupID string
|
||||
pageMeta sdk.PageMetadata
|
||||
svcReq users.Page
|
||||
svcRes users.MembersPage
|
||||
svcErr error
|
||||
authenticateErr error
|
||||
response sdk.UsersPage
|
||||
err errors.SDKError
|
||||
}{
|
||||
{
|
||||
desc: "list client users successfully",
|
||||
token: validToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{convertUser(groupUser)},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{
|
||||
PageRes: sdk.PageRes{
|
||||
Total: 1,
|
||||
},
|
||||
Users: []sdk.User{groupUser},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "list client users with invalid token",
|
||||
token: invalidToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list client users with empty token",
|
||||
token: "",
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list client users with invalid client id",
|
||||
token: validToken,
|
||||
groupID: wrongID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcErr: svcerr.ErrViewEntity,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrViewEntity, http.StatusBadRequest),
|
||||
},
|
||||
{
|
||||
desc: "list clients users with request that cannot be marshalled",
|
||||
token: validToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
Metadata: map[string]interface{}{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
err: errors.NewSDKError(errors.New("json: unsupported type: chan int")),
|
||||
},
|
||||
{
|
||||
desc: "list clients users with response that cannot be unmarshalled",
|
||||
token: validToken,
|
||||
groupID: validID,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: defPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{{
|
||||
ID: groupUser.ID,
|
||||
FirstName: groupUser.FirstName,
|
||||
Metadata: map[string]interface{}{
|
||||
"key": make(chan int),
|
||||
},
|
||||
}},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKError(errors.New("unexpected end of JSON input")),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("ListMembers", mock.Anything, tc.session, "groups", tc.groupID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
||||
resp, err := mgsdk.ListChannelUsers(tc.groupID, domainID, tc.pageMeta, tc.token)
|
||||
assert.Equal(t, tc.err, err)
|
||||
assert.Equal(t, tc.response, resp)
|
||||
if tc.err == nil {
|
||||
ok := svcCall.Parent.AssertCalled(t, "ListMembers", mock.Anything, tc.session, "groups", tc.groupID, tc.svcReq)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
svcCall.Unset()
|
||||
authCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListDomainUser(t *testing.T) {
|
||||
ts, svc, auth := setupUsers()
|
||||
defer ts.Close()
|
||||
|
||||
user := generateTestUser(t)
|
||||
conf := sdk.Config{
|
||||
UsersURL: ts.URL,
|
||||
}
|
||||
mgsdk := sdk.NewSDK(conf)
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session smqauthn.Session
|
||||
pageMeta sdk.PageMetadata
|
||||
svcReq users.Page
|
||||
svcRes users.MembersPage
|
||||
svcErr error
|
||||
authenticateErr error
|
||||
response sdk.UsersPage
|
||||
err errors.SDKError
|
||||
}{
|
||||
{
|
||||
desc: "list domain users successfully",
|
||||
token: validToken,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: membershipPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{convertUser(user)},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{
|
||||
PageRes: sdk.PageRes{
|
||||
Total: 1,
|
||||
},
|
||||
Users: []sdk.User{user},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "list domain users with invalid token",
|
||||
token: invalidToken,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: membershipPermission,
|
||||
},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list domain users with empty token",
|
||||
token: "",
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
||||
},
|
||||
{
|
||||
desc: "list domain users with request that cannot be marshalled",
|
||||
token: validToken,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
Metadata: map[string]interface{}{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
err: errors.NewSDKError(errors.New("json: unsupported type: chan int")),
|
||||
},
|
||||
{
|
||||
desc: "list domain users with response that cannot be unmarshalled",
|
||||
token: validToken,
|
||||
pageMeta: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
DomainID: domainID,
|
||||
},
|
||||
svcReq: users.Page{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Permission: membershipPermission,
|
||||
},
|
||||
svcRes: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []users.User{{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
Metadata: map[string]interface{}{
|
||||
"key": make(chan int),
|
||||
},
|
||||
}},
|
||||
},
|
||||
svcErr: nil,
|
||||
response: sdk.UsersPage{},
|
||||
err: errors.NewSDKError(errors.New("unexpected end of JSON input")),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("ListMembers", mock.Anything, tc.session, "domains", domainID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
||||
resp, err := mgsdk.ListDomainUsers(domainID, tc.pageMeta, tc.token)
|
||||
assert.Equal(t, tc.err, err)
|
||||
assert.Equal(t, tc.response, resp)
|
||||
if tc.err == nil {
|
||||
ok := svcCall.Parent.AssertCalled(t, "ListMembers", mock.Anything, tc.session, "domains", domainID, tc.svcReq)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
svcCall.Unset()
|
||||
authCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -164,95 +164,6 @@ func searchUsersEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
func listMembersByGroupEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(listMembersByObjectReq)
|
||||
req.objectKind = "groups"
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
session, ok := ctx.Value(api.SessionKey).(authn.Session)
|
||||
if !ok {
|
||||
return nil, svcerr.ErrAuthentication
|
||||
}
|
||||
|
||||
page, err := svc.ListMembers(ctx, session, req.objectKind, req.objectID, req.Page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buildUsersResponse(page), nil
|
||||
}
|
||||
}
|
||||
|
||||
func listMembersByChannelEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(listMembersByObjectReq)
|
||||
// In spiceDB schema, using the same 'group' type for both channels and groups, rather than having a separate type for channels.
|
||||
req.objectKind = "groups"
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
session, ok := ctx.Value(api.SessionKey).(authn.Session)
|
||||
if !ok {
|
||||
return nil, svcerr.ErrAuthentication
|
||||
}
|
||||
|
||||
page, err := svc.ListMembers(ctx, session, req.objectKind, req.objectID, req.Page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buildUsersResponse(page), nil
|
||||
}
|
||||
}
|
||||
|
||||
func listMembersByClientEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(listMembersByObjectReq)
|
||||
req.objectKind = "clients"
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
session, ok := ctx.Value(api.SessionKey).(authn.Session)
|
||||
if !ok {
|
||||
return nil, svcerr.ErrAuthentication
|
||||
}
|
||||
|
||||
page, err := svc.ListMembers(ctx, session, req.objectKind, req.objectID, req.Page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buildUsersResponse(page), nil
|
||||
}
|
||||
}
|
||||
|
||||
func listMembersByDomainEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(listMembersByObjectReq)
|
||||
req.objectKind = "domains"
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
session, ok := ctx.Value(api.SessionKey).(authn.Session)
|
||||
if !ok {
|
||||
return nil, svcerr.ErrAuthentication
|
||||
}
|
||||
|
||||
page, err := svc.ListMembers(ctx, session, req.objectKind, req.objectID, req.Page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buildUsersResponse(page), nil
|
||||
}
|
||||
}
|
||||
|
||||
func updateEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(updateUserReq)
|
||||
@@ -574,20 +485,3 @@ func deleteEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return deleteUserRes{true}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func buildUsersResponse(cp users.MembersPage) usersPageRes {
|
||||
res := usersPageRes{
|
||||
pageRes: pageRes{
|
||||
Total: cp.Total,
|
||||
Offset: cp.Offset,
|
||||
Limit: cp.Limit,
|
||||
},
|
||||
Users: []viewUserRes{},
|
||||
}
|
||||
|
||||
for _, user := range cp.Members {
|
||||
res.Users = append(res.Users, viewUserRes{User: user})
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -121,23 +121,6 @@ func (req searchUsersReq) validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type listMembersByObjectReq struct {
|
||||
users.Page
|
||||
objectKind string
|
||||
objectID string
|
||||
}
|
||||
|
||||
func (req listMembersByObjectReq) validate() error {
|
||||
if req.objectID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
if req.objectKind == "" {
|
||||
return apiutil.ErrMissingMemberKind
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type updateUserReq struct {
|
||||
id string
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
@@ -327,87 +310,3 @@ func (req resetTokenReq) validate() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type assignUsersReq struct {
|
||||
groupID string
|
||||
Relation string `json:"relation"`
|
||||
UserIDs []string `json:"user_ids"`
|
||||
}
|
||||
|
||||
func (req assignUsersReq) validate() error {
|
||||
if req.Relation == "" {
|
||||
return apiutil.ErrMissingRelation
|
||||
}
|
||||
|
||||
if req.groupID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.UserIDs) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type unassignUsersReq struct {
|
||||
groupID string
|
||||
Relation string `json:"relation"`
|
||||
UserIDs []string `json:"user_ids"`
|
||||
}
|
||||
|
||||
func (req unassignUsersReq) validate() error {
|
||||
if req.groupID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.UserIDs) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type assignGroupsReq struct {
|
||||
groupID string
|
||||
domainID string
|
||||
GroupIDs []string `json:"group_ids"`
|
||||
}
|
||||
|
||||
func (req assignGroupsReq) validate() error {
|
||||
if req.domainID == "" {
|
||||
return apiutil.ErrMissingDomainID
|
||||
}
|
||||
|
||||
if req.groupID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.GroupIDs) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type unassignGroupsReq struct {
|
||||
groupID string
|
||||
domainID string
|
||||
GroupIDs []string `json:"group_ids"`
|
||||
}
|
||||
|
||||
func (req unassignGroupsReq) validate() error {
|
||||
if req.domainID == "" {
|
||||
return apiutil.ErrMissingDomainID
|
||||
}
|
||||
|
||||
if req.groupID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.GroupIDs) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+1
-237
@@ -22,10 +22,7 @@ const (
|
||||
name = "user"
|
||||
)
|
||||
|
||||
var (
|
||||
validID = testsutil.GenerateUUID(&testing.T{})
|
||||
domain = testsutil.GenerateUUID(&testing.T{})
|
||||
)
|
||||
var validID = testsutil.GenerateUUID(&testing.T{})
|
||||
|
||||
func TestCreateUserReqValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
@@ -207,43 +204,6 @@ func TestSearchUsersReqValidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListMembersByObjectReqValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
req listMembersByObjectReq
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "valid request",
|
||||
req: listMembersByObjectReq{
|
||||
objectKind: "group",
|
||||
objectID: validID,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "empty object kind",
|
||||
req: listMembersByObjectReq{
|
||||
objectKind: "",
|
||||
objectID: validID,
|
||||
},
|
||||
err: apiutil.ErrMissingMemberKind,
|
||||
},
|
||||
{
|
||||
desc: "empty object id",
|
||||
req: listMembersByObjectReq{
|
||||
objectKind: "group",
|
||||
objectID: "",
|
||||
},
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
err := c.req.validate()
|
||||
assert.Equal(t, c.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUserReqValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -660,199 +620,3 @@ func TestResetTokenReqValidate(t *testing.T) {
|
||||
assert.Equal(t, c.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssignUsersRequestValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
req assignUsersReq
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "valid request",
|
||||
req: assignUsersReq{
|
||||
groupID: validID,
|
||||
UserIDs: []string{validID},
|
||||
Relation: valid,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "empty id",
|
||||
req: assignUsersReq{
|
||||
groupID: "",
|
||||
UserIDs: []string{validID},
|
||||
Relation: valid,
|
||||
},
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
{
|
||||
desc: "empty users",
|
||||
req: assignUsersReq{
|
||||
groupID: validID,
|
||||
UserIDs: []string{},
|
||||
Relation: valid,
|
||||
},
|
||||
err: apiutil.ErrEmptyList,
|
||||
},
|
||||
{
|
||||
desc: "empty relation",
|
||||
req: assignUsersReq{
|
||||
groupID: validID,
|
||||
UserIDs: []string{validID},
|
||||
Relation: "",
|
||||
},
|
||||
err: apiutil.ErrMissingRelation,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
err := c.req.validate()
|
||||
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnassignUsersRequestValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
req unassignUsersReq
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "valid request",
|
||||
req: unassignUsersReq{
|
||||
groupID: validID,
|
||||
UserIDs: []string{validID},
|
||||
Relation: valid,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "empty id",
|
||||
req: unassignUsersReq{
|
||||
groupID: "",
|
||||
UserIDs: []string{validID},
|
||||
Relation: valid,
|
||||
},
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
{
|
||||
desc: "empty users",
|
||||
req: unassignUsersReq{
|
||||
groupID: validID,
|
||||
UserIDs: []string{},
|
||||
Relation: valid,
|
||||
},
|
||||
err: apiutil.ErrEmptyList,
|
||||
},
|
||||
{
|
||||
desc: "empty relation",
|
||||
req: unassignUsersReq{
|
||||
groupID: validID,
|
||||
UserIDs: []string{validID},
|
||||
Relation: "",
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
err := c.req.validate()
|
||||
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssignGroupsRequestValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
req assignGroupsReq
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "valid request",
|
||||
req: assignGroupsReq{
|
||||
domainID: domain,
|
||||
groupID: validID,
|
||||
GroupIDs: []string{validID},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "empty group id",
|
||||
req: assignGroupsReq{
|
||||
domainID: domain,
|
||||
groupID: "",
|
||||
GroupIDs: []string{validID},
|
||||
},
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
{
|
||||
desc: "empty user group ids",
|
||||
req: assignGroupsReq{
|
||||
domainID: domain,
|
||||
groupID: validID,
|
||||
GroupIDs: []string{},
|
||||
},
|
||||
err: apiutil.ErrEmptyList,
|
||||
},
|
||||
{
|
||||
desc: "empty domain id",
|
||||
req: assignGroupsReq{
|
||||
domainID: "",
|
||||
groupID: validID,
|
||||
GroupIDs: []string{validID},
|
||||
},
|
||||
err: apiutil.ErrMissingDomainID,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
err := c.req.validate()
|
||||
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnassignGroupsRequestValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
req unassignGroupsReq
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "valid request",
|
||||
req: unassignGroupsReq{
|
||||
domainID: domain,
|
||||
groupID: validID,
|
||||
GroupIDs: []string{validID},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "empty group id",
|
||||
req: unassignGroupsReq{
|
||||
domainID: domain,
|
||||
groupID: "",
|
||||
GroupIDs: []string{validID},
|
||||
},
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
{
|
||||
desc: "empty user group ids",
|
||||
req: unassignGroupsReq{
|
||||
domainID: domain,
|
||||
groupID: validID,
|
||||
GroupIDs: []string{},
|
||||
},
|
||||
err: apiutil.ErrEmptyList,
|
||||
},
|
||||
{
|
||||
desc: "empty domain id",
|
||||
req: unassignGroupsReq{
|
||||
domainID: "",
|
||||
groupID: validID,
|
||||
GroupIDs: []string{valid},
|
||||
},
|
||||
err: apiutil.ErrMissingDomainID,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
err := c.req.validate()
|
||||
assert.Equal(t, c.err, err, "%s: expected %s got %s\n", c.desc, c.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ var (
|
||||
_ supermq.Response = (*viewMembersRes)(nil)
|
||||
_ supermq.Response = (*passwResetReqRes)(nil)
|
||||
_ supermq.Response = (*passwChangeRes)(nil)
|
||||
_ supermq.Response = (*assignUsersRes)(nil)
|
||||
_ supermq.Response = (*unassignUsersRes)(nil)
|
||||
_ supermq.Response = (*updateUserRes)(nil)
|
||||
_ supermq.Response = (*tokenRes)(nil)
|
||||
_ supermq.Response = (*deleteUserRes)(nil)
|
||||
@@ -192,34 +190,6 @@ func (res passwChangeRes) Empty() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type assignUsersRes struct{}
|
||||
|
||||
func (res assignUsersRes) Code() int {
|
||||
return http.StatusCreated
|
||||
}
|
||||
|
||||
func (res assignUsersRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res assignUsersRes) Empty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type unassignUsersRes struct{}
|
||||
|
||||
func (res unassignUsersRes) Code() int {
|
||||
return http.StatusNoContent
|
||||
}
|
||||
|
||||
func (res unassignUsersRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res unassignUsersRes) Empty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type deleteUserRes struct {
|
||||
deleted bool
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/absmach/supermq/pkg/oauth2"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/users"
|
||||
"github.com/go-chi/chi/v5"
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
@@ -173,48 +172,6 @@ func usersHandler(svc users.Service, authn smqauthn.Authentication, tokenClient
|
||||
), "password_reset").ServeHTTP)
|
||||
})
|
||||
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(api.AuthenticateMiddleware(authn, true))
|
||||
|
||||
// Ideal location: users service, groups endpoint.
|
||||
// Reason for placing here :
|
||||
// SpiceDB provides list of user ids in given user_group_id
|
||||
// and users service can access spiceDB and get the user list with user_group_id.
|
||||
// Request to get list of users present in the user_group_id {groupID}
|
||||
r.Get("/{domainID}/groups/{groupID}/users", otelhttp.NewHandler(kithttp.NewServer(
|
||||
listMembersByGroupEndpoint(svc),
|
||||
decodeListMembersByGroup,
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "list_users_by_user_group_id").ServeHTTP)
|
||||
|
||||
// Ideal location: clients service, channels endpoint.
|
||||
// Reason for placing here :
|
||||
// SpiceDB provides list of user ids in given channel_id
|
||||
// and users service can access spiceDB and get the user list with channel_id.
|
||||
// Request to get list of users present in the user_group_id {channelID}
|
||||
r.Get("/{domainID}/channels/{channelID}/users", otelhttp.NewHandler(kithttp.NewServer(
|
||||
listMembersByChannelEndpoint(svc),
|
||||
decodeListMembersByChannel,
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "list_users_by_channel_id").ServeHTTP)
|
||||
|
||||
r.Get("/{domainID}/clients/{clientID}/users", otelhttp.NewHandler(kithttp.NewServer(
|
||||
listMembersByClientEndpoint(svc),
|
||||
decodeListMembersByClient,
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "list_users_by_client_id").ServeHTTP)
|
||||
|
||||
r.Get("/{domainID}/users", otelhttp.NewHandler(kithttp.NewServer(
|
||||
listMembersByDomainEndpoint(svc),
|
||||
decodeListMembersByDomain,
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "list_users_by_domain_id").ServeHTTP)
|
||||
})
|
||||
|
||||
r.Post("/users/tokens/issue", otelhttp.NewHandler(kithttp.NewServer(
|
||||
issueTokenEndpoint(svc),
|
||||
decodeCredentials,
|
||||
@@ -550,123 +507,6 @@ func decodeChangeUserStatus(_ context.Context, r *http.Request) (interface{}, er
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListMembersByGroup(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
page, err := queryPageParams(r, api.DefPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listMembersByObjectReq{
|
||||
Page: page,
|
||||
objectID: chi.URLParam(r, "groupID"),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListMembersByChannel(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
page, err := queryPageParams(r, api.DefPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listMembersByObjectReq{
|
||||
Page: page,
|
||||
objectID: chi.URLParam(r, "channelID"),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListMembersByClient(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
page, err := queryPageParams(r, api.DefPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listMembersByObjectReq{
|
||||
Page: page,
|
||||
objectID: chi.URLParam(r, "clientID"),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListMembersByDomain(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
page, err := queryPageParams(r, policies.MembershipPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listMembersByObjectReq{
|
||||
Page: page,
|
||||
objectID: chi.URLParam(r, "domainID"),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func queryPageParams(r *http.Request, defPermission string) (users.Page, error) {
|
||||
s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefClientStatus)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
o, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
l, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
m, err := apiutil.ReadMetadataQuery(r, api.MetadataKey, nil)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
n, err := apiutil.ReadStringQuery(r, api.UsernameKey, "")
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
f, err := apiutil.ReadStringQuery(r, api.FirstNameKey, "")
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
a, err := apiutil.ReadStringQuery(r, api.LastNameKey, "")
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
i, err := apiutil.ReadStringQuery(r, api.EmailKey, "")
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
t, err := apiutil.ReadStringQuery(r, api.TagKey, "")
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
st, err := users.ToStatus(s)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
p, err := apiutil.ReadStringQuery(r, api.PermissionKey, defPermission)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
lp, err := apiutil.ReadBoolQuery(r, api.ListPerms, api.DefListPerms)
|
||||
if err != nil {
|
||||
return users.Page{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
return users.Page{
|
||||
Status: st,
|
||||
Offset: o,
|
||||
Limit: l,
|
||||
Metadata: m,
|
||||
FirstName: f,
|
||||
Username: n,
|
||||
LastName: a,
|
||||
Email: i,
|
||||
Tag: t,
|
||||
Permission: p,
|
||||
ListPerms: lp,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// oauth2CallbackHandler is a http.HandlerFunc that handles OAuth2 callbacks.
|
||||
func oauth2CallbackHandler(oauth oauth2.Provider, svc users.Service, tokenClient grpcTokenV1.TokenServiceClient) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -43,7 +43,6 @@ var (
|
||||
_ events.Event = (*viewUserEvent)(nil)
|
||||
_ events.Event = (*viewProfileEvent)(nil)
|
||||
_ events.Event = (*listUserEvent)(nil)
|
||||
_ events.Event = (*listUserByGroupEvent)(nil)
|
||||
_ events.Event = (*searchUserEvent)(nil)
|
||||
_ events.Event = (*identifyUserEvent)(nil)
|
||||
_ events.Event = (*generateResetTokenEvent)(nil)
|
||||
@@ -359,63 +358,6 @@ func (lue listUserEvent) Encode() (map[string]interface{}, error) {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
type listUserByGroupEvent struct {
|
||||
users.Page
|
||||
objectKind string
|
||||
objectID string
|
||||
authn.Session
|
||||
}
|
||||
|
||||
func (lcge listUserByGroupEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"operation": userListByGroup,
|
||||
"total": lcge.Total,
|
||||
"offset": lcge.Offset,
|
||||
"limit": lcge.Limit,
|
||||
"object_kind": lcge.objectKind,
|
||||
"object_id": lcge.objectID,
|
||||
"domain": lcge.DomainID,
|
||||
"token_type": lcge.Type.String(),
|
||||
"super_admin": lcge.SuperAdmin,
|
||||
}
|
||||
|
||||
if lcge.Username != "" {
|
||||
val["username"] = lcge.Username
|
||||
}
|
||||
if lcge.Order != "" {
|
||||
val["order"] = lcge.Order
|
||||
}
|
||||
if lcge.Dir != "" {
|
||||
val["dir"] = lcge.Dir
|
||||
}
|
||||
if lcge.Metadata != nil {
|
||||
val["metadata"] = lcge.Metadata
|
||||
}
|
||||
if lcge.Domain != "" {
|
||||
val["domain"] = lcge.Domain
|
||||
}
|
||||
if lcge.Tag != "" {
|
||||
val["tag"] = lcge.Tag
|
||||
}
|
||||
if lcge.Permission != "" {
|
||||
val["permission"] = lcge.Permission
|
||||
}
|
||||
if lcge.Status.String() != "" {
|
||||
val["status"] = lcge.Status.String()
|
||||
}
|
||||
if lcge.FirstName != "" {
|
||||
val["first_name"] = lcge.FirstName
|
||||
}
|
||||
if lcge.LastName != "" {
|
||||
val["last_name"] = lcge.LastName
|
||||
}
|
||||
if lcge.Email != "" {
|
||||
val["email"] = lcge.Email
|
||||
}
|
||||
|
||||
return val, nil
|
||||
}
|
||||
|
||||
type searchUserEvent struct {
|
||||
users.Page
|
||||
}
|
||||
|
||||
@@ -216,25 +216,6 @@ func (es *eventStore) SearchUsers(ctx context.Context, pm users.Page) (users.Use
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, pm users.Page) (users.MembersPage, error) {
|
||||
mp, err := es.svc.ListMembers(ctx, session, objectKind, objectID, pm)
|
||||
if err != nil {
|
||||
return mp, err
|
||||
}
|
||||
event := listUserByGroupEvent{
|
||||
Page: pm,
|
||||
objectKind: objectKind,
|
||||
objectID: objectID,
|
||||
Session: session,
|
||||
}
|
||||
|
||||
if err := es.Publish(ctx, event); err != nil {
|
||||
return mp, err
|
||||
}
|
||||
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) Enable(ctx context.Context, session authn.Session, id string) (users.User, error) {
|
||||
user, err := es.svc.Enable(ctx, session, id)
|
||||
if err != nil {
|
||||
|
||||
@@ -100,73 +100,6 @@ func (am *authorizationMiddleware) ListUsers(ctx context.Context, session authn.
|
||||
return am.svc.ListUsers(ctx, session, pm)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, pm users.Page) (users.MembersPage, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
switch objectKind {
|
||||
case policies.GroupsKind:
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.PatID,
|
||||
OptionalDomainID: session.DomainID,
|
||||
PlatformEntityType: smqauth.PlatformUsersScope,
|
||||
OptionalDomainEntityType: smqauth.DomainGroupsScope,
|
||||
Operation: smqauth.ListOp,
|
||||
EntityIDs: smqauth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return users.MembersPage{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
case policies.DomainsKind:
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.PatID,
|
||||
OptionalDomainID: session.DomainID,
|
||||
PlatformEntityType: smqauth.PlatformUsersScope,
|
||||
OptionalDomainEntityType: smqauth.DomainManagementScope,
|
||||
Operation: smqauth.ListOp,
|
||||
EntityIDs: smqauth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return users.MembersPage{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
case policies.ClientsKind:
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.PatID,
|
||||
OptionalDomainID: session.DomainID,
|
||||
PlatformEntityType: smqauth.PlatformUsersScope,
|
||||
OptionalDomainEntityType: smqauth.DomainClientsScope,
|
||||
Operation: smqauth.ListOp,
|
||||
EntityIDs: smqauth.AnyIDs{}.Values(),
|
||||
}); err != nil {
|
||||
return users.MembersPage{}, errors.Wrap(svcerr.ErrUnauthorizedPAT, err)
|
||||
}
|
||||
default:
|
||||
return users.MembersPage{}, svcerr.ErrAuthorization
|
||||
}
|
||||
}
|
||||
|
||||
if session.DomainUserID == "" {
|
||||
return users.MembersPage{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
switch objectKind {
|
||||
case policies.GroupsKind:
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, smqauth.SwitchToPermission(pm.Permission), policies.GroupType, objectID); err != nil {
|
||||
return users.MembersPage{}, err
|
||||
}
|
||||
case policies.DomainsKind:
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, smqauth.SwitchToPermission(pm.Permission), policies.DomainType, objectID); err != nil {
|
||||
return users.MembersPage{}, err
|
||||
}
|
||||
case policies.ClientsKind:
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.UserID, smqauth.SwitchToPermission(pm.Permission), policies.ClientType, objectID); err != nil {
|
||||
return users.MembersPage{}, err
|
||||
}
|
||||
default:
|
||||
return users.MembersPage{}, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
return am.svc.ListMembers(ctx, session, objectKind, objectID, pm)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) SearchUsers(ctx context.Context, pm users.Page) (users.UsersPage, error) {
|
||||
return am.svc.SearchUsers(ctx, pm)
|
||||
}
|
||||
|
||||
@@ -414,32 +414,6 @@ func (lm *loggingMiddleware) Disable(ctx context.Context, session authn.Session,
|
||||
return lm.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
// ListMembers logs the list_members request. It logs the group id, and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, cp users.Page) (mp users.MembersPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.Group("object",
|
||||
slog.String("kind", objectKind),
|
||||
slog.String("id", objectID),
|
||||
),
|
||||
slog.Group("page",
|
||||
slog.Uint64("limit", cp.Limit),
|
||||
slog.Uint64("offset", cp.Offset),
|
||||
slog.Uint64("total", mp.Total),
|
||||
),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("List members failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("List members completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.ListMembers(ctx, session, objectKind, objectID, cp)
|
||||
}
|
||||
|
||||
// Identify logs the identify request. It logs the time it took to complete the request.
|
||||
func (lm *loggingMiddleware) Identify(ctx context.Context, session authn.Session) (id string, err error) {
|
||||
defer func(begin time.Time) {
|
||||
|
||||
@@ -201,15 +201,6 @@ func (ms *metricsMiddleware) Disable(ctx context.Context, session authn.Session,
|
||||
return ms.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
// ListMembers instruments ListMembers method with metrics.
|
||||
func (ms *metricsMiddleware) ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, pm users.Page) (mp users.MembersPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "list_members").Add(1)
|
||||
ms.latency.With("method", "list_members").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.ListMembers(ctx, session, objectKind, objectID, pm)
|
||||
}
|
||||
|
||||
// Identify instruments Identify method with metrics.
|
||||
func (ms *metricsMiddleware) Identify(ctx context.Context, session authn.Session) (string, error) {
|
||||
defer func(begin time.Time) {
|
||||
|
||||
@@ -171,34 +171,6 @@ func (_m *Service) IssueToken(ctx context.Context, identity string, secret strin
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListMembers provides a mock function with given fields: ctx, session, objectKind, objectID, pm
|
||||
func (_m *Service) ListMembers(ctx context.Context, session authn.Session, objectKind string, objectID string, pm users.Page) (users.MembersPage, error) {
|
||||
ret := _m.Called(ctx, session, objectKind, objectID, pm)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListMembers")
|
||||
}
|
||||
|
||||
var r0 users.MembersPage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string, users.Page) (users.MembersPage, error)); ok {
|
||||
return rf(ctx, session, objectKind, objectID, pm)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string, users.Page) users.MembersPage); ok {
|
||||
r0 = rf(ctx, session, objectKind, objectID, pm)
|
||||
} else {
|
||||
r0 = ret.Get(0).(users.MembersPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, string, users.Page) error); ok {
|
||||
r1 = rf(ctx, session, objectKind, objectID, pm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListUsers provides a mock function with given fields: ctx, session, pm
|
||||
func (_m *Service) ListUsers(ctx context.Context, session authn.Session, pm users.Page) (users.UsersPage, error) {
|
||||
ret := _m.Called(ctx, session, pm)
|
||||
|
||||
+3
-105
@@ -17,14 +17,12 @@ import (
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var (
|
||||
errIssueToken = errors.New("failed to issue token")
|
||||
errFailedPermissionsList = errors.New("failed to list permissions")
|
||||
errRecoveryToken = errors.New("failed to generate password recovery token")
|
||||
errLoginDisableUser = errors.New("failed to login in disabled user")
|
||||
errIssueToken = errors.New("failed to issue token")
|
||||
errRecoveryToken = errors.New("failed to generate password recovery token")
|
||||
errLoginDisableUser = errors.New("failed to login in disabled user")
|
||||
)
|
||||
|
||||
type service struct {
|
||||
@@ -469,106 +467,6 @@ func (svc service) Delete(ctx context.Context, session authn.Session, id string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, pm Page) (MembersPage, error) {
|
||||
var objectType string
|
||||
switch objectKind {
|
||||
case policies.ClientsKind:
|
||||
objectType = policies.ClientType
|
||||
case policies.DomainsKind:
|
||||
objectType = policies.DomainType
|
||||
case policies.GroupsKind:
|
||||
fallthrough
|
||||
default:
|
||||
objectType = policies.GroupType
|
||||
}
|
||||
|
||||
duids, err := svc.policies.ListAllSubjects(ctx, policies.Policy{
|
||||
SubjectType: policies.UserType,
|
||||
Permission: pm.Permission,
|
||||
Object: objectID,
|
||||
ObjectType: objectType,
|
||||
})
|
||||
if err != nil {
|
||||
return MembersPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
if len(duids.Policies) == 0 {
|
||||
return MembersPage{
|
||||
Page: Page{Total: 0, Offset: pm.Offset, Limit: pm.Limit},
|
||||
}, nil
|
||||
}
|
||||
|
||||
var userIDs []string
|
||||
|
||||
for _, domainUserID := range duids.Policies {
|
||||
_, userID := smqauth.DecodeDomainUserID(domainUserID)
|
||||
userIDs = append(userIDs, userID)
|
||||
}
|
||||
pm.IDs = userIDs
|
||||
|
||||
up, err := svc.users.RetrieveAll(ctx, pm)
|
||||
if err != nil {
|
||||
return MembersPage{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
for i, u := range up.Users {
|
||||
up.Users[i] = User{
|
||||
ID: u.ID,
|
||||
FirstName: u.FirstName,
|
||||
LastName: u.LastName,
|
||||
Credentials: Credentials{
|
||||
Username: u.Credentials.Username,
|
||||
},
|
||||
CreatedAt: u.CreatedAt,
|
||||
UpdatedAt: u.UpdatedAt,
|
||||
Status: u.Status,
|
||||
}
|
||||
}
|
||||
|
||||
if pm.ListPerms && len(up.Users) > 0 {
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
for i := range up.Users {
|
||||
// Copying loop variable "i" to avoid "loop variable captured by func literal"
|
||||
iter := i
|
||||
g.Go(func() error {
|
||||
return svc.retrieveObjectUsersPermissions(ctx, session.DomainID, objectType, objectID, &up.Users[iter])
|
||||
})
|
||||
}
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
return MembersPage{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return MembersPage{
|
||||
Page: up.Page,
|
||||
Members: up.Users,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (svc service) retrieveObjectUsersPermissions(ctx context.Context, domainID, objectType, objectID string, user *User) error {
|
||||
userID := smqauth.EncodeDomainUserID(domainID, user.ID)
|
||||
permissions, err := svc.listObjectUserPermission(ctx, userID, objectType, objectID)
|
||||
if err != nil {
|
||||
return errors.Wrap(svcerr.ErrAuthorization, err)
|
||||
}
|
||||
user.Permissions = permissions
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) listObjectUserPermission(ctx context.Context, userID, objectType, objectID string) ([]string, error) {
|
||||
permissions, err := svc.policies.ListPermissions(ctx, policies.Policy{
|
||||
SubjectType: policies.UserType,
|
||||
Subject: userID,
|
||||
Object: objectID,
|
||||
ObjectType: objectType,
|
||||
}, []string{})
|
||||
if err != nil {
|
||||
return []string{}, errors.Wrap(errFailedPermissionsList, err)
|
||||
}
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func (svc *service) checkSuperAdmin(ctx context.Context, session authn.Session) error {
|
||||
if !session.SuperAdmin {
|
||||
if err := svc.users.CheckSuperAdmin(ctx, session.UserID); err != nil {
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
policysvc "github.com/absmach/supermq/pkg/policies"
|
||||
policymocks "github.com/absmach/supermq/pkg/policies/mocks"
|
||||
"github.com/absmach/supermq/pkg/uuid"
|
||||
"github.com/absmach/supermq/users"
|
||||
@@ -1330,297 +1329,6 @@ func TestDeleteUser(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListMembers(t *testing.T) {
|
||||
svc, _, cRepo, policies, _ := newService()
|
||||
|
||||
validPolicy := fmt.Sprintf("%s_%s", validID, user.ID)
|
||||
permissionsUser := basicUser
|
||||
permissionsUser.Permissions = []string{"read"}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
groupID string
|
||||
objectKind string
|
||||
objectID string
|
||||
page users.Page
|
||||
listAllSubjectsReq policysvc.Policy
|
||||
listAllSubjectsResponse policysvc.PolicyPage
|
||||
retrieveAllResponse users.UsersPage
|
||||
listPermissionsResponse policysvc.Permissions
|
||||
response users.MembersPage
|
||||
listAllSubjectsErr error
|
||||
retrieveAllErr error
|
||||
identifyErr error
|
||||
listPermissionErr error
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "list members with no policies successfully of the clients kind",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.ClientsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.ClientType,
|
||||
},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 0,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "list members with policies successsfully of the clients kind",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.ClientsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.ClientType,
|
||||
},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{Policies: []string{validPolicy}},
|
||||
retrieveAllResponse: users.UsersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Users: []users.User{user},
|
||||
},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Members: []users.User{basicUser},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "list members with policies successsfully of the clients kind with permissions",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.ClientsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read", ListPerms: true},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.ClientType,
|
||||
},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{Policies: []string{validPolicy}},
|
||||
retrieveAllResponse: users.UsersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Users: []users.User{basicUser},
|
||||
},
|
||||
listPermissionsResponse: []string{"read"},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Members: []users.User{permissionsUser},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "list members with policies of the clients kind with permissionswith failed list permissions",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.ClientsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read", ListPerms: true},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.ClientType,
|
||||
},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{Policies: []string{validPolicy}},
|
||||
retrieveAllResponse: users.UsersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Users: []users.User{user},
|
||||
},
|
||||
listPermissionsResponse: []string{},
|
||||
response: users.MembersPage{},
|
||||
listPermissionErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "list members with of the clients kind with failed to list all subjects",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.ClientsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.ClientType,
|
||||
},
|
||||
listAllSubjectsErr: repoerr.ErrNotFound,
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{},
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "list members with of the clients kind with failed to retrieve all",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.ClientsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.ClientType,
|
||||
},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{Policies: []string{validPolicy}},
|
||||
retrieveAllResponse: users.UsersPage{},
|
||||
response: users.MembersPage{},
|
||||
retrieveAllErr: repoerr.ErrNotFound,
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "list members with no policies successfully of the domain kind",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.DomainsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.DomainType,
|
||||
},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 0,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "list members with policies successsfully of the domains kind",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.DomainsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.DomainType,
|
||||
},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{Policies: []string{validPolicy}},
|
||||
retrieveAllResponse: users.UsersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Users: []users.User{basicUser},
|
||||
},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Members: []users.User{basicUser},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "list members with no policies successfully of the groups kind",
|
||||
groupID: validID,
|
||||
objectKind: policysvc.GroupsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.GroupType,
|
||||
},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 0,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "list members with policies successsfully of the groups kind",
|
||||
|
||||
groupID: validID,
|
||||
objectKind: policysvc.GroupsKind,
|
||||
objectID: validID,
|
||||
page: users.Page{Offset: 0, Limit: 100, Permission: "read"},
|
||||
listAllSubjectsReq: policysvc.Policy{
|
||||
SubjectType: policysvc.UserType,
|
||||
Permission: "read",
|
||||
Object: validID,
|
||||
ObjectType: policysvc.GroupType,
|
||||
},
|
||||
listAllSubjectsResponse: policysvc.PolicyPage{Policies: []string{validPolicy}},
|
||||
retrieveAllResponse: users.UsersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Users: []users.User{user},
|
||||
},
|
||||
response: users.MembersPage{
|
||||
Page: users.Page{
|
||||
Total: 1,
|
||||
Offset: 0,
|
||||
Limit: 100,
|
||||
},
|
||||
Members: []users.User{basicUser},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
policyCall := policies.On("ListAllSubjects", context.Background(), tc.listAllSubjectsReq).Return(tc.listAllSubjectsResponse, tc.listAllSubjectsErr)
|
||||
repoCall := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.retrieveAllResponse, tc.retrieveAllErr)
|
||||
policyCall1 := policies.On("ListPermissions", mock.Anything, mock.Anything, mock.Anything).Return(tc.listPermissionsResponse, tc.listPermissionErr)
|
||||
page, err := svc.ListMembers(context.Background(), authn.Session{}, tc.objectKind, tc.objectID, tc.page)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
assert.Equal(t, tc.response, page, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, page))
|
||||
policyCall.Unset()
|
||||
repoCall.Unset()
|
||||
policyCall1.Unset()
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueToken(t *testing.T) {
|
||||
svc, auth, cRepo, _, _ := newService()
|
||||
|
||||
|
||||
@@ -210,14 +210,6 @@ func (tm *tracingMiddleware) Disable(ctx context.Context, session authn.Session,
|
||||
return tm.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
// ListMembers traces the "ListMembers" operation of the wrapped users.Service.
|
||||
func (tm *tracingMiddleware) ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, pm users.Page) (users.MembersPage, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_list_members", trace.WithAttributes(attribute.String("object_kind", objectKind)), trace.WithAttributes(attribute.String("object_id", objectID)))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.ListMembers(ctx, session, objectKind, objectID, pm)
|
||||
}
|
||||
|
||||
// Identify traces the "Identify" operation of the wrapped users.Service.
|
||||
func (tm *tracingMiddleware) Identify(ctx context.Context, session authn.Session) (string, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_identify", trace.WithAttributes(attribute.String("user_id", session.UserID)))
|
||||
|
||||
@@ -151,9 +151,6 @@ type Service interface {
|
||||
// ListUsers retrieves users list for a valid auth token.
|
||||
ListUsers(ctx context.Context, session authn.Session, pm Page) (UsersPage, error)
|
||||
|
||||
// ListMembers retrieves everything that is assigned to a group/client identified by objectID.
|
||||
ListMembers(ctx context.Context, session authn.Session, objectKind, objectID string, pm Page) (MembersPage, error)
|
||||
|
||||
// SearchUsers searches for users with provided filters for a valid auth token.
|
||||
SearchUsers(ctx context.Context, pm Page) (UsersPage, error)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user