diff --git a/api/openapi/bootstrap.yml b/api/openapi/bootstrap.yml index f8bed71225..4298604215 100644 --- a/api/openapi/bootstrap.yml +++ b/api/openapi/bootstrap.yml @@ -27,7 +27,7 @@ tags: url: https://docs.magistrala.abstractmachines.fr/ paths: - /things/configs: + /{domainID}/things/configs: post: operationId: createConfig summary: Adds new config @@ -36,6 +36,8 @@ paths: the provided access token. tags: - configs + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" requestBody: $ref: "#/components/requestBodies/ConfigCreateReq" responses: @@ -70,6 +72,7 @@ paths: tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/State" @@ -85,13 +88,14 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /things/configs/{configId}: + /{domainID}/things/configs/{configId}: get: operationId: getConfig summary: Retrieves config info (with channels). tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ConfigId" responses: "200": @@ -118,6 +122,7 @@ paths: tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ConfigId" requestBody: $ref: "#/components/requestBodies/ConfigUpdateReq" @@ -147,6 +152,7 @@ paths: tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ConfigId" responses: "204": @@ -161,7 +167,7 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /things/configs/certs/{configId}: + /{domainID}/things/configs/certs/{configId}: patch: operationId: updateConfigCerts summary: Updates certs @@ -171,6 +177,7 @@ paths: tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ConfigId" requestBody: $ref: "#/components/requestBodies/ConfigCertUpdateReq" @@ -192,7 +199,7 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /things/configs/connections/{configId}: + /{domainID}/things/configs/connections/{configId}: put: operationId: updateConfigConnections summary: Updates channels the thing is connected to @@ -202,6 +209,7 @@ paths: tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ConfigId" requestBody: $ref: "#/components/requestBodies/ConfigConnUpdateReq" @@ -273,7 +281,7 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /things/state/{configId}: + /{domainID}/things/state/{configId}: put: operationId: updateConfigState summary: Updates Config state. @@ -283,6 +291,7 @@ paths: tags: - configs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ConfigId" requestBody: $ref: "#/components/requestBodies/ConfigStateUpdateReq" diff --git a/api/openapi/certs.yml b/api/openapi/certs.yml index 9e41397f73..b5ced9377b 100644 --- a/api/openapi/certs.yml +++ b/api/openapi/certs.yml @@ -27,13 +27,15 @@ tags: url: https://docs.magistrala.abstractmachines.fr/ paths: - /certs: + /{domainID}/certs: post: operationId: createCert summary: Creates a certificate for thing description: Creates a certificate for thing tags: - certs + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" requestBody: $ref: "#/components/requestBodies/CertReq" responses: @@ -51,7 +53,7 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /certs/{certID}: + /{domainID}/certs/{certID}: get: operationId: getCert summary: Retrieves a certificate @@ -60,6 +62,7 @@ paths: tags: - certs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/CertID" responses: "200": @@ -85,10 +88,13 @@ paths: tags: - certs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/CertID" responses: "200": $ref: "#/components/responses/RevokeRes" + "400": + description: Failed due to malformed query parameters. "401": description: Missing or invalid access token provided. "403": @@ -100,7 +106,7 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /serials/{thingID}: + /{domainID}/serials/{thingID}: get: operationId: getSerials summary: Retrieves certificates' serial IDs @@ -109,6 +115,7 @@ paths: tags: - certs parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" responses: "200": diff --git a/api/openapi/invitations.yml b/api/openapi/invitations.yml index 1d2d200137..a4cdf5ec9c 100644 --- a/api/openapi/invitations.yml +++ b/api/openapi/invitations.yml @@ -27,7 +27,7 @@ tags: url: https://docs.magistrala.abstractmachines.fr/ paths: - /invitations: + /{domainID}/invitations: post: operationId: sendInvitation tags: @@ -35,6 +35,8 @@ paths: summary: Send invitation description: | Send invitation to user to join domain. + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" requestBody: $ref: "#/components/requestBodies/SendInvitationReq" security: @@ -70,7 +72,7 @@ paths: - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/UserID" - $ref: "#/components/parameters/InvitedBy" - - $ref: "#/components/parameters/DomainID" + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/Relation" - $ref: "#/components/parameters/State" security: @@ -91,7 +93,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /invitations/accept: + /{domainID}/invitations/accept: post: operationId: acceptInvitation summary: Accept invitation @@ -101,8 +103,8 @@ paths: - Invitations security: - bearerAuth: [] - requestBody: - $ref: "#/components/requestBodies/AcceptInvitationReq" + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" responses: "204": description: Invitation accepted. @@ -112,10 +114,12 @@ paths: description: Missing or invalid access token provided. "404": description: A non-existent entity request. + "415": + description: Missing or invalid content type. "500": $ref: "#/components/responses/ServiceError" - /invitations/reject: + /{domainID}/invitations/reject: post: operationId: rejectInvitation summary: Reject invitation @@ -125,8 +129,8 @@ paths: - Invitations security: - bearerAuth: [] - requestBody: - $ref: "#/components/requestBodies/AcceptInvitationReq" + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" responses: "204": description: Invitation rejected. @@ -136,10 +140,12 @@ paths: description: Missing or invalid access token provided. "404": description: A non-existent entity request. + "415": + description: Missing or invalid content type. "500": $ref: "#/components/responses/ServiceError" - /invitations/{user_id}/{domain_id}: + /{domainID}/invitations/users/{user_id}: get: operationId: getInvitation summary: Retrieves a specific invitation @@ -149,7 +155,7 @@ paths: - Invitations parameters: - $ref: "#/components/parameters/user_id" - - $ref: "#/components/parameters/domain_id" + - $ref: "auth.yml#/components/parameters/DomainID" security: - bearerAuth: [] responses: @@ -161,6 +167,8 @@ paths: description: Missing or invalid access token provided. "404": description: A non-existent entity request. + "415": + description: Missing or invalid content type. "422": description: Database can't process request. "500": @@ -175,7 +183,7 @@ paths: - Invitations parameters: - $ref: "#/components/parameters/user_id" - - $ref: "#/components/parameters/domain_id" + - $ref: "auth.yml#/components/parameters/DomainID" security: - bearerAuth: [] responses: @@ -187,6 +195,8 @@ paths: description: Failed due to non existing user. "401": description: Missing or invalid access token provided. + "415": + description: Missing or invalid content type. "500": $ref: "#/components/responses/ServiceError" @@ -212,11 +222,6 @@ components: format: uuid example: bb7edb32-2eac-4aad-aebe-ed96fe073879 description: User unique identifier. - domain_id: - type: string - format: uuid - example: bb7edb32-2eac-4aad-aebe-ed96fe073879 - description: Domain unique identifier. relation: type: string enum: @@ -238,7 +243,6 @@ components: description: Resend invitation. required: - user_id - - domain_id - relation Invitation: @@ -394,26 +398,6 @@ components: required: true example: bb7edb32-2eac-4aad-aebe-ed96fe073879 - DomainID: - name: domain_id - description: Unique identifier for a domain. - in: query - schema: - type: string - format: uuid - required: false - example: bb7edb32-2eac-4aad-aebe-ed96fe073879 - - domain_id: - name: domain_id - description: Unique identifier for a domain. - in: path - schema: - type: string - format: uuid - required: true - example: bb7edb32-2eac-4aad-aebe-ed96fe073879 - InvitedBy: name: invited_by description: Unique identifier for a user that invited the user. @@ -466,22 +450,6 @@ components: schema: $ref: "#/components/schemas/SendInvitationReqObj" - AcceptInvitationReq: - description: JSON-formatted document describing request for accepting invitation - required: true - content: - application/json: - schema: - type: object - properties: - domain_id: - type: string - format: uuid - example: bb7edb32-2eac-4aad-aebe-ed96fe073879 - description: Domain unique identifier. - required: - - domain_id - responses: InvitationRes: description: Data retrieved. @@ -494,7 +462,6 @@ components: operationId: deleteInvitation parameters: user_id: $response.body#/user_id - domain_id: $response.body#/domain_id InvitationPageRes: description: Data retrieved. diff --git a/api/openapi/provision.yml b/api/openapi/provision.yml index 35b91766b3..9b814e8bc5 100644 --- a/api/openapi/provision.yml +++ b/api/openapi/provision.yml @@ -27,12 +27,14 @@ tags: url: https://docs.magistrala.abstractmachines.fr/ paths: - /mapping: + /{domainID}/mapping: post: summary: Adds new device to proxy description: Adds new device to proxy tags: - provision + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" requestBody: $ref: "#/components/requestBodies/ProvisionReq" responses: @@ -55,6 +57,8 @@ paths: configuration created with provision service. tags: - provision + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" responses: "200": $ref: "#/components/responses/ProvisionRes" diff --git a/api/openapi/things.yml b/api/openapi/things.yml index a01f63d047..852c8690bf 100644 --- a/api/openapi/things.yml +++ b/api/openapi/things.yml @@ -37,7 +37,7 @@ tags: url: https://docs.magistrala.abstractmachines.fr/ paths: - /things: + /{domainID}/things: post: operationId: createThing tags: @@ -46,6 +46,8 @@ paths: description: | Adds new thing to the list of things owned by user identified using the provided access token. + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" requestBody: $ref: "#/components/requestBodies/ThingCreateReq" responses: @@ -79,6 +81,7 @@ paths: 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/Limit" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Metadata" @@ -104,13 +107,15 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/bulk: + /{domainID}/things/bulk: post: operationId: bulkCreateThings summary: Bulk provisions new things description: | Adds new things to the list of things owned by user identified using the provided access token. + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" tags: - Things requestBody: @@ -133,7 +138,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}: + /{domainID}/things/{thingID}: get: operationId: getThing summary: Retrieves thing info @@ -142,12 +147,15 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" security: - bearerAuth: [] responses: "200": $ref: "#/components/responses/ThingRes" + "400": + description: Failed due to malformed domain ID. "401": description: Missing or invalid access token provided. "403": @@ -169,6 +177,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" requestBody: $ref: "#/components/requestBodies/ThingUpdateReq" @@ -201,12 +210,15 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" security: - bearerAuth: [] responses: "204": description: Thing deleted. + "400": + description: Failed due to malformed domain ID. "401": description: Missing or invalid access token provided. "403": @@ -215,7 +227,8 @@ paths: description: Missing thing. "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/tags: + + /{domainID}/things/{thingID}/tags: patch: operationId: updateThingTags summary: Updates tags the thing. @@ -225,6 +238,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" requestBody: $ref: "#/components/requestBodies/ThingUpdateTagsReq" @@ -246,7 +260,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/secret: + /{domainID}/things/{thingID}/secret: patch: operationId: updateThingSecret summary: Updates Secret of the identified thing. @@ -256,6 +270,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" requestBody: $ref: "#/components/requestBodies/ThingUpdateSecretReq" @@ -281,7 +296,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/disable: + /{domainID}/things/{thingID}/disable: post: operationId: disableThing summary: Disables a thing @@ -290,6 +305,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" security: - bearerAuth: [] @@ -311,7 +327,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/enable: + /{domainID}/things/{thingID}/enable: post: operationId: enableThing summary: Enables a thing @@ -320,6 +336,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" security: - bearerAuth: [] @@ -341,7 +358,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/share: + /{domainID}/things/{thingID}/share: post: operationId: shareThing summary: Shares a thing @@ -350,6 +367,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" requestBody: $ref: "#/components/requestBodies/ShareThingReq" @@ -371,7 +389,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/unshare: + /{domainID}/things/{thingID}/unshare: post: operationId: unshareThing summary: Unshares a thing @@ -380,6 +398,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" requestBody: $ref: "#/components/requestBodies/ShareThingReq" @@ -401,7 +420,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/things: + /{domainID}/channels/{chanID}/things: get: operationId: listThingsInaChannel summary: List of things connected to specified channel @@ -411,6 +430,7 @@ paths: tags: - Things parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Limit" @@ -431,7 +451,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels: + /{domainID}/channels: post: operationId: createChannel tags: @@ -443,6 +463,8 @@ paths: $ref: "#/components/requestBodies/ChannelCreateReq" security: - bearerAuth: [] + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" responses: "201": $ref: "#/components/responses/ChannelCreateRes" @@ -476,6 +498,7 @@ paths: security: - bearerAuth: [] parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Metadata" @@ -496,7 +519,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}: + /{domainID}/channels/{chanID}: get: operationId: getChannel summary: Retrieves channel info. @@ -505,6 +528,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" security: - bearerAuth: [] @@ -512,7 +536,7 @@ paths: "200": $ref: "#/components/responses/ChannelRes" "400": - description: Failed due to malformed channel's ID. + description: Failed due to malformed channel's or domain ID. "401": description: Missing or invalid access token provided. "403": @@ -534,6 +558,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" security: - bearerAuth: [] @@ -566,12 +591,15 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" security: - bearerAuth: [] responses: "204": description: Channel deleted. + "400": + description: Failed due to malformed domain ID. "401": description: Missing or invalid access token provided. "403": @@ -581,7 +609,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/enable: + /{domainID}/channels/{chanID}/enable: post: operationId: enableChannel summary: Enables a channel @@ -590,6 +618,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" security: - bearerAuth: [] @@ -611,7 +640,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/disable: + /{domainID}/channels/{chanID}/disable: post: operationId: disableChannel summary: Disables a channel @@ -620,6 +649,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" security: - bearerAuth: [] @@ -641,7 +671,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/users/assign: + /{domainID}/channels/{chanID}/users/assign: post: operationId: assignUsersToChannel summary: Assigns a member to a channel @@ -650,6 +680,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" requestBody: $ref: "#/components/requestBodies/AssignUserReq" @@ -671,7 +702,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/users/unassign: + /{domainID}/channels/{chanID}/users/unassign: post: operationId: unassignUsersFromChannel summary: Unassigns a member from a channel @@ -680,6 +711,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" requestBody: $ref: "#/components/requestBodies/AssignUserReq" @@ -701,7 +733,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/groups/assign: + /{domainID}/channels/{chanID}/groups/assign: post: operationId: assignGroupsToChannel summary: Assigns a member to a channel @@ -710,6 +742,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" requestBody: $ref: "#/components/requestBodies/AssignUsersReq" @@ -731,7 +764,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/groups/unassign: + /{domainID}/channels/{chanID}/groups/unassign: post: operationId: unassignGroupsFromChannel summary: Unassigns a member from a channel @@ -740,6 +773,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" requestBody: $ref: "#/components/requestBodies/AssignUsersReq" @@ -761,7 +795,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /things/{thingID}/channels: + /{domainID}/things/{thingID}/channels: get: operationId: listChannelsConnectedToThing summary: List of channels connected to specified thing @@ -771,6 +805,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/ThingID" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Limit" @@ -790,7 +825,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /users/{memberID}/channels: + /{domainID}/users/{memberID}/channels: get: operationId: listChannelsConnectedToUser summary: List of channels connected to specified user @@ -800,6 +835,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/MemberID" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Limit" @@ -819,7 +855,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{memberID}/channels: + /{domainID}/groups/{memberID}/channels: get: operationId: listChannelsConnectedToGroup summary: List of channels connected to specified group @@ -829,6 +865,7 @@ paths: tags: - Channels parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/MemberID" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Limit" @@ -848,13 +885,15 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /connect: + /{domainID}/connect: post: operationId: connectThingsAndChannels summary: Connects thing and channel. description: | Connect things specified by IDs to channels specified by IDs. Channel and thing are owned by user identified using the provided access token. + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" tags: - Policies requestBody: @@ -879,13 +918,15 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /disconnect: + /{domainID}/disconnect: post: operationId: disconnectThingsAndChannels summary: Disconnect things and channels using lists of IDs. description: | Disconnect things from channels specified by lists of IDs. Channels and things are owned by user identified using the provided access token. + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" tags: - Policies requestBody: @@ -908,7 +949,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/things/{thingID}/connect: + /{domainID}/channels/{chanID}/things/{thingID}/connect: post: operationId: connectThingToChannel summary: Connects a thing to a channel @@ -917,6 +958,7 @@ paths: tags: - Policies parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" - $ref: "#/components/parameters/ThingID" responses: @@ -935,7 +977,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{chanID}/things/{thingID}/disconnect: + /{domainID}/channels/{chanID}/things/{thingID}/disconnect: post: operationId: disconnectThingFromChannel summary: Disconnects a thing to a channel @@ -944,6 +986,7 @@ paths: tags: - Policies parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/chanID" - $ref: "#/components/parameters/ThingID" responses: diff --git a/api/openapi/users.yml b/api/openapi/users.yml index 8f2df294dc..eb6cbdbed0 100644 --- a/api/openapi/users.yml +++ b/api/openapi/users.yml @@ -606,7 +606,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups: + /{domainID}/groups: post: operationId: createGroup tags: @@ -615,6 +615,8 @@ paths: description: | Creates new group that can be used for grouping entities. New account will be uniquely identified by its identity. + parameters: + - $ref: "auth.yml#/components/parameters/DomainID" requestBody: $ref: "#/components/requestBodies/GroupCreateReq" security: @@ -652,6 +654,7 @@ paths: security: - bearerAuth: [] parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/Level" @@ -675,7 +678,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}: + /{domainID}/groups/{groupID}: get: operationId: getGroup summary: Gets group info. @@ -684,6 +687,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" security: - bearerAuth: [] @@ -711,6 +715,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" security: - bearerAuth: [] @@ -743,12 +748,15 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" security: - bearerAuth: [] responses: "204": description: Group deleted. + "400": + description: Failed due to malformed query parameters. "401": description: Missing or invalid access token provided. "403": @@ -758,7 +766,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}/children: + /{domainID}/groups/{groupID}/children: get: operationId: listChildren summary: List children of a certain group @@ -772,6 +780,7 @@ paths: security: - bearerAuth: [] parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" @@ -796,7 +805,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}/parents: + /{domainID}/groups/{groupID}/parents: get: operationId: listParents summary: List parents of a certain group @@ -810,6 +819,7 @@ paths: security: - bearerAuth: [] parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" @@ -834,7 +844,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}/enable: + /{domainID}/groups/{groupID}/enable: post: operationId: enableGroup summary: Enables a group @@ -843,6 +853,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" security: - bearerAuth: [] @@ -866,7 +877,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}/disable: + /{domainID}/groups/{groupID}/disable: post: operationId: disableGroup summary: Disables a group @@ -875,6 +886,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" security: - bearerAuth: [] @@ -898,7 +910,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}/users/assign: + /{domainID}/groups/{groupID}/users/assign: post: operationId: assignUser summary: Assigns a user to a group @@ -907,6 +919,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" requestBody: $ref: "#/components/requestBodies/AssignUserReq" @@ -930,7 +943,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /groups/{groupID}/users/unassign: + /{domainID}/groups/{groupID}/users/unassign: post: operationId: unassignUser summary: Unassigns a user to a group @@ -939,6 +952,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/GroupID" requestBody: $ref: "#/components/requestBodies/AssignUserReq" @@ -962,7 +976,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /channels/{memberID}/groups: + /{domainID}/channels/{memberID}/groups: get: operationId: listGroupsInChannel summary: Get group associated with the member @@ -971,6 +985,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/MemberID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" @@ -995,7 +1010,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /users/{memberID}/groups: + /{domainID}/users/{memberID}/groups: get: operationId: listGroupsByUser summary: Get group associated with the member @@ -1004,6 +1019,7 @@ paths: tags: - Groups parameters: + - $ref: "auth.yml#/components/parameters/DomainID" - $ref: "#/components/parameters/MemberID" - $ref: "#/components/parameters/Limit" - $ref: "#/components/parameters/Offset" @@ -1027,7 +1043,7 @@ paths: description: Database can't process request. "500": $ref: "#/components/responses/ServiceError" - /domains/{domainID}/users: + /{domainID}/users: get: summary: List users assigned to domain description: | diff --git a/bootstrap/api/endpoint_test.go b/bootstrap/api/endpoint_test.go index b8003a83b5..ba76ca98a2 100644 --- a/bootstrap/api/endpoint_test.go +++ b/bootstrap/api/endpoint_test.go @@ -34,6 +34,7 @@ import ( const ( validToken = "validToken" + domainID = "b4d7d79e-fd99-4c2b-ac09-524e43df6888" invalidToken = "invalid" email = "test@example.com" unknown = "unknown" @@ -209,6 +210,7 @@ func TestAdd(t *testing.T) { cases := []struct { desc string req string + domainID string token string session mgauthn.Session contentType string @@ -220,6 +222,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with invalid token", req: data, + domainID: domainID, token: invalidToken, contentType: contentType, status: http.StatusUnauthorized, @@ -230,6 +233,7 @@ func TestAdd(t *testing.T) { { desc: "add a valid config", req: data, + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusCreated, @@ -239,6 +243,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with wrong content type", req: data, + domainID: domainID, token: validToken, contentType: "", status: http.StatusUnsupportedMediaType, @@ -248,6 +253,7 @@ func TestAdd(t *testing.T) { { desc: "add an existing config", req: data, + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusConflict, @@ -257,6 +263,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with non-existent ID", req: neData, + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusConflict, @@ -266,6 +273,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with invalid channels", req: wrongData, + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusConflict, @@ -275,6 +283,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with wrong JSON", req: "{\"external_id\": 5}", + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusBadRequest, @@ -283,6 +292,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with invalid request format", req: "}", + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusBadRequest, @@ -292,6 +302,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with empty JSON", req: "{}", + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusBadRequest, @@ -301,6 +312,7 @@ func TestAdd(t *testing.T) { { desc: "add a config with an empty request", req: "", + domainID: domainID, token: validToken, contentType: contentType, status: http.StatusBadRequest, @@ -310,26 +322,29 @@ func TestAdd(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("Add", mock.Anything, tc.session, tc.token, mock.Anything).Return(c, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/configs", bs.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - location := res.Header.Get("Location") - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.location, location, fmt.Sprintf("%s: expected location '%s' got '%s'", tc.desc, tc.location, location)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + + svcCall := svc.On("Add", mock.Anything, tc.session, tc.token, mock.Anything).Return(c, tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/configs", bs.URL, tc.domainID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.req), + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + location := res.Header.Get("Location") + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + assert.Equal(t, tc.location, location, fmt.Sprintf("%s: expected location '%s' got '%s'", tc.desc, tc.location, location)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -408,33 +423,35 @@ func TestView(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("View", mock.Anything, tc.session, tc.id).Return(c, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/things/configs/%s", bs.URL, tc.id), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - var view config - if err := json.NewDecoder(res.Body).Decode(&view); err != io.EOF { - assert.Nil(t, err, fmt.Sprintf("Decoding expected to succeed %s: %s", tc.desc, err)) - } - - assert.ElementsMatch(t, tc.res.Channels, view.Channels, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res.Channels, view.Channels)) - // Empty channels to prevent order mismatch. - tc.res.Channels = []channel{} - view.Channels = []channel{} - assert.Equal(t, tc.res, view, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res, view)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("View", mock.Anything, tc.session, tc.id).Return(c, tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/things/configs/%s", bs.URL, domainID, tc.id), + token: tc.token, + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + var view config + if err := json.NewDecoder(res.Body).Decode(&view); err != io.EOF { + assert.Nil(t, err, fmt.Sprintf("Decoding expected to succeed %s: %s", tc.desc, err)) + } + + assert.ElementsMatch(t, tc.res.Channels, view.Channels, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res.Channels, view.Channels)) + // Empty channels to prevent order mismatch. + tc.res.Channels = []channel{} + view.Channels = []channel{} + assert.Equal(t, tc.res, view, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res, view)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -523,24 +540,26 @@ func TestUpdate(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("Update", mock.Anything, tc.session, mock.Anything).Return(tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodPut, - url: fmt.Sprintf("%s/things/configs/%s", bs.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("Update", mock.Anything, tc.session, mock.Anything).Return(tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodPut, + url: fmt.Sprintf("%s/%s/things/configs/%s", bs.URL, domainID, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.req), + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -629,24 +648,26 @@ func TestUpdateCert(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("UpdateCert", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(c, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/things/configs/certs/%s", bs.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("UpdateCert", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(c, tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/%s/things/configs/certs/%s", bs.URL, domainID, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.req), + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -748,24 +769,26 @@ func TestUpdateConnections(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - repoCall := svc.On("UpdateConnections", mock.Anything, tc.session, tc.token, mock.Anything, mock.Anything).Return(tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodPut, - url: fmt.Sprintf("%s/things/configs/connections/%s", bs.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - repoCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + repoCall := svc.On("UpdateConnections", mock.Anything, tc.session, tc.token, mock.Anything, mock.Anything).Return(tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodPut, + url: fmt.Sprintf("%s/%s/things/configs/connections/%s", bs.URL, domainID, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.req), + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + repoCall.Unset() + authCall.Unset() + }) } } @@ -777,7 +800,7 @@ func TestList(t *testing.T) { bs, svc, auth := newBootstrapServer() defer bs.Close() - path := fmt.Sprintf("%s/%s", bs.URL, "things/configs") + path := fmt.Sprintf("%s/%s/%s", bs.URL, domainID, "things/configs") c := newConfig() @@ -1015,23 +1038,33 @@ func TestList(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("List", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bootstrap.ConfigsPage{Total: tc.res.Total, Offset: tc.res.Offset, Limit: tc.res.Limit}, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodGet, - url: tc.url, - token: tc.token, - } - - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("List", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bootstrap.ConfigsPage{Total: tc.res.Total, Offset: tc.res.Offset, Limit: tc.res.Limit}, tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodGet, + url: tc.url, + token: tc.token, + } + + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + var body configPage + + err = json.NewDecoder(res.Body).Decode(&body) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + assert.Equal(t, tc.res.Total, body.Total, fmt.Sprintf("%s: expected response total '%d' got '%d'", tc.desc, tc.res.Total, body.Total)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1088,22 +1121,24 @@ func TestRemove(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("Remove", mock.Anything, mock.Anything, mock.Anything).Return(tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodDelete, - url: fmt.Sprintf("%s/things/configs/%s", bs.URL, tc.id), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("Remove", mock.Anything, mock.Anything, mock.Anything).Return(tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodDelete, + url: fmt.Sprintf("%s/%s/things/configs/%s", bs.URL, domainID, tc.id), + token: tc.token, + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1215,26 +1250,28 @@ func TestBootstrap(t *testing.T) { } for _, tc := range cases { - svcCall := svc.On("Bootstrap", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(c, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/things/bootstrap/%s", bs.URL, tc.externalID), - key: tc.externalKey, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - body, err := io.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - if tc.secure && tc.status == http.StatusOK { - body, err = dec(body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding body: %s", tc.desc, err)) - } - data := strings.Trim(string(body), "\n") - assert.Equal(t, tc.res, data, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res, data)) - svcCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + svcCall := svc.On("Bootstrap", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(c, tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/things/bootstrap/%s", bs.URL, tc.externalID), + key: tc.externalKey, + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + body, err := io.ReadAll(res.Body) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + if tc.secure && tc.status == http.StatusOK { + body, err = dec(body) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding body: %s", tc.desc, err)) + } + data := strings.Trim(string(body), "\n") + assert.Equal(t, tc.res, data, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res, data)) + svcCall.Unset() + }) } } @@ -1333,24 +1370,26 @@ func TestChangeState(t *testing.T) { } for _, tc := range cases { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("ChangeState", mock.Anything, tc.session, tc.token, mock.Anything, mock.Anything).Return(tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodPut, - url: fmt.Sprintf("%s/things/state/%s", bs.URL, tc.id), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(tc.state), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + if tc.token == validToken { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("ChangeState", mock.Anything, tc.session, tc.token, mock.Anything, mock.Anything).Return(tc.err) + req := testRequest{ + client: bs.Client(), + method: http.MethodPut, + url: fmt.Sprintf("%s/%s/things/state/%s", bs.URL, domainID, tc.id), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(tc.state), + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } diff --git a/bootstrap/api/requests_test.go b/bootstrap/api/requests_test.go index 666a3c597f..73ac1df9df 100644 --- a/bootstrap/api/requests_test.go +++ b/bootstrap/api/requests_test.go @@ -112,7 +112,10 @@ func TestEntityReqValidation(t *testing.T) { } for _, tc := range cases { - req := entityReq{} + req := entityReq{ + id: tc.id, + } + err := req.validate() assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) } @@ -120,10 +123,9 @@ func TestEntityReqValidation(t *testing.T) { func TestUpdateReqValidation(t *testing.T) { cases := []struct { - desc string - token string - id string - err error + desc string + id string + err error }{ { desc: "valid request", @@ -175,7 +177,8 @@ func TestUpdateConnReqValidation(t *testing.T) { desc string id string token string - err error + + err error }{ { desc: "empty token", diff --git a/bootstrap/api/transport.go b/bootstrap/api/transport.go index 176a5f04cd..c5a76927ab 100644 --- a/bootstrap/api/transport.go +++ b/bootstrap/api/transport.go @@ -47,7 +47,7 @@ func MakeHandler(svc bootstrap.Service, authn mgauthn.Authentication, reader boo r := chi.NewRouter() - r.Route("/things", func(r chi.Router) { + r.Route("/{domainID}/things", func(r chi.Router) { r.Group(func(r chi.Router) { r.Use(api.AuthenticateMiddleware(authn)) @@ -96,30 +96,31 @@ func MakeHandler(svc bootstrap.Service, authn mgauthn.Authentication, reader boo }) }) - r.Route("/bootstrap", func(r chi.Router) { - r.Get("/", otelhttp.NewHandler(kithttp.NewServer( - bootstrapEndpoint(svc, reader, false), - decodeBootstrapRequest, - api.EncodeResponse, - opts...), "bootstrap").ServeHTTP) - r.Get("/{externalID}", otelhttp.NewHandler(kithttp.NewServer( - bootstrapEndpoint(svc, reader, false), - decodeBootstrapRequest, - api.EncodeResponse, - opts...), "bootstrap").ServeHTTP) - r.Get("/secure/{externalID}", otelhttp.NewHandler(kithttp.NewServer( - bootstrapEndpoint(svc, reader, true), - decodeBootstrapRequest, - encodeSecureRes, - opts...), "bootstrap_secure").ServeHTTP) - }) - r.With(api.AuthenticateMiddleware(authn)).Put("/state/{thingID}", otelhttp.NewHandler(kithttp.NewServer( stateEndpoint(svc), decodeStateRequest, api.EncodeResponse, opts...), "update_state").ServeHTTP) }) + + r.Route("/things/bootstrap", func(r chi.Router) { + r.Get("/", otelhttp.NewHandler(kithttp.NewServer( + bootstrapEndpoint(svc, reader, false), + decodeBootstrapRequest, + api.EncodeResponse, + opts...), "bootstrap").ServeHTTP) + r.Get("/{externalID}", otelhttp.NewHandler(kithttp.NewServer( + bootstrapEndpoint(svc, reader, false), + decodeBootstrapRequest, + api.EncodeResponse, + opts...), "bootstrap").ServeHTTP) + r.Get("/secure/{externalID}", otelhttp.NewHandler(kithttp.NewServer( + bootstrapEndpoint(svc, reader, true), + decodeBootstrapRequest, + encodeSecureRes, + opts...), "bootstrap_secure").ServeHTTP) + }) + r.Get("/health", magistrala.Health("bootstrap", instanceID)) r.Handle("/metrics", promhttp.Handler()) @@ -131,7 +132,9 @@ func decodeAddRequest(_ context.Context, r *http.Request) (interface{}, error) { return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) } - req := addReq{token: apiutil.ExtractBearerToken(r)} + req := addReq{ + token: apiutil.ExtractBearerToken(r), + } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) } diff --git a/bootstrap/events/producer/streams_test.go b/bootstrap/events/producer/streams_test.go index 6ad6a003df..cd896621ae 100644 --- a/bootstrap/events/producer/streams_test.go +++ b/bootstrap/events/producer/streams_test.go @@ -192,7 +192,7 @@ func TestAdd(t *testing.T) { lastID := "0" for _, tc := range cases { tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID} - sdkCall := tv.sdk.On("Thing", tc.config.ThingID, tc.token).Return(mgsdk.Thing{ID: tc.config.ThingID, Credentials: mgsdk.Credentials{Secret: tc.config.ThingKey}}, errors.NewSDKError(tc.thingErr)) + sdkCall := tv.sdk.On("Thing", tc.config.ThingID, tc.domainID, tc.token).Return(mgsdk.Thing{ID: tc.config.ThingID, Credentials: mgsdk.Credentials{Secret: tc.config.ThingKey}}, errors.NewSDKError(tc.thingErr)) repoCall := tv.boot.On("ListExisting", context.Background(), domainID, mock.Anything).Return(tc.config.Channels, tc.listErr) repoCall1 := tv.boot.On("Save", context.Background(), mock.Anything, mock.Anything).Return(mock.Anything, tc.saveErr) @@ -475,7 +475,7 @@ func TestUpdateConnections(t *testing.T) { lastID := "0" for _, tc := range cases { tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID} - sdkCall := tv.sdk.On("Channel", mock.Anything, tc.token).Return(mgsdk.Channel{}, tc.channelErr) + sdkCall := tv.sdk.On("Channel", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Channel{}, tc.channelErr) repoCall := tv.boot.On("RetrieveByID", context.Background(), tc.domainID, tc.configID).Return(config, tc.retrieveErr) repoCall1 := tv.boot.On("ListExisting", context.Background(), domainID, mock.Anything, mock.Anything).Return(config.Channels, tc.listErr) repoCall2 := tv.boot.On("UpdateConnections", context.Background(), tc.domainID, tc.configID, mock.Anything, tc.connections).Return(tc.updateErr) @@ -1054,7 +1054,7 @@ func TestChangeState(t *testing.T) { for _, tc := range cases { tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID} repoCall := tv.boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(config, tc.retrieveErr) - sdkCall1 := tv.sdk.On("Connect", mock.Anything, mock.Anything).Return(errors.NewSDKError(tc.connectErr)) + sdkCall1 := tv.sdk.On("Connect", mock.Anything, mock.Anything, mock.Anything).Return(errors.NewSDKError(tc.connectErr)) repoCall1 := tv.boot.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(tc.stateErr) err := tv.svc.ChangeState(context.Background(), tc.session, tc.token, tc.id, tc.state) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) diff --git a/bootstrap/service.go b/bootstrap/service.go index 1e78e0918d..91976bd563 100644 --- a/bootstrap/service.go +++ b/bootstrap/service.go @@ -146,13 +146,13 @@ func (bs bootstrapService) Add(ctx context.Context, session mgauthn.Session, tok return Config{}, errors.Wrap(errCheckChannels, err) } - cfg.Channels, err = bs.connectionChannels(toConnect, bs.toIDList(existing), token) + cfg.Channels, err = bs.connectionChannels(toConnect, bs.toIDList(existing), session.DomainID, token) if err != nil { return Config{}, errors.Wrap(errConnectionChannels, err) } id := cfg.ThingID - mgThing, err := bs.thing(id, token) + mgThing, err := bs.thing(session.DomainID, id, token) if err != nil { return Config{}, errors.Wrap(errThingNotFound, err) } @@ -173,7 +173,7 @@ func (bs bootstrapService) Add(ctx context.Context, session mgauthn.Session, tok // If id is empty, then a new thing has been created function - bs.thing(id, token) // So, on bootstrap config save error , delete the newly created thing. if id == "" { - if errT := bs.sdk.DeleteThing(cfg.ThingID, token); errT != nil { + if errT := bs.sdk.DeleteThing(cfg.ThingID, cfg.DomainID, token); errT != nil { err = errors.Wrap(err, errT) } } @@ -224,7 +224,7 @@ func (bs bootstrapService) UpdateConnections(ctx context.Context, session mgauth return errors.Wrap(errUpdateConnections, err) } - channels, err := bs.connectionChannels(connections, bs.toIDList(existing), token) + channels, err := bs.connectionChannels(connections, bs.toIDList(existing), session.DomainID, token) if err != nil { return errors.Wrap(errUpdateConnections, err) } @@ -238,7 +238,7 @@ func (bs bootstrapService) UpdateConnections(ctx context.Context, session mgauth } for _, c := range disconnect { - if err := bs.sdk.DisconnectThing(id, c, token); err != nil { + if err := bs.sdk.DisconnectThing(id, c, session.DomainID, token); err != nil { if errors.Contains(err, repoerr.ErrNotFound) { continue } @@ -251,7 +251,7 @@ func (bs bootstrapService) UpdateConnections(ctx context.Context, session mgauth ChannelID: c, ThingID: id, } - if err := bs.sdk.Connect(conIDs, token); err != nil { + if err := bs.sdk.Connect(conIDs, session.DomainID, token); err != nil { return ErrThings } } @@ -340,7 +340,7 @@ func (bs bootstrapService) ChangeState(ctx context.Context, session mgauthn.Sess ChannelID: c.ID, ThingID: cfg.ThingID, } - if err := bs.sdk.Connect(conIDs, token); err != nil { + if err := bs.sdk.Connect(conIDs, session.DomainID, token); err != nil { // Ignore conflict errors as they indicate the connection already exists. if errors.Contains(err, svcerr.ErrConflict) { continue @@ -350,7 +350,7 @@ func (bs bootstrapService) ChangeState(ctx context.Context, session mgauthn.Sess } case Inactive: for _, c := range cfg.Channels { - if err := bs.sdk.DisconnectThing(cfg.ThingID, c.ID, token); err != nil { + if err := bs.sdk.DisconnectThing(cfg.ThingID, c.ID, session.DomainID, token); err != nil { if errors.Contains(err, repoerr.ErrNotFound) { continue } @@ -400,14 +400,14 @@ func (bs bootstrapService) DisconnectThingHandler(ctx context.Context, channelID } // Method thing retrieves Magistrala Thing creating one if an empty ID is passed. -func (bs bootstrapService) thing(id, token string) (mgsdk.Thing, error) { +func (bs bootstrapService) thing(domainID, id, token string) (mgsdk.Thing, error) { // If Thing ID is not provided, then create new thing. if id == "" { id, err := bs.idProvider.ID() if err != nil { return mgsdk.Thing{}, errors.Wrap(errCreateThing, err) } - thing, sdkErr := bs.sdk.CreateThing(mgsdk.Thing{ID: id, Name: "Bootstrapped Thing " + id}, token) + thing, sdkErr := bs.sdk.CreateThing(mgsdk.Thing{ID: id, Name: "Bootstrapped Thing " + id}, domainID, token) if sdkErr != nil { return mgsdk.Thing{}, errors.Wrap(errCreateThing, sdkErr) } @@ -415,14 +415,14 @@ func (bs bootstrapService) thing(id, token string) (mgsdk.Thing, error) { } // If Thing ID is provided, then retrieve thing - thing, sdkErr := bs.sdk.Thing(id, token) + thing, sdkErr := bs.sdk.Thing(id, domainID, token) if sdkErr != nil { return mgsdk.Thing{}, errors.Wrap(ErrThings, sdkErr) } return thing, nil } -func (bs bootstrapService) connectionChannels(channels, existing []string, token string) ([]Channel, error) { +func (bs bootstrapService) connectionChannels(channels, existing []string, domainID, token string) ([]Channel, error) { add := make(map[string]bool, len(channels)) for _, ch := range channels { add[ch] = true @@ -436,7 +436,7 @@ func (bs bootstrapService) connectionChannels(channels, existing []string, token var ret []Channel for id := range add { - ch, err := bs.sdk.Channel(id, token) + ch, err := bs.sdk.Channel(id, domainID, token) if err != nil { return nil, errors.Wrap(errors.ErrMalformedEntity, err) } diff --git a/bootstrap/service_test.go b/bootstrap/service_test.go index ab7b4cdf3d..18a2a8268d 100644 --- a/bootstrap/service_test.go +++ b/bootstrap/service_test.go @@ -150,19 +150,21 @@ func TestAdd(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} - repoCall := sdk.On("Thing", tc.config.ThingID, tc.token).Return(mgsdk.Thing{ID: tc.config.ThingID, Credentials: mgsdk.Credentials{Secret: tc.config.ThingKey}}, tc.thingErr) - repoCall1 := sdk.On("CreateThing", mock.Anything, tc.token).Return(mgsdk.Thing{}, tc.createThingErr) - repoCall2 := sdk.On("DeleteThing", tc.config.ThingID, tc.token).Return(tc.deleteThingErr) - repoCall3 := boot.On("ListExisting", context.Background(), tc.domainID, mock.Anything).Return(tc.config.Channels, tc.listExistingErr) - repoCall4 := boot.On("Save", context.Background(), mock.Anything, mock.Anything).Return(mock.Anything, tc.saveErr) - _, err := svc.Add(context.Background(), tc.session, tc.token, tc.config) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() - repoCall1.Unset() - repoCall2.Unset() - repoCall3.Unset() - repoCall4.Unset() + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} + repoCall := sdk.On("Thing", tc.config.ThingID, mock.Anything, tc.token).Return(mgsdk.Thing{ID: tc.config.ThingID, Credentials: mgsdk.Credentials{Secret: tc.config.ThingKey}}, tc.thingErr) + repoCall1 := sdk.On("CreateThing", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Thing{}, tc.createThingErr) + repoCall2 := sdk.On("DeleteThing", tc.config.ThingID, tc.domainID, tc.token).Return(tc.deleteThingErr) + repoCall3 := boot.On("ListExisting", context.Background(), tc.domainID, mock.Anything).Return(tc.config.Channels, tc.listExistingErr) + repoCall4 := boot.On("Save", context.Background(), mock.Anything, mock.Anything).Return(mock.Anything, tc.saveErr) + _, err := svc.Add(context.Background(), tc.session, tc.token, tc.config) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + repoCall1.Unset() + repoCall2.Unset() + repoCall3.Unset() + repoCall4.Unset() + }) } } @@ -214,11 +216,13 @@ func TestView(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domain, DomainUserID: validID} - repoCall := boot.On("RetrieveByID", context.Background(), tc.thingDomain, tc.configID).Return(config, tc.retrieveErr) - _, err := svc.View(context.Background(), tc.session, tc.configID) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domain, DomainUserID: validID} + repoCall := boot.On("RetrieveByID", context.Background(), tc.thingDomain, tc.configID).Return(config, tc.retrieveErr) + _, err := svc.View(context.Background(), tc.session, tc.configID) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -276,11 +280,13 @@ func TestUpdate(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} - repoCall := boot.On("Update", context.Background(), mock.Anything).Return(tc.updateErr) - err := svc.Update(context.Background(), tc.session, tc.config) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} + repoCall := boot.On("Update", context.Background(), mock.Anything).Return(tc.updateErr) + err := svc.Update(context.Background(), tc.session, tc.config) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -349,18 +355,20 @@ func TestUpdateCert(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} - repoCall := boot.On("UpdateCert", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.expectedConfig, tc.updateErr) - cfg, err := svc.UpdateCert(context.Background(), tc.session, tc.thingID, tc.clientCert, tc.clientKey, tc.caCert) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - sort.Slice(cfg.Channels, func(i, j int) bool { - return cfg.Channels[i].ID < cfg.Channels[j].ID - }) - sort.Slice(tc.expectedConfig.Channels, func(i, j int) bool { - return tc.expectedConfig.Channels[i].ID < tc.expectedConfig.Channels[j].ID + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} + repoCall := boot.On("UpdateCert", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.expectedConfig, tc.updateErr) + cfg, err := svc.UpdateCert(context.Background(), tc.session, tc.thingID, tc.clientCert, tc.clientKey, tc.caCert) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + sort.Slice(cfg.Channels, func(i, j int) bool { + return cfg.Channels[i].ID < cfg.Channels[j].ID + }) + sort.Slice(tc.expectedConfig.Channels, func(i, j int) bool { + return tc.expectedConfig.Channels[i].ID < tc.expectedConfig.Channels[j].ID + }) + assert.Equal(t, tc.expectedConfig, cfg, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.expectedConfig, cfg)) + repoCall.Unset() }) - assert.Equal(t, tc.expectedConfig, cfg, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.expectedConfig, cfg)) - repoCall.Unset() } } @@ -424,17 +432,19 @@ func TestUpdateConnections(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} - sdkCall := sdk.On("Channel", mock.Anything, tc.token).Return(mgsdk.Channel{}, tc.channelErr) - repoCall := boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(c, tc.retrieveErr) - repoCall1 := boot.On("ListExisting", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(c.Channels, tc.listErr) - repoCall2 := boot.On("UpdateConnections", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.updateErr) - err := svc.UpdateConnections(context.Background(), tc.session, tc.token, tc.id, tc.connections) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - sdkCall.Unset() - repoCall.Unset() - repoCall1.Unset() - repoCall2.Unset() + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} + sdkCall := sdk.On("Channel", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Channel{}, tc.channelErr) + repoCall := boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(c, tc.retrieveErr) + repoCall1 := boot.On("ListExisting", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(c.Channels, tc.listErr) + repoCall2 := boot.On("UpdateConnections", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.updateErr) + err := svc.UpdateConnections(context.Background(), tc.session, tc.token, tc.id, tc.connections) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + sdkCall.Unset() + repoCall.Unset() + repoCall1.Unset() + repoCall2.Unset() + }) } } @@ -707,20 +717,22 @@ func TestList(t *testing.T) { } for _, tc := range cases { - policyCall := policies.On("ListAllObjects", mock.Anything, policysvc.Policy{ - SubjectType: policysvc.UserType, - Subject: tc.userID, - Permission: policysvc.ViewPermission, - ObjectType: policysvc.ThingType, - }).Return(tc.listObjectsResponse, tc.listObjectsErr) - repoCall := boot.On("RetrieveAll", context.Background(), mock.Anything, mock.Anything, tc.filter, tc.offset, tc.limit).Return(tc.config, tc.retrieveErr) + t.Run(tc.desc, func(t *testing.T) { + policyCall := policies.On("ListAllObjects", mock.Anything, policysvc.Policy{ + SubjectType: policysvc.UserType, + Subject: tc.userID, + Permission: policysvc.ViewPermission, + ObjectType: policysvc.ThingType, + }).Return(tc.listObjectsResponse, tc.listObjectsErr) + repoCall := boot.On("RetrieveAll", context.Background(), mock.Anything, mock.Anything, tc.filter, tc.offset, tc.limit).Return(tc.config, tc.retrieveErr) - result, err := svc.List(context.Background(), tc.session, tc.filter, tc.offset, tc.limit) - assert.ElementsMatch(t, tc.config.Configs, result.Configs, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Configs, result.Configs)) - assert.Equal(t, tc.config.Total, result.Total, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Total, result.Total)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - policyCall.Unset() - repoCall.Unset() + result, err := svc.List(context.Background(), tc.session, tc.filter, tc.offset, tc.limit) + assert.ElementsMatch(t, tc.config.Configs, result.Configs, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Configs, result.Configs)) + assert.Equal(t, tc.config.Total, result.Total, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Total, result.Total)) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + policyCall.Unset() + repoCall.Unset() + }) } } @@ -766,11 +778,13 @@ func TestRemove(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} - repoCall := boot.On("Remove", context.Background(), mock.Anything, mock.Anything).Return(tc.removeErr) - err := svc.Remove(context.Background(), tc.session, tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} + repoCall := boot.On("Remove", context.Background(), mock.Anything, mock.Anything).Return(tc.removeErr) + err := svc.Remove(context.Background(), tc.session, tc.id) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -834,11 +848,13 @@ func TestBootstrap(t *testing.T) { } for _, tc := range cases { - repoCall := boot.On("RetrieveByExternalID", context.Background(), mock.Anything).Return(tc.config, tc.err) - config, err := svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, tc.encrypted) - assert.Equal(t, tc.config, config, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.config, config)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + repoCall := boot.On("RetrieveByExternalID", context.Background(), mock.Anything).Return(tc.config, tc.err) + config, err := svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, tc.encrypted) + assert.Equal(t, tc.config, config, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.config, config)) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -920,15 +936,17 @@ func TestChangeState(t *testing.T) { } for _, tc := range cases { - tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} - repoCall := boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(c, tc.retrieveErr) - sdkCall := sdk.On("Connect", mock.Anything, mock.Anything).Return(tc.connectErr) - repoCall1 := boot.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(tc.stateErr) - err := svc.ChangeState(context.Background(), tc.session, tc.token, tc.id, tc.state) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - sdkCall.Unset() - repoCall.Unset() - repoCall1.Unset() + t.Run(tc.desc, func(t *testing.T) { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID} + repoCall := boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(c, tc.retrieveErr) + sdkCall := sdk.On("Connect", mock.Anything, mock.Anything, mock.Anything).Return(tc.connectErr) + repoCall1 := boot.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(tc.stateErr) + err := svc.ChangeState(context.Background(), tc.session, tc.token, tc.id, tc.state) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + sdkCall.Unset() + repoCall.Unset() + repoCall1.Unset() + }) } } @@ -959,10 +977,12 @@ func TestUpdateChannelHandler(t *testing.T) { } for _, tc := range cases { - repoCall := boot.On("UpdateChannel", context.Background(), mock.Anything).Return(tc.err) - err := svc.UpdateChannelHandler(context.Background(), tc.channel) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + repoCall := boot.On("UpdateChannel", context.Background(), mock.Anything).Return(tc.err) + err := svc.UpdateChannelHandler(context.Background(), tc.channel) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -987,10 +1007,12 @@ func TestRemoveChannelHandler(t *testing.T) { } for _, tc := range cases { - repoCall := boot.On("RemoveChannel", context.Background(), mock.Anything).Return(tc.err) - err := svc.RemoveChannelHandler(context.Background(), tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + repoCall := boot.On("RemoveChannel", context.Background(), mock.Anything).Return(tc.err) + err := svc.RemoveChannelHandler(context.Background(), tc.id) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -1015,10 +1037,12 @@ func TestRemoveConfigHandler(t *testing.T) { } for _, tc := range cases { - repoCall := boot.On("RemoveThing", context.Background(), mock.Anything).Return(tc.err) - err := svc.RemoveConfigHandler(context.Background(), tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + repoCall := boot.On("RemoveThing", context.Background(), mock.Anything).Return(tc.err) + err := svc.RemoveConfigHandler(context.Background(), tc.id) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -1046,10 +1070,12 @@ func TestConnectThingsHandler(t *testing.T) { } for _, tc := range cases { - repoCall := boot.On("ConnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err) - err := svc.ConnectThingHandler(context.Background(), tc.channelID, tc.thingID) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + repoCall := boot.On("ConnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err) + err := svc.ConnectThingHandler(context.Background(), tc.channelID, tc.thingID) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } @@ -1077,9 +1103,11 @@ func TestDisconnectThingsHandler(t *testing.T) { } for _, tc := range cases { - repoCall := boot.On("DisconnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err) - err := svc.DisconnectThingHandler(context.Background(), tc.channelID, tc.thingID) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + repoCall := boot.On("DisconnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err) + err := svc.DisconnectThingHandler(context.Background(), tc.channelID, tc.thingID) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + repoCall.Unset() + }) } } diff --git a/certs/api/endpoint.go b/certs/api/endpoint.go index 9b88af4584..8e03f47281 100644 --- a/certs/api/endpoint.go +++ b/certs/api/endpoint.go @@ -18,7 +18,7 @@ func issueCert(svc certs.Service) endpoint.Endpoint { if err := req.validate(); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) } - res, err := svc.IssueCert(ctx, req.token, req.ThingID, req.TTL) + res, err := svc.IssueCert(ctx, req.domainID, req.token, req.ThingID, req.TTL) if err != nil { return certsRes{}, errors.Wrap(apiutil.ErrValidation, err) } @@ -97,7 +97,7 @@ func revokeCert(svc certs.Service) endpoint.Endpoint { if err := req.validate(); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) } - res, err := svc.RevokeCert(ctx, req.token, req.certID) + res, err := svc.RevokeCert(ctx, req.domainID, req.token, req.certID) if err != nil { return nil, err } diff --git a/certs/api/endpoint_test.go b/certs/api/endpoint_test.go index 5f3e6108be..6cc2c143bb 100644 --- a/certs/api/endpoint_test.go +++ b/certs/api/endpoint_test.go @@ -84,6 +84,7 @@ func TestIssueCert(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session contentType string @@ -99,6 +100,7 @@ func TestIssueCert(t *testing.T) { { desc: "issue cert successfully", token: valid, + domainID: valid, contentType: contentType, thingID: thingID, ttl: ttl, @@ -108,6 +110,19 @@ func TestIssueCert(t *testing.T) { svcErr: nil, err: nil, }, + { + desc: "issue cert with failed service", + token: valid, + domainID: valid, + contentType: contentType, + thingID: thingID, + ttl: ttl, + request: fmt.Sprintf(validReqString, thingID, ttl), + status: http.StatusUnprocessableEntity, + svcRes: certs.Cert{}, + svcErr: svcerr.ErrCreateEntity, + err: svcerr.ErrCreateEntity, + }, { desc: "issue with invalid token", token: invalid, @@ -122,7 +137,7 @@ func TestIssueCert(t *testing.T) { }, { desc: "issue with empty token", - token: "", + domainID: valid, contentType: contentType, request: fmt.Sprintf(validReqString, thingID, ttl), status: http.StatusUnauthorized, @@ -130,9 +145,21 @@ func TestIssueCert(t *testing.T) { svcErr: nil, err: apiutil.ErrBearerToken, }, + { + desc: "issue with empty domain id", + token: valid, + domainID: "", + contentType: contentType, + request: fmt.Sprintf(validReqString, thingID, ttl), + status: http.StatusBadRequest, + svcRes: certs.Cert{}, + svcErr: nil, + err: apiutil.ErrMissingDomainID, + }, { desc: "issue with empty thing id", token: valid, + domainID: valid, contentType: contentType, request: fmt.Sprintf(validReqString, "", ttl), status: http.StatusBadRequest, @@ -143,6 +170,7 @@ func TestIssueCert(t *testing.T) { { desc: "issue with empty ttl", token: valid, + domainID: valid, contentType: contentType, request: fmt.Sprintf(validReqString, thingID, ""), status: http.StatusBadRequest, @@ -153,6 +181,7 @@ func TestIssueCert(t *testing.T) { { desc: "issue with invalid ttl", token: valid, + domainID: valid, contentType: contentType, request: fmt.Sprintf(validReqString, thingID, invalid), status: http.StatusBadRequest, @@ -163,6 +192,7 @@ func TestIssueCert(t *testing.T) { { desc: "issue with invalid content type", token: valid, + domainID: valid, contentType: "application/xml", request: fmt.Sprintf(validReqString, thingID, ttl), status: http.StatusUnsupportedMediaType, @@ -173,6 +203,7 @@ func TestIssueCert(t *testing.T) { { desc: "issue with invalid request body", token: valid, + domainID: valid, contentType: contentType, request: fmt.Sprintf(invalidReqString, thingID, ttl), status: http.StatusInternalServerError, @@ -183,31 +214,33 @@ func TestIssueCert(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: cs.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/certs", cs.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.request), - } - if tc.token == valid { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("IssueCert", mock.Anything, tc.token, tc.thingID, tc.ttl).Return(tc.svcRes, tc.svcErr) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: cs.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/certs", cs.URL, tc.domainID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.request), + } + if tc.token == valid { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("IssueCert", mock.Anything, tc.domainID, tc.token, tc.thingID, tc.ttl).Return(tc.svcRes, tc.svcErr) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -217,6 +250,7 @@ func TestViewCert(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session serialID string @@ -230,6 +264,7 @@ func TestViewCert(t *testing.T) { { desc: "view cert successfully", token: valid, + domainID: valid, serialID: serial, status: http.StatusOK, svcRes: certs.Cert{SerialNumber: serial}, @@ -248,6 +283,7 @@ func TestViewCert(t *testing.T) { { desc: "view with empty token", token: "", + domainID: valid, serialID: serial, status: http.StatusUnauthorized, svcRes: certs.Cert{}, @@ -257,6 +293,7 @@ func TestViewCert(t *testing.T) { { desc: "view non-existing cert", token: valid, + domainID: valid, serialID: invalid, status: http.StatusNotFound, svcRes: certs.Cert{}, @@ -265,29 +302,31 @@ func TestViewCert(t *testing.T) { }, } for _, tc := range cases { - req := testRequest{ - client: cs.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/certs/%s", cs.URL, tc.serialID), - token: tc.token, - } - if tc.token == valid { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("ViewCert", mock.Anything, tc.serialID).Return(tc.svcRes, tc.svcErr) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: cs.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/certs/%s", cs.URL, tc.domainID, tc.serialID), + token: tc.token, + } + if tc.token == valid { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("ViewCert", mock.Anything, tc.serialID).Return(tc.svcRes, tc.svcErr) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -297,6 +336,7 @@ func TestRevokeCert(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session serialID string @@ -309,6 +349,7 @@ func TestRevokeCert(t *testing.T) { { desc: "revoke cert successfully", token: valid, + domainID: valid, serialID: serial, status: http.StatusOK, svcRes: certs.Revoke{RevocationTime: time.Now()}, @@ -324,9 +365,19 @@ func TestRevokeCert(t *testing.T) { authenticateErr: svcerr.ErrAuthentication, err: svcerr.ErrAuthentication, }, + { + desc: "revoke with empty domain id", + token: valid, + domainID: "", + serialID: serial, + status: http.StatusBadRequest, + svcErr: nil, + err: apiutil.ErrMissingDomainID, + }, { desc: "revoke with empty token", token: "", + domainID: valid, serialID: serial, status: http.StatusUnauthorized, svcErr: nil, @@ -335,6 +386,7 @@ func TestRevokeCert(t *testing.T) { { desc: "revoke non-existing cert", token: valid, + domainID: valid, serialID: invalid, status: http.StatusNotFound, svcRes: certs.Revoke{}, @@ -343,29 +395,31 @@ func TestRevokeCert(t *testing.T) { }, } for _, tc := range cases { - req := testRequest{ - client: cs.Client(), - method: http.MethodDelete, - url: fmt.Sprintf("%s/certs/%s", cs.URL, tc.serialID), - token: tc.token, - } - if tc.token == valid { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("RevokeCert", mock.Anything, tc.token, tc.serialID).Return(tc.svcRes, tc.svcErr) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: cs.Client(), + method: http.MethodDelete, + url: fmt.Sprintf("%s/%s/certs/%s", cs.URL, tc.domainID, tc.serialID), + token: tc.token, + } + if tc.token == valid { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("RevokeCert", mock.Anything, tc.domainID, tc.token, tc.serialID).Return(tc.svcRes, tc.svcErr) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -377,6 +431,7 @@ func TestListSerials(t *testing.T) { cases := []struct { desc string token string + domainID string session mgauthn.Session thingID string revoked string @@ -390,14 +445,15 @@ func TestListSerials(t *testing.T) { err error }{ { - desc: "list certs successfully with default limit", - token: valid, - thingID: thingID, - revoked: revoked, - offset: 0, - limit: 10, - query: "", - status: http.StatusOK, + desc: "list certs successfully with default limit", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + offset: 0, + limit: 10, + query: "", + status: http.StatusOK, svcRes: certs.CertPage{ Total: 1, Offset: 0, @@ -408,14 +464,15 @@ func TestListSerials(t *testing.T) { err: nil, }, { - desc: "list certs successfully with default revoke", - token: valid, - thingID: thingID, - revoked: revoked, - offset: 0, - limit: 10, - query: "", - status: http.StatusOK, + desc: "list certs successfully with default revoke", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + offset: 0, + limit: 10, + query: "", + status: http.StatusOK, svcRes: certs.CertPage{ Total: 1, Offset: 0, @@ -426,14 +483,15 @@ func TestListSerials(t *testing.T) { err: nil, }, { - desc: "list certs successfully with all certs", - token: valid, - thingID: thingID, - revoked: "all", - offset: 0, - limit: 10, - query: "?revoked=all", - status: http.StatusOK, + desc: "list certs successfully with all certs", + domainID: valid, + token: valid, + thingID: thingID, + revoked: "all", + offset: 0, + limit: 10, + query: "?revoked=all", + status: http.StatusOK, svcRes: certs.CertPage{ Total: 1, Offset: 0, @@ -444,14 +502,15 @@ func TestListSerials(t *testing.T) { err: nil, }, { - desc: "list certs successfully with limit", - token: valid, - thingID: thingID, - revoked: revoked, - offset: 0, - limit: 5, - query: "?limit=5", - status: http.StatusOK, + desc: "list certs successfully with limit", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + offset: 0, + limit: 5, + query: "?limit=5", + status: http.StatusOK, svcRes: certs.CertPage{ Total: 1, Offset: 0, @@ -462,14 +521,15 @@ func TestListSerials(t *testing.T) { err: nil, }, { - desc: "list certs successfully with offset", - token: valid, - thingID: thingID, - revoked: revoked, - offset: 1, - limit: 10, - query: "?offset=1", - status: http.StatusOK, + desc: "list certs successfully with offset", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + offset: 1, + limit: 10, + query: "?offset=1", + status: http.StatusOK, svcRes: certs.CertPage{ Total: 1, Offset: 1, @@ -480,14 +540,15 @@ func TestListSerials(t *testing.T) { err: nil, }, { - desc: "list certs successfully with offset and limit", - token: valid, - thingID: thingID, - revoked: revoked, - offset: 1, - limit: 5, - query: "?offset=1&limit=5", - status: http.StatusOK, + desc: "list certs successfully with offset and limit", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + offset: 1, + limit: 5, + query: "?offset=1&limit=5", + status: http.StatusOK, svcRes: certs.CertPage{ Total: 1, Offset: 1, @@ -499,6 +560,7 @@ func TestListSerials(t *testing.T) { }, { desc: "list with invalid token", + domainID: valid, token: invalid, thingID: thingID, revoked: revoked, @@ -511,89 +573,96 @@ func TestListSerials(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "list with empty token", - token: "", - thingID: thingID, - revoked: revoked, - offset: 0, - limit: 10, - query: "", - status: http.StatusUnauthorized, - svcRes: certs.CertPage{}, - svcErr: nil, - err: apiutil.ErrBearerToken, + desc: "list with empty token", + domainID: valid, + token: "", + thingID: thingID, + revoked: revoked, + offset: 0, + limit: 10, + query: "", + status: http.StatusUnauthorized, + svcRes: certs.CertPage{}, + svcErr: nil, + err: apiutil.ErrBearerToken, }, { - desc: "list with limit exceeding max limit", - token: valid, - thingID: thingID, - revoked: revoked, - query: "?limit=1000", - status: http.StatusBadRequest, - svcRes: certs.CertPage{}, - svcErr: nil, - err: apiutil.ErrLimitSize, + desc: "list with limit exceeding max limit", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + query: "?limit=1000", + status: http.StatusBadRequest, + svcRes: certs.CertPage{}, + svcErr: nil, + err: apiutil.ErrLimitSize, }, { - desc: "list with invalid offset", - token: valid, - thingID: thingID, - revoked: revoked, - query: "?offset=invalid", - status: http.StatusBadRequest, - svcRes: certs.CertPage{}, - svcErr: nil, - err: apiutil.ErrValidation, + desc: "list with invalid offset", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + query: "?offset=invalid", + status: http.StatusBadRequest, + svcRes: certs.CertPage{}, + svcErr: nil, + err: apiutil.ErrValidation, }, { - desc: "list with invalid limit", - token: valid, - thingID: thingID, - revoked: revoked, - query: "?limit=invalid", - status: http.StatusBadRequest, - svcRes: certs.CertPage{}, - svcErr: nil, - err: apiutil.ErrValidation, + desc: "list with invalid limit", + domainID: valid, + token: valid, + thingID: thingID, + revoked: revoked, + query: "?limit=invalid", + status: http.StatusBadRequest, + svcRes: certs.CertPage{}, + svcErr: nil, + err: apiutil.ErrValidation, }, { - desc: "list with invalid thing id", - token: valid, - thingID: invalid, - revoked: revoked, - offset: 0, - limit: 10, - query: "", - status: http.StatusNotFound, - svcRes: certs.CertPage{}, - svcErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, + desc: "list with invalid thing id", + domainID: valid, + token: valid, + thingID: invalid, + revoked: revoked, + offset: 0, + limit: 10, + query: "", + status: http.StatusNotFound, + svcRes: certs.CertPage{}, + svcErr: svcerr.ErrNotFound, + err: svcerr.ErrNotFound, }, } for _, tc := range cases { - req := testRequest{ - client: cs.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/serials/%s", cs.URL, tc.thingID) + tc.query, - token: tc.token, - } - if tc.token == valid { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("ListSerials", mock.Anything, tc.thingID, certs.PageMetadata{Revoked: tc.revoked, Offset: tc.offset, Limit: tc.limit}).Return(tc.svcRes, tc.svcErr) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: cs.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/serials/%s", cs.URL, tc.domainID, tc.thingID) + tc.query, + token: tc.token, + } + if tc.token == valid { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + } + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) + svcCall := svc.On("ListSerials", mock.Anything, tc.thingID, certs.PageMetadata{Revoked: tc.revoked, Offset: tc.offset, Limit: tc.limit}).Return(tc.svcRes, tc.svcErr) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } diff --git a/certs/api/logging.go b/certs/api/logging.go index 86a113f625..7a8c3b7d33 100644 --- a/certs/api/logging.go +++ b/certs/api/logging.go @@ -27,7 +27,7 @@ func LoggingMiddleware(svc certs.Service, logger *slog.Logger) certs.Service { // IssueCert logs the issue_cert request. It logs the ttl, thing ID and the time it took to complete the request. // If the request fails, it logs the error. -func (lm *loggingMiddleware) IssueCert(ctx context.Context, token, thingID, ttl string) (c certs.Cert, err error) { +func (lm *loggingMiddleware) IssueCert(ctx context.Context, domainID, token, thingID, ttl string) (c certs.Cert, err error) { defer func(begin time.Time) { args := []any{ slog.String("duration", time.Since(begin).String()), @@ -42,7 +42,7 @@ func (lm *loggingMiddleware) IssueCert(ctx context.Context, token, thingID, ttl lm.logger.Info("Issue certificate completed successfully", args...) }(time.Now()) - return lm.svc.IssueCert(ctx, token, thingID, ttl) + return lm.svc.IssueCert(ctx, domainID, token, thingID, ttl) } // ListCerts logs the list_certs request. It logs the thing ID and the time it took to complete the request. @@ -114,7 +114,7 @@ func (lm *loggingMiddleware) ViewCert(ctx context.Context, serialID string) (c c // RevokeCert logs the revoke_cert request. It logs the thing ID and the time it took to complete the request. // If the request fails, it logs the error. -func (lm *loggingMiddleware) RevokeCert(ctx context.Context, token, thingID string) (c certs.Revoke, err error) { +func (lm *loggingMiddleware) RevokeCert(ctx context.Context, domainID, token, thingID string) (c certs.Revoke, err error) { defer func(begin time.Time) { args := []any{ slog.String("duration", time.Since(begin).String()), @@ -128,5 +128,5 @@ func (lm *loggingMiddleware) RevokeCert(ctx context.Context, token, thingID stri lm.logger.Info("Revoke certificate completed successfully", args...) }(time.Now()) - return lm.svc.RevokeCert(ctx, token, thingID) + return lm.svc.RevokeCert(ctx, domainID, token, thingID) } diff --git a/certs/api/metrics.go b/certs/api/metrics.go index fee094753a..9f78fd012c 100644 --- a/certs/api/metrics.go +++ b/certs/api/metrics.go @@ -31,13 +31,13 @@ func MetricsMiddleware(svc certs.Service, counter metrics.Counter, latency metri } // IssueCert instruments IssueCert method with metrics. -func (ms *metricsMiddleware) IssueCert(ctx context.Context, token, thingID, ttl string) (certs.Cert, error) { +func (ms *metricsMiddleware) IssueCert(ctx context.Context, domainID, token, thingID, ttl string) (certs.Cert, error) { defer func(begin time.Time) { ms.counter.With("method", "issue_cert").Add(1) ms.latency.With("method", "issue_cert").Observe(time.Since(begin).Seconds()) }(time.Now()) - return ms.svc.IssueCert(ctx, token, thingID, ttl) + return ms.svc.IssueCert(ctx, domainID, token, thingID, ttl) } // ListCerts instruments ListCerts method with metrics. @@ -71,11 +71,11 @@ func (ms *metricsMiddleware) ViewCert(ctx context.Context, serialID string) (cer } // RevokeCert instruments RevokeCert method with metrics. -func (ms *metricsMiddleware) RevokeCert(ctx context.Context, token, thingID string) (certs.Revoke, error) { +func (ms *metricsMiddleware) RevokeCert(ctx context.Context, domainID, token, thingID string) (certs.Revoke, error) { defer func(begin time.Time) { ms.counter.With("method", "revoke_cert").Add(1) ms.latency.With("method", "revoke_cert").Observe(time.Since(begin).Seconds()) }(time.Now()) - return ms.svc.RevokeCert(ctx, token, thingID) + return ms.svc.RevokeCert(ctx, domainID, token, thingID) } diff --git a/certs/api/requests.go b/certs/api/requests.go index 68725d4b00..54bea166bd 100644 --- a/certs/api/requests.go +++ b/certs/api/requests.go @@ -13,9 +13,10 @@ import ( const maxLimitSize = 100 type addCertsReq struct { - token string - ThingID string `json:"thing_id"` - TTL string `json:"ttl"` + token string + domainID string + ThingID string `json:"thing_id"` + TTL string `json:"ttl"` } func (req addCertsReq) validate() error { @@ -23,6 +24,10 @@ func (req addCertsReq) validate() error { return apiutil.ErrBearerToken } + if req.domainID == "" { + return apiutil.ErrMissingDomainID + } + if req.ThingID == "" { return apiutil.ErrMissingID } @@ -47,6 +52,7 @@ func (req *listReq) validate() error { if req.pm.Limit > maxLimitSize { return apiutil.ErrLimitSize } + return nil } @@ -63,8 +69,9 @@ func (req *viewReq) validate() error { } type revokeReq struct { - token string - certID string + token string + certID string + domainID string } func (req *revokeReq) validate() error { @@ -72,6 +79,10 @@ func (req *revokeReq) validate() error { return apiutil.ErrBearerToken } + if req.domainID == "" { + return apiutil.ErrMissingDomainID + } + if req.certID == "" { return apiutil.ErrMissingID } diff --git a/certs/api/transport.go b/certs/api/transport.go index c7e4f86ebe..8acc34a564 100644 --- a/certs/api/transport.go +++ b/certs/api/transport.go @@ -41,35 +41,35 @@ func MakeHandler(svc certs.Service, authn mgauthn.Authentication, logger *slog.L r.Group(func(r chi.Router) { r.Use(api.AuthenticateMiddleware(authn)) - - r.Route("/certs", func(r chi.Router) { - r.Post("/", otelhttp.NewHandler(kithttp.NewServer( - issueCert(svc), - decodeCerts, - api.EncodeResponse, - opts..., - ), "issue").ServeHTTP) - r.Get("/{certID}", otelhttp.NewHandler(kithttp.NewServer( - viewCert(svc), - decodeViewCert, + r.Route("/{domainID}", func(r chi.Router) { + r.Route("/certs", func(r chi.Router) { + r.Post("/", otelhttp.NewHandler(kithttp.NewServer( + issueCert(svc), + decodeCerts, + api.EncodeResponse, + opts..., + ), "issue").ServeHTTP) + r.Get("/{certID}", otelhttp.NewHandler(kithttp.NewServer( + viewCert(svc), + decodeViewCert, + api.EncodeResponse, + opts..., + ), "view").ServeHTTP) + r.Delete("/{certID}", otelhttp.NewHandler(kithttp.NewServer( + revokeCert(svc), + decodeRevokeCerts, + api.EncodeResponse, + opts..., + ), "revoke").ServeHTTP) + }) + r.Get("/serials/{thingID}", otelhttp.NewHandler(kithttp.NewServer( + listSerials(svc), + decodeListCerts, api.EncodeResponse, opts..., - ), "view").ServeHTTP) - r.Delete("/{certID}", otelhttp.NewHandler(kithttp.NewServer( - revokeCert(svc), - decodeRevokeCerts, - api.EncodeResponse, - opts..., - ), "revoke").ServeHTTP) + ), "list_serials").ServeHTTP) }) - r.Get("/serials/{thingID}", otelhttp.NewHandler(kithttp.NewServer( - listSerials(svc), - decodeListCerts, - api.EncodeResponse, - opts..., - ), "list_serials").ServeHTTP) }) - r.Handle("/metrics", promhttp.Handler()) r.Get("/health", magistrala.Health("certs", instanceID)) @@ -114,7 +114,10 @@ func decodeCerts(_ context.Context, r *http.Request) (interface{}, error) { return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) } - req := addCertsReq{token: apiutil.ExtractBearerToken(r)} + req := addCertsReq{ + token: apiutil.ExtractBearerToken(r), + domainID: chi.URLParam(r, "domainID"), + } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) } @@ -124,8 +127,9 @@ func decodeCerts(_ context.Context, r *http.Request) (interface{}, error) { func decodeRevokeCerts(_ context.Context, r *http.Request) (interface{}, error) { req := revokeReq{ - token: apiutil.ExtractBearerToken(r), - certID: chi.URLParam(r, "certID"), + token: apiutil.ExtractBearerToken(r), + certID: chi.URLParam(r, "certID"), + domainID: chi.URLParam(r, "domainID"), } return req, nil diff --git a/certs/mocks/service.go b/certs/mocks/service.go index e16203e9e4..864f3e28dd 100644 --- a/certs/mocks/service.go +++ b/certs/mocks/service.go @@ -17,9 +17,9 @@ type Service struct { mock.Mock } -// IssueCert provides a mock function with given fields: ctx, token, thingID, ttl -func (_m *Service) IssueCert(ctx context.Context, token string, thingID string, ttl string) (certs.Cert, error) { - ret := _m.Called(ctx, token, thingID, ttl) +// IssueCert provides a mock function with given fields: ctx, domainID, token, thingID, ttl +func (_m *Service) IssueCert(ctx context.Context, domainID string, token string, thingID string, ttl string) (certs.Cert, error) { + ret := _m.Called(ctx, domainID, token, thingID, ttl) if len(ret) == 0 { panic("no return value specified for IssueCert") @@ -27,17 +27,17 @@ func (_m *Service) IssueCert(ctx context.Context, token string, thingID string, var r0 certs.Cert var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, string) (certs.Cert, error)); ok { - return rf(ctx, token, thingID, ttl) + if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string) (certs.Cert, error)); ok { + return rf(ctx, domainID, token, thingID, ttl) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, string) certs.Cert); ok { - r0 = rf(ctx, token, thingID, ttl) + if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string) certs.Cert); ok { + r0 = rf(ctx, domainID, token, thingID, ttl) } else { r0 = ret.Get(0).(certs.Cert) } - if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok { - r1 = rf(ctx, token, thingID, ttl) + if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string) error); ok { + r1 = rf(ctx, domainID, token, thingID, ttl) } else { r1 = ret.Error(1) } @@ -101,9 +101,9 @@ func (_m *Service) ListSerials(ctx context.Context, thingID string, pm certs.Pag return r0, r1 } -// RevokeCert provides a mock function with given fields: ctx, token, thingID -func (_m *Service) RevokeCert(ctx context.Context, token string, thingID string) (certs.Revoke, error) { - ret := _m.Called(ctx, token, thingID) +// RevokeCert provides a mock function with given fields: ctx, domainID, token, thingID +func (_m *Service) RevokeCert(ctx context.Context, domainID string, token string, thingID string) (certs.Revoke, error) { + ret := _m.Called(ctx, domainID, token, thingID) if len(ret) == 0 { panic("no return value specified for RevokeCert") @@ -111,17 +111,17 @@ func (_m *Service) RevokeCert(ctx context.Context, token string, thingID string) var r0 certs.Revoke var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) (certs.Revoke, error)); ok { - return rf(ctx, token, thingID) + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) (certs.Revoke, error)); ok { + return rf(ctx, domainID, token, thingID) } - if rf, ok := ret.Get(0).(func(context.Context, string, string) certs.Revoke); ok { - r0 = rf(ctx, token, thingID) + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) certs.Revoke); ok { + r0 = rf(ctx, domainID, token, thingID) } else { r0 = ret.Get(0).(certs.Revoke) } - if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { - r1 = rf(ctx, token, thingID) + if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok { + r1 = rf(ctx, domainID, token, thingID) } else { r1 = ret.Error(1) } diff --git a/certs/service.go b/certs/service.go index 354b717def..d5e3980537 100644 --- a/certs/service.go +++ b/certs/service.go @@ -34,7 +34,7 @@ var _ Service = (*certsService)(nil) //go:generate mockery --name Service --output=./mocks --filename service.go --quiet --note "Copyright (c) Abstract Machines" type Service interface { // IssueCert issues certificate for given thing id if access is granted with token - IssueCert(ctx context.Context, token, thingID, ttl string) (Cert, error) + IssueCert(ctx context.Context, domainID, token, thingID, ttl string) (Cert, error) // ListCerts lists certificates issued for a given thing ID ListCerts(ctx context.Context, thingID string, pm PageMetadata) (CertPage, error) @@ -46,7 +46,7 @@ type Service interface { ViewCert(ctx context.Context, serialID string) (Cert, error) // RevokeCert revokes a certificate for a given thing ID - RevokeCert(ctx context.Context, token, thingID string) (Revoke, error) + RevokeCert(ctx context.Context, domainID, token, thingID string) (Revoke, error) } type certsService struct { @@ -67,10 +67,10 @@ type Revoke struct { RevocationTime time.Time `mapstructure:"revocation_time"` } -func (cs *certsService) IssueCert(ctx context.Context, token, thingID, ttl string) (Cert, error) { +func (cs *certsService) IssueCert(ctx context.Context, domainID, token, thingID, ttl string) (Cert, error) { var err error - thing, err := cs.sdk.Thing(thingID, token) + thing, err := cs.sdk.Thing(thingID, domainID, token) if err != nil { return Cert{}, errors.Wrap(ErrFailedCertCreation, err) } @@ -90,11 +90,11 @@ func (cs *certsService) IssueCert(ctx context.Context, token, thingID, ttl strin }, err } -func (cs *certsService) RevokeCert(ctx context.Context, token, thingID string) (Revoke, error) { +func (cs *certsService) RevokeCert(ctx context.Context, domainID, token, thingID string) (Revoke, error) { var revoke Revoke var err error - thing, err := cs.sdk.Thing(thingID, token) + thing, err := cs.sdk.Thing(thingID, domainID, token) if err != nil { return revoke, errors.Wrap(ErrFailedCertRevocation, err) } diff --git a/certs/service_test.go b/certs/service_test.go index a5750ff267..fa0c774e9c 100644 --- a/certs/service_test.go +++ b/certs/service_test.go @@ -23,6 +23,7 @@ import ( const ( invalid = "invalid" email = "user@example.com" + domain = "domain" token = "token" thingsNum = 1 thingKey = "thingKey" @@ -49,6 +50,7 @@ var cert = mgcrt.Cert{ func TestIssueCert(t *testing.T) { svc, agent, sdk := newService(t) cases := []struct { + domainID string token string desc string thingID string @@ -61,15 +63,17 @@ func TestIssueCert(t *testing.T) { err error }{ { - desc: "issue new cert", - token: token, - thingID: thingID, - ttl: ttl, - ipAddr: []string{}, - cert: cert, + desc: "issue new cert", + domainID: domain, + token: token, + thingID: thingID, + ttl: ttl, + ipAddr: []string{}, + cert: cert, }, { desc: "issue new for failed pki", + domainID: domain, token: token, thingID: thingID, ttl: ttl, @@ -80,6 +84,7 @@ func TestIssueCert(t *testing.T) { }, { desc: "issue new cert for non existing thing id", + domainID: domain, token: token, thingID: "2", ttl: ttl, @@ -89,6 +94,7 @@ func TestIssueCert(t *testing.T) { }, { desc: "issue new cert for invalid token", + domainID: domain, token: invalid, thingID: thingID, ttl: ttl, @@ -100,9 +106,9 @@ func TestIssueCert(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdk.On("Thing", tc.thingID, tc.token).Return(mgsdk.Thing{ID: tc.thingID, Credentials: mgsdk.Credentials{Secret: thingKey}}, tc.thingErr) + sdkCall := sdk.On("Thing", tc.thingID, tc.domainID, tc.token).Return(mgsdk.Thing{ID: tc.thingID, Credentials: mgsdk.Credentials{Secret: thingKey}}, tc.thingErr) agentCall := agent.On("Issue", thingID, tc.ttl, tc.ipAddr).Return(tc.cert, tc.issueCertErr) - resp, err := svc.IssueCert(context.Background(), tc.token, tc.thingID, tc.ttl) + resp, err := svc.IssueCert(context.Background(), tc.domainID, tc.token, tc.thingID, tc.ttl) 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.cert.SerialNumber, resp.SerialNumber, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.cert.SerialNumber, resp.SerialNumber)) sdkCall.Unset() @@ -114,6 +120,7 @@ func TestIssueCert(t *testing.T) { func TestRevokeCert(t *testing.T) { svc, agent, sdk := newService(t) cases := []struct { + domainID string token string desc string thingID string @@ -125,13 +132,15 @@ func TestRevokeCert(t *testing.T) { err error }{ { - desc: "revoke cert", - token: token, - thingID: thingID, - page: mgcrt.CertPage{Limit: 10000, Offset: 0, Total: 1, Certificates: []mgcrt.Cert{cert}}, + desc: "revoke cert", + domainID: domain, + token: token, + thingID: thingID, + page: mgcrt.CertPage{Limit: 10000, Offset: 0, Total: 1, Certificates: []mgcrt.Cert{cert}}, }, { desc: "revoke cert for failed pki revoke", + domainID: domain, token: token, thingID: thingID, page: mgcrt.CertPage{Limit: 10000, Offset: 0, Total: 1, Certificates: []mgcrt.Cert{cert}}, @@ -140,6 +149,7 @@ func TestRevokeCert(t *testing.T) { }, { desc: "revoke cert for invalid thing id", + domainID: domain, token: token, thingID: "2", page: mgcrt.CertPage{}, @@ -147,21 +157,22 @@ func TestRevokeCert(t *testing.T) { err: certs.ErrFailedCertRevocation, }, { - desc: "revoke cert with failed to list certs", - token: token, - thingID: thingID, - page: mgcrt.CertPage{}, - listErr: certs.ErrFailedCertRevocation, - err: certs.ErrFailedCertRevocation, + desc: "revoke cert with failed to list certs", + domainID: domain, + token: token, + thingID: thingID, + page: mgcrt.CertPage{}, + listErr: certs.ErrFailedCertRevocation, + err: certs.ErrFailedCertRevocation, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdk.On("Thing", tc.thingID, tc.token).Return(mgsdk.Thing{ID: tc.thingID, Credentials: mgsdk.Credentials{Secret: thingKey}}, tc.thingErr) + sdkCall := sdk.On("Thing", tc.thingID, tc.domainID, tc.token).Return(mgsdk.Thing{ID: tc.thingID, Credentials: mgsdk.Credentials{Secret: thingKey}}, tc.thingErr) agentCall := agent.On("Revoke", mock.Anything).Return(tc.revokeErr) agentCall1 := agent.On("ListCerts", mock.Anything).Return(tc.page, tc.listErr) - _, err := svc.RevokeCert(context.Background(), tc.token, tc.thingID) + _, err := svc.RevokeCert(context.Background(), tc.domainID, tc.token, tc.thingID) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) sdkCall.Unset() agentCall.Unset() diff --git a/certs/tracing/tracing.go b/certs/tracing/tracing.go index cf8604a89b..48a0173dfe 100644 --- a/certs/tracing/tracing.go +++ b/certs/tracing/tracing.go @@ -24,14 +24,14 @@ func New(svc certs.Service, tracer trace.Tracer) certs.Service { } // IssueCert traces the "IssueCert" operation of the wrapped certs.Service. -func (tm *tracingMiddleware) IssueCert(ctx context.Context, token, thingID, ttl string) (certs.Cert, error) { +func (tm *tracingMiddleware) IssueCert(ctx context.Context, domainID, token, thingID, ttl string) (certs.Cert, error) { ctx, span := tm.tracer.Start(ctx, "svc_create_group", trace.WithAttributes( attribute.String("thing_id", thingID), attribute.String("ttl", ttl), )) defer span.End() - return tm.svc.IssueCert(ctx, token, thingID, ttl) + return tm.svc.IssueCert(ctx, domainID, token, thingID, ttl) } // ListCerts traces the "ListCerts" operation of the wrapped certs.Service. @@ -69,11 +69,11 @@ func (tm *tracingMiddleware) ViewCert(ctx context.Context, serialID string) (cer } // RevokeCert traces the "RevokeCert" operation of the wrapped certs.Service. -func (tm *tracingMiddleware) RevokeCert(ctx context.Context, token, serialID string) (certs.Revoke, error) { +func (tm *tracingMiddleware) RevokeCert(ctx context.Context, domainID, token, serialID string) (certs.Revoke, error) { ctx, span := tm.tracer.Start(ctx, "svc_revoke_cert", trace.WithAttributes( attribute.String("serial_id", serialID), )) defer span.End() - return tm.svc.RevokeCert(ctx, token, serialID) + return tm.svc.RevokeCert(ctx, domainID, token, serialID) } diff --git a/cli/bootstrap.go b/cli/bootstrap.go index 4961bd81f4..2e145b997a 100644 --- a/cli/bootstrap.go +++ b/cli/bootstrap.go @@ -12,11 +12,11 @@ import ( var cmdBootstrap = []cobra.Command{ { - Use: "create ", + Use: "create ", Short: "Create config", Long: `Create new Thing Bootstrap Config to the user identified by the provided key`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -27,7 +27,7 @@ var cmdBootstrap = []cobra.Command{ return } - id, err := sdk.AddBootstrap(cfg, args[1]) + id, err := sdk.AddBootstrap(cfg, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -37,24 +37,25 @@ var cmdBootstrap = []cobra.Command{ }, }, { - Use: "get [all | ] ", + Use: "get [all | ] ", Short: "Get config", Long: `Get Thing Config with given ID belonging to the user identified by the given key. all - lists all config - view config of `, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pageMetadata := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, - State: State, - Name: Name, + Offset: Offset, + Limit: Limit, + State: State, + Name: Name, + DomainID: args[1], } if args[0] == "all" { - l, err := sdk.Bootstraps(pageMetadata, args[1]) + l, err := sdk.Bootstraps(pageMetadata, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -63,7 +64,7 @@ var cmdBootstrap = []cobra.Command{ return } - c, err := sdk.ViewBootstrap(args[0], args[1]) + c, err := sdk.ViewBootstrap(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -73,7 +74,7 @@ var cmdBootstrap = []cobra.Command{ }, }, { - Use: "update [config | connection | certs ] ", + Use: "update [config | connection | certs ] ", Short: "Update config", Long: `Updates editable fields of the provided Config. config - Updates editable fields of the provided Config. @@ -81,7 +82,7 @@ var cmdBootstrap = []cobra.Command{ channel_ids - '["channel_id1", ...]' certs - Update bootstrap config certificates.`, Run: func(cmd *cobra.Command, args []string) { - if len(args) < 3 { + if len(args) < 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -92,7 +93,7 @@ var cmdBootstrap = []cobra.Command{ return } - if err := sdk.UpdateBootstrap(cfg, args[1]); err != nil { + if err := sdk.UpdateBootstrap(cfg, args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } @@ -106,7 +107,7 @@ var cmdBootstrap = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.UpdateBootstrapConnection(args[1], ids, args[3]); err != nil { + if err := sdk.UpdateBootstrapConnection(args[1], ids, args[3], args[4]); err != nil { logErrorCmd(*cmd, err) return } @@ -115,7 +116,7 @@ var cmdBootstrap = []cobra.Command{ return } if args[0] == "certs" { - cfg, err := sdk.UpdateBootstrapCerts(args[0], args[1], args[2], args[3], args[4]) + cfg, err := sdk.UpdateBootstrapCerts(args[0], args[1], args[2], args[3], args[4], args[5]) if err != nil { logErrorCmd(*cmd, err) return @@ -128,16 +129,16 @@ var cmdBootstrap = []cobra.Command{ }, }, { - Use: "remove ", + Use: "remove ", Short: "Remove config", Long: `Removes Config with specified key that belongs to the user identified by the given key`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - if err := sdk.RemoveBootstrap(args[0], args[1]); err != nil { + if err := sdk.RemoveBootstrap(args[0], args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } @@ -175,11 +176,11 @@ var cmdBootstrap = []cobra.Command{ }, }, { - Use: "whitelist ", + Use: "whitelist ", Short: "Whitelist config", Long: `Whitelist updates thing state config with given id from the authenticated user`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -190,7 +191,7 @@ var cmdBootstrap = []cobra.Command{ return } - if err := sdk.Whitelist(cfg.ThingID, cfg.State, args[1]); err != nil { + if err := sdk.Whitelist(cfg.ThingID, cfg.State, args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } diff --git a/cli/bootstrap_test.go b/cli/bootstrap_test.go index a6024377d7..b954034644 100644 --- a/cli/bootstrap_test.go +++ b/cli/bootstrap_test.go @@ -48,6 +48,7 @@ func TestCreateBootstrapConfigCmd(t *testing.T) { desc: "create bootstrap config successfully", args: []string{ jsonConfig, + domainID, validToken, }, logType: createLog, @@ -58,6 +59,7 @@ func TestCreateBootstrapConfigCmd(t *testing.T) { desc: "create bootstrap config with invald args", args: []string{ jsonConfig, + domainID, validToken, extraArg, }, @@ -67,6 +69,7 @@ func TestCreateBootstrapConfigCmd(t *testing.T) { desc: "create bootstrap config with invald json", args: []string{ invalidJson, + domainID, validToken, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -77,6 +80,7 @@ func TestCreateBootstrapConfigCmd(t *testing.T) { desc: "create bootstrap config with invald token", args: []string{ jsonConfig, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -87,7 +91,7 @@ func TestCreateBootstrapConfigCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("AddBootstrap", mock.Anything, mock.Anything).Return(tc.id, tc.sdkErr) + sdkCall := sdkMock.On("AddBootstrap", mock.Anything, mock.Anything, mock.Anything).Return(tc.id, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{createCmd}, tc.args...)...) switch tc.logType { @@ -125,6 +129,7 @@ func TestGetBootstrapConfigCmd(t *testing.T) { desc: "get all bootstrap config successfully", args: []string{ all, + domainID, token, }, page: mgsdk.BootstrapPage{ @@ -141,6 +146,7 @@ func TestGetBootstrapConfigCmd(t *testing.T) { desc: "get bootstrap config with id", args: []string{ channel.ID, + domainID, token, }, logType: entityLog, @@ -150,6 +156,7 @@ func TestGetBootstrapConfigCmd(t *testing.T) { desc: "get bootstrap config with invalid args", args: []string{ all, + domainID, token, extraArg, }, @@ -159,6 +166,7 @@ func TestGetBootstrapConfigCmd(t *testing.T) { desc: "get all bootstrap config with invalid token", args: []string{ all, + domainID, invalidToken, }, logType: errLog, @@ -169,6 +177,7 @@ func TestGetBootstrapConfigCmd(t *testing.T) { desc: "get bootstrap config with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -179,8 +188,8 @@ func TestGetBootstrapConfigCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ViewBootstrap", tc.args[0], tc.args[1]).Return(tc.boot, tc.sdkErr) - sdkCall1 := sdkMock.On("Bootstraps", mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ViewBootstrap", tc.args[0], tc.args[1], tc.args[2]).Return(tc.boot, tc.sdkErr) + sdkCall1 := sdkMock.On("Bootstraps", mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) @@ -223,6 +232,7 @@ func TestRemoveBootstrapConfigCmd(t *testing.T) { desc: "remove bootstrap config successfully", args: []string{ thing.ID, + domainID, token, }, logType: okLog, @@ -231,6 +241,7 @@ func TestRemoveBootstrapConfigCmd(t *testing.T) { desc: "remove bootstrap config with invalid args", args: []string{ thing.ID, + domainID, token, extraArg, }, @@ -240,6 +251,7 @@ func TestRemoveBootstrapConfigCmd(t *testing.T) { desc: "remove bootstrap config with invalid thing id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -250,6 +262,7 @@ func TestRemoveBootstrapConfigCmd(t *testing.T) { desc: "remove bootstrap config with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -260,7 +273,7 @@ func TestRemoveBootstrapConfigCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("RemoveBootstrap", tc.args[0], tc.args[1]).Return(tc.sdkErr) + sdkCall := sdkMock.On("RemoveBootstrap", tc.args[0], tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{rmCmd}, tc.args...)...) switch tc.logType { @@ -300,6 +313,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { args: []string{ config, newConfigJson, + domainID, token, }, logType: okLog, @@ -309,6 +323,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { args: []string{ config, newConfigJson, + domainID, invalidToken, }, logType: errLog, @@ -321,6 +336,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { connection, thing.ID, chanIDsJson, + domainID, token, }, logType: okLog, @@ -331,6 +347,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { connection, thing.ID, fmt.Sprintf("[\"%s\"", thing.ID), + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -343,6 +360,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { connection, thing.ID, chanIDsJson, + domainID, invalidToken, }, logType: errLog, @@ -357,6 +375,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { "client cert", "client key", "ca", + domainID, token, }, boot: bootConfig, @@ -370,6 +389,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { "client cert", "client key", "ca", + domainID, invalidToken, }, logType: errLog, @@ -380,6 +400,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { desc: "update bootstrap config with invalid args", args: []string{ newConfigJson, + domainID, token, }, logType: usageLog, @@ -389,6 +410,7 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { args: []string{ config, "{\"name\" : \"New Bootstrap\"", + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -410,9 +432,9 @@ func TestUpdateBootstrapConfigCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var boot mgsdk.BootstrapConfig - sdkCall := sdkMock.On("UpdateBootstrap", mock.Anything, mock.Anything).Return(tc.sdkErr) - sdkCall1 := sdkMock.On("UpdateBootstrapConnection", mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) - sdkCall2 := sdkMock.On("UpdateBootstrapCerts", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) + sdkCall := sdkMock.On("UpdateBootstrap", mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) + sdkCall1 := sdkMock.On("UpdateBootstrapConnection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) + sdkCall2 := sdkMock.On("UpdateBootstrapCerts", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{updCmd}, tc.args...)...) switch tc.logType { @@ -453,6 +475,7 @@ func TestWhitelistConfigCmd(t *testing.T) { desc: "whitelist config successfully", args: []string{ jsonConfig, + domainID, validToken, }, logType: okLog, @@ -461,6 +484,7 @@ func TestWhitelistConfigCmd(t *testing.T) { desc: "whitelist config with invalid args", args: []string{ jsonConfig, + domainID, validToken, extraArg, }, @@ -470,6 +494,7 @@ func TestWhitelistConfigCmd(t *testing.T) { desc: "whitelist config with invalid json", args: []string{ fmt.Sprintf("{\"thing_id\": \"%s\", \"state\":%d", thing.ID, 1), + domainID, validToken, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -480,6 +505,7 @@ func TestWhitelistConfigCmd(t *testing.T) { desc: "whitelist config with invalid token", args: []string{ jsonConfig, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -490,7 +516,7 @@ func TestWhitelistConfigCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Whitelist", mock.Anything, mock.Anything, tc.args[1]).Return(tc.sdkErr) + sdkCall := sdkMock.On("Whitelist", mock.Anything, mock.Anything, tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{whitelistCmd}, tc.args...)...) switch tc.logType { case okLog: diff --git a/cli/certs.go b/cli/certs.go index bd38a36aa5..988e0c20e8 100644 --- a/cli/certs.go +++ b/cli/certs.go @@ -9,16 +9,16 @@ import ( var cmdCerts = []cobra.Command{ { - Use: "get [ | thing ] ", + Use: "get [ | thing ] ", Short: "Get certificate", Long: `Gets a certificate for a given cert ID.`, Run: func(cmd *cobra.Command, args []string) { - if len(args) < 2 { + if len(args) < 3 { logUsageCmd(*cmd, cmd.Use) return } if args[0] == "thing" { - cert, err := sdk.ViewCertByThing(args[1], args[2]) + cert, err := sdk.ViewCertByThing(args[1], args[2], args[3]) if err != nil { logErrorCmd(*cmd, err) return @@ -26,7 +26,7 @@ var cmdCerts = []cobra.Command{ logJSONCmd(*cmd, cert) return } - cert, err := sdk.ViewCert(args[0], args[1]) + cert, err := sdk.ViewCert(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -35,15 +35,15 @@ var cmdCerts = []cobra.Command{ }, }, { - Use: "revoke ", + Use: "revoke ", Short: "Revoke certificate", Long: `Revokes a certificate for a given thing ID.`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - rtime, err := sdk.RevokeCert(args[0], args[1]) + rtime, err := sdk.RevokeCert(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -58,18 +58,18 @@ func NewCertsCmd() *cobra.Command { var ttl string issueCmd := cobra.Command{ - Use: "issue [--ttl=8760h]", + Use: "issue [--ttl=8760h]", Short: "Issue certificate", Long: `Issues new certificate for a thing`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } thingID := args[0] - c, err := sdk.IssueCert(thingID, ttl, args[1]) + c, err := sdk.IssueCert(thingID, ttl, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return diff --git a/cli/certs_test.go b/cli/certs_test.go index 962d350415..efc057c107 100644 --- a/cli/certs_test.go +++ b/cli/certs_test.go @@ -47,6 +47,7 @@ func TestGetCertCmd(t *testing.T) { args: []string{ "thing", thing.ID, + domainID, validToken, }, logType: entityLog, @@ -63,6 +64,7 @@ func TestGetCertCmd(t *testing.T) { desc: "get cert successfully by id", args: []string{ thing.ID, + domainID, validToken, }, logType: entityLog, @@ -73,6 +75,7 @@ func TestGetCertCmd(t *testing.T) { args: []string{ "thing", thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -83,6 +86,7 @@ func TestGetCertCmd(t *testing.T) { desc: "get cert by id with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -100,8 +104,8 @@ func TestGetCertCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ViewCertByThing", mock.Anything, mock.Anything).Return(tc.serials, tc.sdkErr) - sdkCall1 := sdkMock.On("ViewCert", mock.Anything, mock.Anything).Return(tc.cert, tc.sdkErr) + sdkCall := sdkMock.On("ViewCertByThing", mock.Anything, mock.Anything, mock.Anything).Return(tc.serials, tc.sdkErr) + sdkCall1 := sdkMock.On("ViewCert", mock.Anything, mock.Anything, mock.Anything).Return(tc.cert, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) switch tc.logType { case entityLog: @@ -147,6 +151,7 @@ func TestRevokeCertCmd(t *testing.T) { desc: "revoke cert successfully", args: []string{ thing.ID, + domainID, token, }, logType: revokeLog, @@ -157,6 +162,7 @@ func TestRevokeCertCmd(t *testing.T) { desc: "revoke cert with invalid args", args: []string{ thing.ID, + domainID, token, extraArg, }, @@ -166,6 +172,7 @@ func TestRevokeCertCmd(t *testing.T) { desc: "revoke cert with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -176,7 +183,7 @@ func TestRevokeCertCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("RevokeCert", tc.args[0], tc.args[1]).Return(tc.time, tc.sdkErr) + sdkCall := sdkMock.On("RevokeCert", tc.args[0], tc.args[1], tc.args[2]).Return(tc.time, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{revokeCmd}, tc.args...)...) switch tc.logType { @@ -215,6 +222,7 @@ func TestIssueCertCmd(t *testing.T) { desc: "issue cert successfully", args: []string{ thing.ID, + domainID, validToken, }, cert: cert, @@ -224,6 +232,7 @@ func TestIssueCertCmd(t *testing.T) { desc: "issue cert with invalid args", args: []string{ thing.ID, + domainID, validToken, extraArg, }, @@ -233,6 +242,7 @@ func TestIssueCertCmd(t *testing.T) { desc: "issue cert with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, logType: errLog, @@ -243,7 +253,7 @@ func TestIssueCertCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("IssueCert", mock.Anything, mock.Anything, tc.args[1]).Return(tc.cert, tc.sdkErr) + sdkCall := sdkMock.On("IssueCert", mock.Anything, mock.Anything, tc.args[1], tc.args[2]).Return(tc.cert, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{issueCmd}, tc.args...)...) switch tc.logType { diff --git a/cli/channels.go b/cli/channels.go index 83ea3e2ef5..2a74f9ba2d 100644 --- a/cli/channels.go +++ b/cli/channels.go @@ -14,11 +14,11 @@ const all = "all" var cmdChannels = []cobra.Command{ { - Use: "create ", + Use: "create ", Short: "Create channel", Long: `Creates new channel and generates it's UUID`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -29,7 +29,7 @@ var cmdChannels = []cobra.Command{ return } - channel, err := sdk.CreateChannel(channel, args[1]) + channel, err := sdk.CreateChannel(channel, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -39,14 +39,14 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "get [all | ] ", + Use: "get [all | ] ", Short: "Get channel", Long: `Get all channels or get channel by id. Channels can be filtered by name or metadata. all - lists all channels - shows thing with provided `, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -63,7 +63,7 @@ var cmdChannels = []cobra.Command{ } if args[0] == all { - l, err := sdk.Channels(pageMetadata, args[1]) + l, err := sdk.Channels(pageMetadata, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -72,7 +72,7 @@ var cmdChannels = []cobra.Command{ logJSONCmd(*cmd, l) return } - c, err := sdk.Channel(args[0], args[1]) + c, err := sdk.Channel(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -82,17 +82,17 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "delete ", + Use: "delete ", Short: "Delete channel", Long: "Delete channel by id.\n" + "Usage:\n" + - "\tmagistrala-cli channels delete $USERTOKEN - delete the given channel ID\n", + "\tmagistrala-cli channels delete $DOMAINID $USERTOKEN - delete the given channel ID\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - if err := sdk.DeleteChannel(args[0], args[1]); err != nil { + if err := sdk.DeleteChannel(args[0], args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } @@ -100,11 +100,11 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "update ", + Use: "update ", Short: "Update channel", Long: `Updates channel record`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { + if len(args) != 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -115,7 +115,7 @@ var cmdChannels = []cobra.Command{ return } channel.ID = args[0] - channel, err := sdk.UpdateChannel(channel, args[2]) + channel, err := sdk.UpdateChannel(channel, args[2], args[3]) if err != nil { logErrorCmd(*cmd, err) return @@ -125,19 +125,20 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "connections ", + Use: "connections ", Short: "Connections list", Long: `List of Things connected to a Channel`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[1], } - cl, err := sdk.ThingsByChannel(args[0], pm, args[1]) + cl, err := sdk.ThingsByChannel(args[0], pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -147,16 +148,16 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "enable ", + Use: "enable ", Short: "Change channel status to enabled", Long: `Change channel status to enabled`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - channel, err := sdk.EnableChannel(args[0], args[1]) + channel, err := sdk.EnableChannel(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -166,16 +167,16 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "disable ", + Use: "disable ", Short: "Change channel status to disabled", Long: `Change channel status to disabled`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - channel, err := sdk.DisableChannel(args[0], args[1]) + channel, err := sdk.DisableChannel(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -185,21 +186,22 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "users ", + Use: "users ", Short: "List users", Long: "List users of a channel\n" + "Usage:\n" + - "\tmagistrala-cli channels users $USERTOKEN\n", + "\tmagistrala-cli channels users $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[1], } - ul, err := sdk.ListChannelUsers(args[0], pm, args[1]) + ul, err := sdk.ListChannelUsers(args[0], pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -209,21 +211,22 @@ var cmdChannels = []cobra.Command{ }, }, { - Use: "groups ", + Use: "groups ", Short: "List groups", Long: "List groups of a channel\n" + "Usage:\n" + - "\tmagistrala-cli channels groups $USERTOKEN\n", + "\tmagistrala-cli channels groups $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[1], } - ul, err := sdk.ListChannelUserGroups(args[0], pm, args[1]) + ul, err := sdk.ListChannelUserGroups(args[0], pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -236,13 +239,13 @@ var cmdChannels = []cobra.Command{ var channelAssignCmds = []cobra.Command{ { - Use: "users ", + Use: "users ", Short: "Assign users", Long: "Assign users to a channel\n" + "Usage:\n" + - "\tmagistrala-cli channels assign users '[\"\", \"\"]' $USERTOKEN\n", + "\tmagistrala-cli channels assign users '[\"\", \"\"]' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 { + if len(args) != 5 { logUsageCmd(*cmd, cmd.Use) return } @@ -251,7 +254,7 @@ var channelAssignCmds = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.AddUserToChannel(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3]); err != nil { + if err := sdk.AddUserToChannel(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3], args[4]); err != nil { logErrorCmd(*cmd, err) return } @@ -259,14 +262,14 @@ var channelAssignCmds = []cobra.Command{ }, }, { - Use: "groups ", + Use: "groups ", Short: "Assign groups", Long: "Assign groups to a channel\n" + "Usage:\n" + - "\tmagistrala-cli channels assign groups '[\"\", \"\"]' $USERTOKEN\n", + "\tmagistrala-cli channels assign groups '[\"\", \"\"]' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { + if len(args) != 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -275,7 +278,7 @@ var channelAssignCmds = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.AddUserGroupToChannel(args[1], mgxsdk.UserGroupsRequest{UserGroupIDs: groupIDs}, args[2]); err != nil { + if err := sdk.AddUserGroupToChannel(args[1], mgxsdk.UserGroupsRequest{UserGroupIDs: groupIDs}, args[2], args[3]); err != nil { logErrorCmd(*cmd, err) return } @@ -286,13 +289,13 @@ var channelAssignCmds = []cobra.Command{ var channelUnassignCmds = []cobra.Command{ { - Use: "groups ", + Use: "groups ", Short: "Unassign groups", Long: "Unassign groups from a channel\n" + "Usage:\n" + - "\tmagistrala-cli channels unassign groups '[\"\", \"\"]' $USERTOKEN\n", + "\tmagistrala-cli channels unassign groups '[\"\", \"\"]' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { + if len(args) != 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -301,7 +304,7 @@ var channelUnassignCmds = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.RemoveUserGroupFromChannel(args[1], mgxsdk.UserGroupsRequest{UserGroupIDs: groupIDs}, args[2]); err != nil { + if err := sdk.RemoveUserGroupFromChannel(args[1], mgxsdk.UserGroupsRequest{UserGroupIDs: groupIDs}, args[2], args[3]); err != nil { logErrorCmd(*cmd, err) return } @@ -310,13 +313,13 @@ var channelUnassignCmds = []cobra.Command{ }, { - Use: "users ", + Use: "users ", Short: "Unassign users", Long: "Unassign users from a channel\n" + "Usage:\n" + - "\tmagistrala-cli channels unassign users '[\"\", \"\"]' $USERTOKEN\n", + "\tmagistrala-cli channels unassign users '[\"\", \"\"]' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 { + if len(args) != 5 { logUsageCmd(*cmd, cmd.Use) return } @@ -325,7 +328,7 @@ var channelUnassignCmds = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.RemoveUserFromChannel(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3]); err != nil { + if err := sdk.RemoveUserFromChannel(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3], args[4]); err != nil { logErrorCmd(*cmd, err) return } diff --git a/cli/channels_test.go b/cli/channels_test.go index f7686503d3..ec65652e8d 100644 --- a/cli/channels_test.go +++ b/cli/channels_test.go @@ -45,6 +45,7 @@ func TestCreateChannelCmd(t *testing.T) { desc: "create channel successfully", args: []string{ channelJson, + domainID, token, }, channel: channel, @@ -54,6 +55,7 @@ func TestCreateChannelCmd(t *testing.T) { desc: "create channel with invalid args", args: []string{ channelJson, + domainID, token, extraArg, }, @@ -63,6 +65,7 @@ func TestCreateChannelCmd(t *testing.T) { desc: "create channel with invalid json", args: []string{ "{\"name\":\"testchannel\", \"metadata\":{\"key1\":\"value1\"}", + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -73,27 +76,18 @@ func TestCreateChannelCmd(t *testing.T) { desc: "create channel with invalid token", args: []string{ channelJson, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), logType: errLog, }, - { - desc: "create channel without domain token", - args: []string{ - channelJson, - tokenWithoutDomain, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), - logType: errLog, - }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("CreateChannel", mock.Anything, tc.args[1]).Return(tc.channel, tc.sdkErr) + sdkCall := sdkMock.On("CreateChannel", mock.Anything, tc.args[1], tc.args[2]).Return(tc.channel, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{createCmd}, tc.args...)...) switch tc.logType { @@ -133,6 +127,7 @@ func TestGetChannelsCmd(t *testing.T) { desc: "get all channels successfully", args: []string{ all, + domainID, token, }, page: mgsdk.ChannelsPage{ @@ -144,6 +139,7 @@ func TestGetChannelsCmd(t *testing.T) { desc: "get channel with id", args: []string{ channel.ID, + domainID, token, }, logType: entityLog, @@ -153,6 +149,7 @@ func TestGetChannelsCmd(t *testing.T) { desc: "get channels with invalid args", args: []string{ all, + domainID, token, extraArg, }, @@ -162,26 +159,18 @@ func TestGetChannelsCmd(t *testing.T) { desc: "get all channels with invalid token", args: []string{ all, + domainID, invalidToken, }, logType: errLog, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), }, - { - desc: "get channel without domain token", - args: []string{ - channel.ID, - tokenWithoutDomain, - }, - logType: errLog, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), - }, { desc: "get channel with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -192,8 +181,8 @@ func TestGetChannelsCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Channel", tc.args[0], tc.args[1]).Return(tc.channel, tc.sdkErr) - sdkCall1 := sdkMock.On("Channels", mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("Channel", tc.args[0], tc.args[1], tc.args[2]).Return(tc.channel, tc.sdkErr) + sdkCall1 := sdkMock.On("Channels", mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) @@ -236,6 +225,7 @@ func TestDeleteChannelCmd(t *testing.T) { desc: "delete channel successfully", args: []string{ channel.ID, + domainID, token, }, logType: okLog, @@ -244,6 +234,7 @@ func TestDeleteChannelCmd(t *testing.T) { desc: "delete channel with invalid args", args: []string{ channel.ID, + domainID, token, extraArg, }, @@ -253,6 +244,7 @@ func TestDeleteChannelCmd(t *testing.T) { desc: "delete channel with invalid channel id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -263,6 +255,7 @@ func TestDeleteChannelCmd(t *testing.T) { desc: "delete channel with invalid token", args: []string{ channel.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -273,7 +266,7 @@ func TestDeleteChannelCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("DeleteChannel", tc.args[0], tc.args[1]).Return(tc.sdkErr) + sdkCall := sdkMock.On("DeleteChannel", tc.args[0], tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{delCmd}, tc.args...)...) switch tc.logType { @@ -309,6 +302,7 @@ func TestUpdateChannelCmd(t *testing.T) { args: []string{ channel.ID, newChannelJson, + domainID, token, }, channel: mgsdk.Channel{ @@ -322,6 +316,7 @@ func TestUpdateChannelCmd(t *testing.T) { args: []string{ channel.ID, newChannelJson, + domainID, token, extraArg, }, @@ -332,6 +327,7 @@ func TestUpdateChannelCmd(t *testing.T) { args: []string{ invalidID, newChannelJson, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -343,6 +339,7 @@ func TestUpdateChannelCmd(t *testing.T) { args: []string{ channel.ID, "{\"name\" : \"channel1\"", + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -353,7 +350,7 @@ func TestUpdateChannelCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var ch mgsdk.Channel - sdkCall := sdkMock.On("UpdateChannel", mock.Anything, tc.args[2]).Return(tc.channel, tc.sdkErr) + sdkCall := sdkMock.On("UpdateChannel", mock.Anything, tc.args[2], tc.args[3]).Return(tc.channel, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{updCmd}, tc.args...)...) switch tc.logType { @@ -390,6 +387,7 @@ func TestListConnectionsCmd(t *testing.T) { desc: "list connections successfully", args: []string{ channel.ID, + domainID, token, }, page: mgsdk.ThingsPage{ @@ -406,6 +404,7 @@ func TestListConnectionsCmd(t *testing.T) { desc: "list connections with invalid args", args: []string{ channel.ID, + domainID, token, extraArg, }, @@ -415,6 +414,7 @@ func TestListConnectionsCmd(t *testing.T) { desc: "list connections with invalid channel id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -425,7 +425,7 @@ func TestListConnectionsCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ThingsByChannel", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ThingsByChannel", tc.args[0], mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{connsCmd}, tc.args...)...) switch tc.logType { case entityLog: @@ -463,6 +463,7 @@ func TestEnableChannelCmd(t *testing.T) { desc: "enable channel successfully", args: []string{ channel.ID, + domainID, validToken, }, channel: channel, @@ -472,6 +473,7 @@ func TestEnableChannelCmd(t *testing.T) { desc: "delete channel with invalid token", args: []string{ channel.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -482,6 +484,7 @@ func TestEnableChannelCmd(t *testing.T) { desc: "delete channel with invalid channel ID", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -492,6 +495,7 @@ func TestEnableChannelCmd(t *testing.T) { desc: "enable channel with invalid args", args: []string{ channel.ID, + domainID, validToken, extraArg, }, @@ -501,7 +505,7 @@ func TestEnableChannelCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("EnableChannel", tc.args[0], tc.args[1]).Return(tc.channel, tc.sdkErr) + sdkCall := sdkMock.On("EnableChannel", tc.args[0], tc.args[1], tc.args[2]).Return(tc.channel, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{enableCmd}, tc.args...)...) switch tc.logType { @@ -540,6 +544,7 @@ func TestDisableChannelCmd(t *testing.T) { desc: "disable channel successfully", args: []string{ channel.ID, + domainID, validToken, }, logType: entityLog, @@ -549,6 +554,7 @@ func TestDisableChannelCmd(t *testing.T) { desc: "disable channel with invalid token", args: []string{ channel.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -559,6 +565,7 @@ func TestDisableChannelCmd(t *testing.T) { desc: "disable channel with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -569,6 +576,7 @@ func TestDisableChannelCmd(t *testing.T) { desc: "disable thing with invalid args", args: []string{ channel.ID, + domainID, validToken, extraArg, }, @@ -578,7 +586,7 @@ func TestDisableChannelCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("DisableChannel", tc.args[0], tc.args[1]).Return(tc.channel, tc.sdkErr) + sdkCall := sdkMock.On("DisableChannel", tc.args[0], tc.args[1], tc.args[2]).Return(tc.channel, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{disableCmd}, tc.args...)...) switch tc.logType { @@ -619,6 +627,7 @@ func TestUsersChannelCmd(t *testing.T) { desc: "get channel's users successfully", args: []string{ channel.ID, + domainID, token, }, page: mgsdk.UsersPage{ @@ -635,25 +644,17 @@ func TestUsersChannelCmd(t *testing.T) { desc: "list channel users with invalid args", args: []string{ channel.ID, + domainID, token, extraArg, }, logType: usageLog, }, - { - desc: "list channel users without domain token", - args: []string{ - channel.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 channel users with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -664,7 +665,7 @@ func TestUsersChannelCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ListChannelUsers", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ListChannelUsers", tc.args[0], mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{usrCmd}, tc.args...)...) switch tc.logType { @@ -703,6 +704,7 @@ func TestListGroupCmd(t *testing.T) { desc: "list groups successfully", args: []string{ channel.ID, + domainID, token, }, page: mgsdk.GroupsPage{ @@ -719,6 +721,7 @@ func TestListGroupCmd(t *testing.T) { desc: "list groups with invalid args", args: []string{ channel.ID, + domainID, token, extraArg, }, @@ -728,6 +731,7 @@ func TestListGroupCmd(t *testing.T) { desc: "list groups with invalid channel id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -737,7 +741,7 @@ func TestListGroupCmd(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ListChannelUserGroups", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ListChannelUserGroups", tc.args[0], mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{grpCmd}, tc.args...)...) switch tc.logType { case entityLog: @@ -777,6 +781,7 @@ func TestAssignUserCmd(t *testing.T) { relation, userIds, channel.ID, + domainID, token, }, logType: okLog, @@ -787,6 +792,7 @@ func TestAssignUserCmd(t *testing.T) { relation, userIds, channel.ID, + domainID, token, extraArg, }, @@ -798,6 +804,7 @@ func TestAssignUserCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"", user.ID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -810,6 +817,7 @@ func TestAssignUserCmd(t *testing.T) { relation, userIds, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -822,6 +830,7 @@ func TestAssignUserCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"]", invalidID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -832,7 +841,7 @@ func TestAssignUserCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("AddUserToChannel", tc.args[2], mock.Anything, tc.args[3]).Return(tc.sdkErr) + sdkCall := sdkMock.On("AddUserToChannel", tc.args[2], mock.Anything, tc.args[3], tc.args[4]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{assignCmd, usrCmd}, tc.args...)...) switch tc.logType { case okLog: @@ -867,6 +876,7 @@ func TestAssignGroupCmd(t *testing.T) { args: []string{ grpIds, channel.ID, + domainID, token, }, logType: okLog, @@ -876,6 +886,7 @@ func TestAssignGroupCmd(t *testing.T) { args: []string{ grpIds, channel.ID, + domainID, token, extraArg, }, @@ -886,6 +897,7 @@ func TestAssignGroupCmd(t *testing.T) { args: []string{ fmt.Sprintf("[\"%s\"", group.ID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -897,6 +909,7 @@ func TestAssignGroupCmd(t *testing.T) { args: []string{ grpIds, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -908,6 +921,7 @@ func TestAssignGroupCmd(t *testing.T) { args: []string{ fmt.Sprintf("[\"%s\"]", invalidID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -918,7 +932,7 @@ func TestAssignGroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("AddUserGroupToChannel", tc.args[1], mock.Anything, tc.args[2]).Return(tc.sdkErr) + sdkCall := sdkMock.On("AddUserGroupToChannel", tc.args[1], mock.Anything, tc.args[2], tc.args[3]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{assignCmd, grpCmd}, tc.args...)...) switch tc.logType { case okLog: @@ -954,6 +968,7 @@ func TestUnassignUserCmd(t *testing.T) { relation, userIds, channel.ID, + domainID, token, }, logType: okLog, @@ -964,6 +979,7 @@ func TestUnassignUserCmd(t *testing.T) { relation, userIds, channel.ID, + domainID, token, extraArg, }, @@ -975,6 +991,7 @@ func TestUnassignUserCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"", user.ID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -987,6 +1004,7 @@ func TestUnassignUserCmd(t *testing.T) { relation, userIds, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -999,6 +1017,7 @@ func TestUnassignUserCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"]", invalidID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -1009,7 +1028,7 @@ func TestUnassignUserCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("RemoveUserFromChannel", tc.args[2], mock.Anything, tc.args[3]).Return(tc.sdkErr) + sdkCall := sdkMock.On("RemoveUserFromChannel", tc.args[2], mock.Anything, tc.args[3], tc.args[4]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{unassignCmd, usrCmd}, tc.args...)...) switch tc.logType { case okLog: @@ -1046,6 +1065,7 @@ func TestUnassignGroupCmd(t *testing.T) { grpCmd, grpIds, channel.ID, + domainID, token, }, logType: okLog, @@ -1055,6 +1075,7 @@ func TestUnassignGroupCmd(t *testing.T) { args: []string{ grpIds, channel.ID, + domainID, token, extraArg, }, @@ -1065,6 +1086,7 @@ func TestUnassignGroupCmd(t *testing.T) { args: []string{ fmt.Sprintf("[\"%s\"", group.ID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -1076,6 +1098,7 @@ func TestUnassignGroupCmd(t *testing.T) { args: []string{ grpIds, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -1087,6 +1110,7 @@ func TestUnassignGroupCmd(t *testing.T) { args: []string{ fmt.Sprintf("[\"%s\"]", invalidID), channel.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -1097,7 +1121,7 @@ func TestUnassignGroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("RemoveUserGroupFromChannel", tc.args[1], mock.Anything, tc.args[2]).Return(tc.sdkErr) + sdkCall := sdkMock.On("RemoveUserGroupFromChannel", tc.args[1], mock.Anything, tc.args[2], tc.args[3]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{unassignCmd, grpCmd}, tc.args...)...) switch tc.logType { case okLog: diff --git a/cli/groups.go b/cli/groups.go index aff1475d89..b910c946c6 100644 --- a/cli/groups.go +++ b/cli/groups.go @@ -13,13 +13,13 @@ import ( var cmdGroups = []cobra.Command{ { - Use: "create ", + Use: "create ", Short: "Create group", Long: "Creates new group\n" + "Usage:\n" + - "\tmagistrala-cli groups create '{\"name\":\"new group\", \"description\":\"new group description\", \"metadata\":{\"key\": \"value\"}}' $USERTOKEN\n", + "\tmagistrala-cli groups create '{\"name\":\"new group\", \"description\":\"new group description\", \"metadata\":{\"key\": \"value\"}}' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -29,7 +29,7 @@ var cmdGroups = []cobra.Command{ return } group.Status = mgclients.EnabledStatus.String() - group, err := sdk.CreateGroup(group, args[1]) + group, err := sdk.CreateGroup(group, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -38,13 +38,13 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "update ", + Use: "update ", Short: "Update group", Long: "Updates group\n" + "Usage:\n" + - "\tmagistrala-cli groups update '{\"id\":\"\", \"name\":\"new group\", \"description\":\"new group description\", \"metadata\":{\"key\": \"value\"}}' $USERTOKEN\n", + "\tmagistrala-cli groups update '{\"id\":\"\", \"name\":\"new group\", \"description\":\"new group description\", \"metadata\":{\"key\": \"value\"}}' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -55,7 +55,7 @@ var cmdGroups = []cobra.Command{ return } - group, err := sdk.UpdateGroup(group, args[1]) + group, err := sdk.UpdateGroup(group, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -65,29 +65,30 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "get [all | children | parents | members | ] ", + Use: "get [all | children | parents | members | ] ", Short: "Get group", Long: "Get all users groups, group children or group by id.\n" + "Usage:\n" + - "\tmagistrala-cli groups get all $USERTOKEN - lists all groups\n" + - "\tmagistrala-cli groups get children $USERTOKEN - lists all children groups of \n" + - "\tmagistrala-cli groups get parents $USERTOKEN - lists all parent groups of \n" + - "\tmagistrala-cli groups get $USERTOKEN - shows group with provided group ID\n", + "\tmagistrala-cli groups get all $DOMAINID $USERTOKEN - lists all groups\n" + + "\tmagistrala-cli groups get children $DOMAINID $USERTOKEN - lists all children groups of \n" + + "\tmagistrala-cli groups get parents $DOMAINID $USERTOKEN - lists all parent groups of \n" + + "\tmagistrala-cli groups get $DOMAINID $USERTOKEN - shows group with provided group ID\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) < 2 { + if len(args) < 3 { logUsageCmd(*cmd, cmd.Use) return } if args[0] == all { - if len(args) > 2 { + if len(args) > 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[1], } - l, err := sdk.Groups(pm, args[1]) + l, err := sdk.Groups(pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -96,15 +97,16 @@ var cmdGroups = []cobra.Command{ return } if args[0] == "children" { - if len(args) > 3 { + if len(args) > 4 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[2], } - l, err := sdk.Children(args[1], pm, args[2]) + l, err := sdk.Children(args[1], pm, args[3]) if err != nil { logErrorCmd(*cmd, err) return @@ -113,15 +115,16 @@ var cmdGroups = []cobra.Command{ return } if args[0] == "parents" { - if len(args) > 3 { + if len(args) > 4 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[2], } - l, err := sdk.Parents(args[1], pm, args[2]) + l, err := sdk.Parents(args[1], pm, args[3]) if err != nil { logErrorCmd(*cmd, err) return @@ -129,11 +132,11 @@ var cmdGroups = []cobra.Command{ logJSONCmd(*cmd, l) return } - if len(args) > 2 { + if len(args) > 3 { logUsageCmd(*cmd, cmd.Use) return } - t, err := sdk.Group(args[0], args[1]) + t, err := sdk.Group(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -142,17 +145,17 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "delete ", + Use: "delete ", Short: "Delete group", Long: "Delete group by id.\n" + "Usage:\n" + - "\tmagistrala-cli groups delete $USERTOKEN - delete the given group ID\n", + "\tmagistrala-cli groups delete $DOMAINID $USERTOKEN - delete the given group ID\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - if err := sdk.DeleteGroup(args[0], args[1]); err != nil { + if err := sdk.DeleteGroup(args[0], args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } @@ -160,22 +163,23 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "users ", + Use: "users ", Short: "List users", Long: "List users in a group\n" + "Usage:\n" + - "\tmagistrala-cli groups users $USERTOKEN", + "\tmagistrala-cli groups users $DOMAINID $USERTOKEN", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, - Status: Status, + Offset: Offset, + Limit: Limit, + Status: Status, + DomainID: args[1], } - users, err := sdk.ListGroupUsers(args[0], pm, args[1]) + users, err := sdk.ListGroupUsers(args[0], pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -184,22 +188,23 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "channels ", + Use: "channels ", Short: "List channels", Long: "List channels in a group\n" + "Usage:\n" + - "\tmagistrala-cli groups channels $USERTOKEN", + "\tmagistrala-cli groups channels $DOMAINID $USERTOKEN", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, - Status: Status, + Offset: Offset, + Limit: Limit, + Status: Status, + DomainID: args[1], } - channels, err := sdk.ListGroupChannels(args[0], pm, args[1]) + channels, err := sdk.ListGroupChannels(args[0], pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -208,18 +213,18 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "enable ", + Use: "enable ", Short: "Change group status to enabled", Long: "Change group status to enabled\n" + "Usage:\n" + - "\tmagistrala-cli groups enable $USERTOKEN\n", + "\tmagistrala-cli groups enable $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - group, err := sdk.EnableGroup(args[0], args[1]) + group, err := sdk.EnableGroup(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -229,18 +234,18 @@ var cmdGroups = []cobra.Command{ }, }, { - Use: "disable ", + Use: "disable ", Short: "Change group status to disabled", Long: "Change group status to disabled\n" + "Usage:\n" + - "\tmagistrala-cli groups disable $USERTOKEN\n", + "\tmagistrala-cli groups disable $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - group, err := sdk.DisableGroup(args[0], args[1]) + group, err := sdk.DisableGroup(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -253,13 +258,13 @@ var cmdGroups = []cobra.Command{ var groupAssignCmds = []cobra.Command{ { - Use: "users ", + Use: "users ", Short: "Assign users", Long: "Assign users to a group\n" + "Usage:\n" + - "\tmagistrala-cli groups assign users '[\"\", \"\"]' $USERTOKEN\n", + "\tmagistrala-cli groups assign users '[\"\", \"\"]' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 { + if len(args) != 5 { logUsageCmd(*cmd, cmd.Use) return } @@ -268,7 +273,7 @@ var groupAssignCmds = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.AddUserToGroup(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3]); err != nil { + if err := sdk.AddUserToGroup(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3], args[4]); err != nil { logErrorCmd(*cmd, err) return } @@ -279,13 +284,13 @@ var groupAssignCmds = []cobra.Command{ var groupUnassignCmds = []cobra.Command{ { - Use: "users ", + Use: "users ", Short: "Unassign users", Long: "Unassign users from a group\n" + "Usage:\n" + - "\tmagistrala-cli groups unassign users '[\"\", \"\"]' $USERTOKEN\n", + "\tmagistrala-cli groups unassign users '[\"\", \"\"]' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 { + if len(args) != 5 { logUsageCmd(*cmd, cmd.Use) return } @@ -294,7 +299,7 @@ var groupUnassignCmds = []cobra.Command{ logErrorCmd(*cmd, err) return } - if err := sdk.RemoveUserFromGroup(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3]); err != nil { + if err := sdk.RemoveUserFromGroup(args[2], mgxsdk.UsersRelationRequest{Relation: args[0], UserIDs: userIDs}, args[3], args[4]); err != nil { logErrorCmd(*cmd, err) return } diff --git a/cli/groups_test.go b/cli/groups_test.go index a262b8146d..200377c4da 100644 --- a/cli/groups_test.go +++ b/cli/groups_test.go @@ -45,6 +45,7 @@ func TestCreateGroupCmd(t *testing.T) { desc: "create group successfully", args: []string{ groupJson, + domainID, token, }, group: group, @@ -54,6 +55,7 @@ func TestCreateGroupCmd(t *testing.T) { desc: "create group with invalid args", args: []string{ groupJson, + domainID, token, extraArg, }, @@ -63,6 +65,7 @@ func TestCreateGroupCmd(t *testing.T) { desc: "create group with invalid json", args: []string{ "{\"name\":\"testgroup\", \"metadata\":{\"key1\":\"value1\"}", + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -73,6 +76,7 @@ func TestCreateGroupCmd(t *testing.T) { desc: "create group with invalid token", args: []string{ groupJson, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -80,10 +84,11 @@ func TestCreateGroupCmd(t *testing.T) { logType: errLog, }, { - desc: "create group without domain token", + desc: "create group with invalid domain", args: []string{ groupJson, - tokenWithoutDomain, + domainID, + token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), @@ -93,7 +98,7 @@ func TestCreateGroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("CreateGroup", mock.Anything, tc.args[1]).Return(tc.group, tc.sdkErr) + sdkCall := sdkMock.On("CreateGroup", mock.Anything, tc.args[1], tc.args[2]).Return(tc.group, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{createCmd}, tc.args...)...) switch tc.logType { @@ -133,6 +138,7 @@ func TestGetGroupsCmd(t *testing.T) { desc: "get all groups successfully", args: []string{ all, + domainID, token, }, page: mgsdk.GroupsPage{ @@ -144,28 +150,31 @@ func TestGetGroupsCmd(t *testing.T) { desc: "get all groups with invalid args", args: []string{ all, + domainID, token, extraArg, }, logType: usageLog, }, - { - desc: "get children groups successfully", - args: []string{ - childCmd, - group.ID, - token, - }, - page: mgsdk.GroupsPage{ - Groups: []mgsdk.Group{group}, - }, - logType: entityLog, - }, + // { + // desc: "get children groups successfully", + // args: []string{ + // childCmd, + // group.ID, + // domainID, + // token, + // }, + // page: mgsdk.GroupsPage{ + // Groups: []mgsdk.Group{group}, + // }, + // logType: entityLog, + // }, { desc: "get children groups with invalid args", args: []string{ childCmd, group.ID, + domainID, token, extraArg, }, @@ -176,6 +185,7 @@ func TestGetGroupsCmd(t *testing.T) { args: []string{ childCmd, group.ID, + domainID, invalidToken, }, logType: errLog, @@ -187,6 +197,7 @@ func TestGetGroupsCmd(t *testing.T) { args: []string{ parentCmd, group.ID, + domainID, token, }, page: mgsdk.GroupsPage{ @@ -199,6 +210,7 @@ func TestGetGroupsCmd(t *testing.T) { args: []string{ parentCmd, group.ID, + domainID, token, extraArg, }, @@ -209,6 +221,7 @@ func TestGetGroupsCmd(t *testing.T) { args: []string{ parentCmd, group.ID, + domainID, invalidToken, }, logType: errLog, @@ -219,6 +232,7 @@ func TestGetGroupsCmd(t *testing.T) { desc: "get group with id", args: []string{ group.ID, + domainID, token, }, logType: entityLog, @@ -235,6 +249,7 @@ func TestGetGroupsCmd(t *testing.T) { desc: "get all groups with invalid token", args: []string{ all, + domainID, invalidToken, }, logType: errLog, @@ -242,10 +257,11 @@ func TestGetGroupsCmd(t *testing.T) { errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), }, { - desc: "get group without domain token", + desc: "get group with invalid domain", args: []string{ group.ID, - invalidToken, + invalidID, + token, }, logType: errLog, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), @@ -255,6 +271,7 @@ func TestGetGroupsCmd(t *testing.T) { desc: "get group with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -265,6 +282,7 @@ func TestGetGroupsCmd(t *testing.T) { desc: "get group with invalid args", args: []string{ group.ID, + domainID, token, extraArg, }, @@ -274,7 +292,7 @@ func TestGetGroupsCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Group", mock.Anything, mock.Anything).Return(tc.group, tc.sdkErr) + sdkCall := sdkMock.On("Group", mock.Anything, mock.Anything, mock.Anything).Return(tc.group, tc.sdkErr) sdkCall1 := sdkMock.On("Groups", mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr) sdkCall2 := sdkMock.On("Parents", mock.Anything, mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr) sdkCall3 := sdkMock.On("Children", mock.Anything, mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr) @@ -322,6 +340,7 @@ func TestDeletegroupCmd(t *testing.T) { desc: "delete group successfully", args: []string{ group.ID, + domainID, token, }, logType: okLog, @@ -330,6 +349,7 @@ func TestDeletegroupCmd(t *testing.T) { desc: "delete group with invalid args", args: []string{ group.ID, + domainID, token, extraArg, }, @@ -339,6 +359,7 @@ func TestDeletegroupCmd(t *testing.T) { desc: "delete group with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -349,6 +370,7 @@ func TestDeletegroupCmd(t *testing.T) { desc: "delete group with invalid token", args: []string{ group.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -359,7 +381,7 @@ func TestDeletegroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("DeleteGroup", tc.args[0], tc.args[1]).Return(tc.sdkErr) + sdkCall := sdkMock.On("DeleteGroup", tc.args[0], tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{delCmd}, tc.args...)...) switch tc.logType { @@ -394,6 +416,7 @@ func TestUpdategroupCmd(t *testing.T) { desc: "update group successfully", args: []string{ newGroupJson, + domainID, token, }, group: mgsdk.Group{ @@ -406,6 +429,7 @@ func TestUpdategroupCmd(t *testing.T) { desc: "update group with invalid args", args: []string{ newGroupJson, + domainID, token, extraArg, }, @@ -415,6 +439,7 @@ func TestUpdategroupCmd(t *testing.T) { desc: "update group with invalid group id", args: []string{ fmt.Sprintf("{\"id\":\"%s\",\"name\" : \"group1\"}", invalidID), + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -425,6 +450,7 @@ func TestUpdategroupCmd(t *testing.T) { desc: "update group with invalid json syntax", args: []string{ fmt.Sprintf("{\"id\":\"%s\",\"name\" : \"group1\"", group.ID), + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -435,7 +461,7 @@ func TestUpdategroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var ch mgsdk.Group - sdkCall := sdkMock.On("UpdateGroup", mock.Anything, tc.args[1]).Return(tc.group, tc.sdkErr) + sdkCall := sdkMock.On("UpdateGroup", mock.Anything, tc.args[1], tc.args[2]).Return(tc.group, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{updCmd}, tc.args...)...) switch tc.logType { @@ -472,6 +498,7 @@ func TestListUsersCmd(t *testing.T) { desc: "list users successfully", args: []string{ group.ID, + domainID, token, }, page: mgsdk.UsersPage{ @@ -488,6 +515,7 @@ func TestListUsersCmd(t *testing.T) { desc: "list users with invalid args", args: []string{ group.ID, + domainID, token, extraArg, }, @@ -497,6 +525,7 @@ func TestListUsersCmd(t *testing.T) { desc: "list users with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -506,7 +535,7 @@ func TestListUsersCmd(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ListGroupUsers", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ListGroupUsers", tc.args[0], mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{usrCmd}, tc.args...)...) switch tc.logType { case entityLog: @@ -544,6 +573,7 @@ func TestListChannelsCmd(t *testing.T) { desc: "list channels successfully", args: []string{ group.ID, + domainID, token, }, page: mgsdk.ChannelsPage{ @@ -560,6 +590,7 @@ func TestListChannelsCmd(t *testing.T) { desc: "list channels with invalid args", args: []string{ group.ID, + domainID, token, extraArg, }, @@ -569,6 +600,7 @@ func TestListChannelsCmd(t *testing.T) { desc: "list channels with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -578,7 +610,7 @@ func TestListChannelsCmd(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ListGroupChannels", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ListGroupChannels", tc.args[0], mock.Anything, tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{chansCmd}, tc.args...)...) switch tc.logType { case entityLog: @@ -616,6 +648,7 @@ func TestEnablegroupCmd(t *testing.T) { desc: "enable group successfully", args: []string{ group.ID, + domainID, validToken, }, group: group, @@ -625,6 +658,7 @@ func TestEnablegroupCmd(t *testing.T) { desc: "delete group with invalid token", args: []string{ group.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -635,6 +669,7 @@ func TestEnablegroupCmd(t *testing.T) { desc: "delete group with invalid group ID", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -645,6 +680,7 @@ func TestEnablegroupCmd(t *testing.T) { desc: "enable group with invalid args", args: []string{ group.ID, + domainID, validToken, extraArg, }, @@ -654,7 +690,7 @@ func TestEnablegroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("EnableGroup", tc.args[0], tc.args[1]).Return(tc.group, tc.sdkErr) + sdkCall := sdkMock.On("EnableGroup", tc.args[0], tc.args[1], tc.args[2]).Return(tc.group, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{enableCmd}, tc.args...)...) switch tc.logType { @@ -693,6 +729,7 @@ func TestDisablegroupCmd(t *testing.T) { desc: "disable group successfully", args: []string{ group.ID, + domainID, validToken, }, logType: entityLog, @@ -702,6 +739,7 @@ func TestDisablegroupCmd(t *testing.T) { desc: "disable group with invalid token", args: []string{ group.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -712,6 +750,7 @@ func TestDisablegroupCmd(t *testing.T) { desc: "disable group with invalid id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -722,6 +761,7 @@ func TestDisablegroupCmd(t *testing.T) { desc: "disable thing with invalid args", args: []string{ group.ID, + domainID, validToken, extraArg, }, @@ -731,7 +771,7 @@ func TestDisablegroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("DisableGroup", tc.args[0], tc.args[1]).Return(tc.group, tc.sdkErr) + sdkCall := sdkMock.On("DisableGroup", tc.args[0], tc.args[1], tc.args[2]).Return(tc.group, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{disableCmd}, tc.args...)...) switch tc.logType { @@ -773,6 +813,7 @@ func TestAssignUserToGroupCmd(t *testing.T) { relation, userIds, group.ID, + domainID, token, }, logType: okLog, @@ -783,6 +824,7 @@ func TestAssignUserToGroupCmd(t *testing.T) { relation, userIds, group.ID, + domainID, token, extraArg, }, @@ -794,6 +836,7 @@ func TestAssignUserToGroupCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"", user.ID), group.ID, + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -806,6 +849,7 @@ func TestAssignUserToGroupCmd(t *testing.T) { relation, userIds, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -818,6 +862,7 @@ func TestAssignUserToGroupCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"]", invalidID), group.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -828,7 +873,7 @@ func TestAssignUserToGroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("AddUserToGroup", tc.args[2], mock.Anything, tc.args[3]).Return(tc.sdkErr) + sdkCall := sdkMock.On("AddUserToGroup", tc.args[2], mock.Anything, tc.args[3], tc.args[4]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{assignCmd, usrCmd}, tc.args...)...) switch tc.logType { case okLog: @@ -864,6 +909,7 @@ func TestUnassignUserToGroupCmd(t *testing.T) { relation, userIds, group.ID, + domainID, token, }, logType: okLog, @@ -874,6 +920,7 @@ func TestUnassignUserToGroupCmd(t *testing.T) { relation, userIds, group.ID, + domainID, token, extraArg, }, @@ -885,6 +932,7 @@ func TestUnassignUserToGroupCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"", user.ID), group.ID, + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -897,6 +945,7 @@ func TestUnassignUserToGroupCmd(t *testing.T) { relation, userIds, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -909,6 +958,7 @@ func TestUnassignUserToGroupCmd(t *testing.T) { relation, fmt.Sprintf("[\"%s\"]", invalidID), group.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -919,7 +969,7 @@ func TestUnassignUserToGroupCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("RemoveUserFromGroup", tc.args[2], mock.Anything, tc.args[3]).Return(tc.sdkErr) + sdkCall := sdkMock.On("RemoveUserFromGroup", tc.args[2], mock.Anything, tc.args[3], tc.args[4]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{unassignCmd, usrCmd}, tc.args...)...) switch tc.logType { case okLog: diff --git a/cli/provision.go b/cli/provision.go index b7156ae35d..dd0d51ac92 100644 --- a/cli/provision.go +++ b/cli/provision.go @@ -31,11 +31,11 @@ var ( var cmdProvision = []cobra.Command{ { - Use: "things ", + Use: "things ", Short: "Provision things", Long: `Bulk create things`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -51,7 +51,7 @@ var cmdProvision = []cobra.Command{ return } - things, err = sdk.CreateThings(things, args[1]) + things, err = sdk.CreateThings(things, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -61,11 +61,11 @@ var cmdProvision = []cobra.Command{ }, }, { - Use: "channels ", + Use: "channels ", Short: "Provision channels", Long: `Bulk create channels`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -78,7 +78,7 @@ var cmdProvision = []cobra.Command{ var chs []mgxsdk.Channel for _, c := range channels { - c, err = sdk.CreateChannel(c, args[1]) + c, err = sdk.CreateChannel(c, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -91,11 +91,11 @@ var cmdProvision = []cobra.Command{ }, }, { - Use: "connect ", + Use: "connect ", Short: "Provision connections", Long: `Bulk connect things to channels`, Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -106,7 +106,7 @@ var cmdProvision = []cobra.Command{ return } for _, conn := range connIDs { - if err := sdk.Connect(conn, args[1]); err != nil { + if err := sdk.Connect(conn, args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } @@ -182,7 +182,7 @@ var cmdProvision = []cobra.Command{ things = append(things, t) } - things, err = sdk.CreateThings(things, ut.AccessToken) + things, err = sdk.CreateThings(things, domain.ID, ut.AccessToken) if err != nil { logErrorCmd(*cmd, err) return @@ -194,7 +194,7 @@ var cmdProvision = []cobra.Command{ Name: fmt.Sprintf("%s-channel-%d", name, i), Status: mgxsdk.EnabledStatus, } - c, err = sdk.CreateChannel(c, ut.AccessToken) + c, err = sdk.CreateChannel(c, domain.ID, ut.AccessToken) if err != nil { logErrorCmd(*cmd, err) return @@ -208,7 +208,7 @@ var cmdProvision = []cobra.Command{ ChannelID: channels[0].ID, ThingID: things[0].ID, } - if err := sdk.Connect(conIDs, ut.AccessToken); err != nil { + if err := sdk.Connect(conIDs, domain.ID, ut.AccessToken); err != nil { logErrorCmd(*cmd, err) return } @@ -217,7 +217,7 @@ var cmdProvision = []cobra.Command{ ChannelID: channels[1].ID, ThingID: things[0].ID, } - if err := sdk.Connect(conIDs, ut.AccessToken); err != nil { + if err := sdk.Connect(conIDs, domain.ID, ut.AccessToken); err != nil { logErrorCmd(*cmd, err) return } @@ -226,7 +226,7 @@ var cmdProvision = []cobra.Command{ ChannelID: channels[0].ID, ThingID: things[1].ID, } - if err := sdk.Connect(conIDs, ut.AccessToken); err != nil { + if err := sdk.Connect(conIDs, domain.ID, ut.AccessToken); err != nil { logErrorCmd(*cmd, err) return } diff --git a/cli/things.go b/cli/things.go index e37e6f24b3..56bc6b65c1 100644 --- a/cli/things.go +++ b/cli/things.go @@ -13,13 +13,13 @@ import ( var cmdThings = []cobra.Command{ { - Use: "create ", + Use: "create ", Short: "Create thing", Long: "Creates new thing with provided name and metadata\n" + "Usage:\n" + - "\tmagistrala-cli things create '{\"name\":\"new thing\", \"metadata\":{\"key\": \"value\"}}' $USERTOKEN\n", + "\tmagistrala-cli things create '{\"name\":\"new thing\", \"metadata\":{\"key\": \"value\"}}' $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -30,7 +30,7 @@ var cmdThings = []cobra.Command{ return } thing.Status = mgclients.EnabledStatus.String() - thing, err := sdk.CreateThing(thing, args[1]) + thing, err := sdk.CreateThing(thing, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -40,15 +40,15 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "get [all | ] ", + Use: "get [all | ] ", Short: "Get things", Long: "Get all things or get thing by id. Things can be filtered by name or metadata\n" + "Usage:\n" + - "\tmagistrala-cli things get all $USERTOKEN - lists all things\n" + - "\tmagistrala-cli things get all $USERTOKEN --offset=10 --limit=10 - lists all things with offset and limit\n" + + "\tmagistrala-cli things get all $DOMAINID $USERTOKEN - lists all things\n" + + "\tmagistrala-cli things get all $DOMAINID $USERTOKEN --offset=10 --limit=10 - lists all things with offset and limit\n" + "\tmagistrala-cli things get $USERTOKEN - shows thing with provided \n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -72,7 +72,7 @@ var cmdThings = []cobra.Command{ logJSONCmd(*cmd, l) return } - t, err := sdk.Thing(args[0], args[1]) + t, err := sdk.Thing(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -82,17 +82,17 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "delete ", + Use: "delete ", Short: "Delete thing", Long: "Delete thing by id\n" + "Usage:\n" + - "\tmagistrala-cli things delete $USERTOKEN - delete thing with \n", + "\tmagistrala-cli things delete $DOMAINID $USERTOKEN - delete thing with \n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - if err := sdk.DeleteThing(args[0], args[1]); err != nil { + if err := sdk.DeleteThing(args[0], args[1], args[2]); err != nil { logErrorCmd(*cmd, err) return } @@ -100,15 +100,15 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "update [ | tags | secret ] ", + Use: "update [ | tags | secret ] ", Short: "Update thing", Long: "Updates thing with provided id, name and metadata, or updates thing tags, secret\n" + "Usage:\n" + - "\tmagistrala-cli things update '{\"name\":\"new name\", \"metadata\":{\"key\": \"value\"}}' $USERTOKEN\n" + - "\tmagistrala-cli things update tags '{\"tag1\":\"value1\", \"tag2\":\"value2\"}' $USERTOKEN\n" + - "\tmagistrala-cli things update secret $USERTOKEN\n", + "\tmagistrala-cli things update '{\"name\":\"new name\", \"metadata\":{\"key\": \"value\"}}' $DOMAINID $USERTOKEN\n" + + "\tmagistrala-cli things update tags '{\"tag1\":\"value1\", \"tag2\":\"value2\"}' $DOMAINID $USERTOKEN\n" + + "\tmagistrala-cli things update secret $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 && len(args) != 3 { + if len(args) != 5 && len(args) != 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -120,7 +120,7 @@ var cmdThings = []cobra.Command{ return } thing.ID = args[1] - thing, err := sdk.UpdateThingTags(thing, args[3]) + thing, err := sdk.UpdateThingTags(thing, args[3], args[4]) if err != nil { logErrorCmd(*cmd, err) return @@ -131,7 +131,7 @@ var cmdThings = []cobra.Command{ } if args[0] == "secret" { - thing, err := sdk.UpdateThingSecret(args[1], args[2], args[3]) + thing, err := sdk.UpdateThingSecret(args[1], args[2], args[3], args[4]) if err != nil { logErrorCmd(*cmd, err) return @@ -146,7 +146,7 @@ var cmdThings = []cobra.Command{ return } thing.ID = args[0] - thing, err := sdk.UpdateThing(thing, args[2]) + thing, err := sdk.UpdateThing(thing, args[2], args[3]) if err != nil { logErrorCmd(*cmd, err) return @@ -156,18 +156,18 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "enable ", + Use: "enable ", Short: "Change thing status to enabled", Long: "Change thing status to enabled\n" + "Usage:\n" + - "\tmagistrala-cli things enable $USERTOKEN\n", + "\tmagistrala-cli things enable $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - thing, err := sdk.EnableThing(args[0], args[1]) + thing, err := sdk.EnableThing(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -177,18 +177,18 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "disable ", + Use: "disable ", Short: "Change thing status to disabled", Long: "Change thing status to disabled\n" + "Usage:\n" + - "\tmagistrala-cli things disable $USERTOKEN\n", + "\tmagistrala-cli things disable $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } - thing, err := sdk.DisableThing(args[0], args[1]) + thing, err := sdk.DisableThing(args[0], args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -198,13 +198,13 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "share ", + Use: "share ", Short: "Share thing with a user", Long: "Share thing with a user\n" + "Usage:\n" + - "\tmagistrala-cli things share $USERTOKEN\n", + "\tmagistrala-cli things share $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 { + if len(args) != 5 { logUsageCmd(*cmd, cmd.Use) return } @@ -212,7 +212,7 @@ var cmdThings = []cobra.Command{ Relation: args[2], UserIDs: []string{args[1]}, } - err := sdk.ShareThing(args[0], req, args[3]) + err := sdk.ShareThing(args[0], req, args[3], args[4]) if err != nil { logErrorCmd(*cmd, err) return @@ -222,13 +222,13 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "unshare ", + Use: "unshare ", Short: "Unshare thing with a user", Long: "Unshare thing with a user\n" + "Usage:\n" + - "\tmagistrala-cli things share $USERTOKEN\n", + "\tmagistrala-cli things share $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 4 { + if len(args) != 5 { logUsageCmd(*cmd, cmd.Use) return } @@ -236,7 +236,7 @@ var cmdThings = []cobra.Command{ Relation: args[2], UserIDs: []string{args[1]}, } - err := sdk.UnshareThing(args[0], req, args[3]) + err := sdk.UnshareThing(args[0], req, args[3], args[4]) if err != nil { logErrorCmd(*cmd, err) return @@ -246,13 +246,13 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "connect ", + Use: "connect ", Short: "Connect thing", Long: "Connect thing to the channel\n" + "Usage:\n" + - "\tmagistrala-cli things connect $USERTOKEN\n", + "\tmagistrala-cli things connect $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { + if len(args) != 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -261,7 +261,7 @@ var cmdThings = []cobra.Command{ ChannelID: args[1], ThingID: args[0], } - if err := sdk.Connect(connIDs, args[2]); err != nil { + if err := sdk.Connect(connIDs, args[2], args[3]); err != nil { logErrorCmd(*cmd, err) return } @@ -270,13 +270,13 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "disconnect ", + Use: "disconnect ", Short: "Disconnect thing", Long: "Disconnect thing to the channel\n" + "Usage:\n" + - "\tmagistrala-cli things disconnect $USERTOKEN\n", + "\tmagistrala-cli things disconnect $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { + if len(args) != 4 { logUsageCmd(*cmd, cmd.Use) return } @@ -285,7 +285,7 @@ var cmdThings = []cobra.Command{ ThingID: args[0], ChannelID: args[1], } - if err := sdk.Disconnect(connIDs, args[2]); err != nil { + if err := sdk.Disconnect(connIDs, args[2], args[3]); err != nil { logErrorCmd(*cmd, err) return } @@ -294,13 +294,13 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "connections ", + Use: "connections ", Short: "Connected list", Long: "List of Channels connected to Thing\n" + "Usage:\n" + - "\tmagistrala-cli connections $USERTOKEN\n", + "\tmagistrala-cli connections $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } @@ -308,7 +308,7 @@ var cmdThings = []cobra.Command{ Offset: Offset, Limit: Limit, } - cl, err := sdk.ChannelsByThing(args[0], pm, args[1]) + cl, err := sdk.ChannelsByThing(args[0], pm, args[1], args[2]) if err != nil { logErrorCmd(*cmd, err) return @@ -318,21 +318,22 @@ var cmdThings = []cobra.Command{ }, }, { - Use: "users ", + Use: "users ", Short: "List users", Long: "List users of a thing\n" + "Usage:\n" + - "\tmagistrala-cli things users $USERTOKEN\n", + "\tmagistrala-cli things users $DOMAINID $USERTOKEN\n", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { + if len(args) != 3 { logUsageCmd(*cmd, cmd.Use) return } pm := mgxsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, + Offset: Offset, + Limit: Limit, + DomainID: args[1], } - ul, err := sdk.ListThingUsers(args[0], pm, args[1]) + ul, err := sdk.ListThingUsers(args[0], pm, args[2]) if err != nil { logErrorCmd(*cmd, err) return diff --git a/cli/things_test.go b/cli/things_test.go index 6a7bdcd182..7d40fbe5cd 100644 --- a/cli/things_test.go +++ b/cli/things_test.go @@ -24,6 +24,7 @@ import ( var ( token = "valid" + "domaintoken" + domainID = "domain-id" tokenWithoutDomain = "valid" relation = "administrator" all = "all" @@ -60,6 +61,7 @@ func TestCreateThingsCmd(t *testing.T) { desc: "create thing successfully with token", args: []string{ thingJson, + domainID, token, }, thing: thing, @@ -69,6 +71,7 @@ func TestCreateThingsCmd(t *testing.T) { desc: "create thing without token", args: []string{ thingJson, + domainID, }, logType: usageLog, }, @@ -76,6 +79,7 @@ func TestCreateThingsCmd(t *testing.T) { desc: "create thing with invalid token", args: []string{ thingJson, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -86,26 +90,18 @@ func TestCreateThingsCmd(t *testing.T) { desc: "failed to create thing", args: []string{ thingJson, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity)), logType: errLog, }, - { - desc: "create thing without domain token", - args: []string{ - thingJson, - tokenWithoutDomain, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), - logType: errLog, - }, { desc: "create thing with invalid metadata", args: []string{ "{\"name\":\"testthing\", \"metadata\":{\"key1\":value1}}", + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(errors.New("invalid character 'v' looking for beginning of value"), 306), @@ -116,7 +112,7 @@ func TestCreateThingsCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("CreateThing", mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) + sdkCall := sdkMock.On("CreateThing", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{createCmd}, tc.args...)...) switch tc.logType { @@ -157,6 +153,7 @@ func TestGetThingsCmd(t *testing.T) { desc: "get all things successfully", args: []string{ all, + domainID, token, }, logType: entityLog, @@ -168,6 +165,7 @@ func TestGetThingsCmd(t *testing.T) { desc: "get thing successfully with id", args: []string{ thing.ID, + domainID, token, }, logType: entityLog, @@ -177,6 +175,7 @@ func TestGetThingsCmd(t *testing.T) { desc: "get things with invalid token", args: []string{ all, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -184,16 +183,6 @@ func TestGetThingsCmd(t *testing.T) { page: sdk.ThingsPage{}, logType: errLog, }, - { - desc: "get thing without domain token", - args: []string{ - all, - tokenWithoutDomain, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), - logType: errLog, - }, { desc: "get things with invalid args", args: []string{ @@ -212,6 +201,7 @@ func TestGetThingsCmd(t *testing.T) { desc: "get thing without token", args: []string{ all, + domainID, }, logType: usageLog, }, @@ -219,6 +209,7 @@ func TestGetThingsCmd(t *testing.T) { desc: "get thing with invalid thing id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -229,8 +220,8 @@ func TestGetThingsCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Things", mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr) - sdkCall1 := sdkMock.On("Thing", mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) + sdkCall := sdkMock.On("Things", mock.Anything, mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr) + sdkCall1 := sdkMock.On("Thing", mock.Anything, mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) @@ -296,6 +287,7 @@ func TestUpdateThingCmd(t *testing.T) { args: []string{ thing.ID, newNameandMeta, + domainID, token, }, thing: sdk.Thing{ @@ -316,6 +308,7 @@ func TestUpdateThingCmd(t *testing.T) { args: []string{ thing.ID, "{\"name\": \"thingName\", \"metadata\": {\"role\": \"general\"}", + domainID, token, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), @@ -327,6 +320,7 @@ func TestUpdateThingCmd(t *testing.T) { args: []string{ invalidID, newNameandMeta, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -339,6 +333,7 @@ func TestUpdateThingCmd(t *testing.T) { tagUpdateType, thing.ID, newTagsJson, + domainID, token, }, thing: sdk.Thing{ @@ -356,6 +351,7 @@ func TestUpdateThingCmd(t *testing.T) { tagUpdateType, thing.ID, "[\"tag1\", \"tag2\"", + domainID, token, }, logType: errLog, @@ -368,6 +364,7 @@ func TestUpdateThingCmd(t *testing.T) { tagUpdateType, invalidID, newTagsJson, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -380,6 +377,7 @@ func TestUpdateThingCmd(t *testing.T) { secretUpdateType, thing.ID, newSecret, + domainID, token, }, thing: sdk.Thing{ @@ -399,6 +397,7 @@ func TestUpdateThingCmd(t *testing.T) { secretUpdateType, thing.ID, "", + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingSecret), http.StatusBadRequest), @@ -411,6 +410,7 @@ func TestUpdateThingCmd(t *testing.T) { secretUpdateType, thing.ID, newSecret, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -423,6 +423,7 @@ func TestUpdateThingCmd(t *testing.T) { secretUpdateType, thing.ID, newSecret, + domainID, token, extraArg, }, @@ -433,9 +434,9 @@ func TestUpdateThingCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var tg sdk.Thing - sdkCall := sdkMock.On("UpdateThing", mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) - sdkCall1 := sdkMock.On("UpdateThingTags", mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) - sdkCall2 := sdkMock.On("UpdateThingSecret", mock.Anything, mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) + sdkCall := sdkMock.On("UpdateThing", mock.Anything, mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) + sdkCall1 := sdkMock.On("UpdateThingTags", mock.Anything, mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) + sdkCall2 := sdkMock.On("UpdateThingSecret", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.thing, tc.sdkErr) switch { case tc.args[0] == tagUpdateType: @@ -488,6 +489,7 @@ func TestDeleteThingCmd(t *testing.T) { desc: "delete thing successfully", args: []string{ thing.ID, + domainID, token, }, logType: okLog, @@ -496,6 +498,7 @@ func TestDeleteThingCmd(t *testing.T) { desc: "delete thing with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -506,6 +509,7 @@ func TestDeleteThingCmd(t *testing.T) { desc: "delete thing with invalid thing id", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -516,6 +520,7 @@ func TestDeleteThingCmd(t *testing.T) { desc: "delete thing with invalid args", args: []string{ thing.ID, + domainID, token, extraArg, }, @@ -525,7 +530,7 @@ func TestDeleteThingCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("DeleteThing", tc.args[0], tc.args[1]).Return(tc.sdkErr) + sdkCall := sdkMock.On("DeleteThing", tc.args[0], tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{delCmd}, tc.args...)...) switch tc.logType { @@ -560,6 +565,7 @@ func TestEnableThingCmd(t *testing.T) { desc: "enable thing successfully", args: []string{ thing.ID, + domainID, validToken, }, sdkErr: nil, @@ -570,6 +576,7 @@ func TestEnableThingCmd(t *testing.T) { desc: "delete thing with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -580,6 +587,7 @@ func TestEnableThingCmd(t *testing.T) { desc: "delete thing with invalid thing ID", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -590,6 +598,7 @@ func TestEnableThingCmd(t *testing.T) { desc: "enable thing with invalid args", args: []string{ thing.ID, + domainID, validToken, extraArg, }, @@ -599,7 +608,7 @@ func TestEnableThingCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("EnableThing", tc.args[0], tc.args[1]).Return(tc.thing, tc.sdkErr) + sdkCall := sdkMock.On("EnableThing", tc.args[0], tc.args[1], tc.args[2]).Return(tc.thing, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{enableCmd}, tc.args...)...) switch tc.logType { @@ -638,6 +647,7 @@ func TestDisablethingCmd(t *testing.T) { desc: "disable thing successfully", args: []string{ thing.ID, + domainID, validToken, }, logType: entityLog, @@ -647,6 +657,7 @@ func TestDisablethingCmd(t *testing.T) { desc: "delete thing with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -657,6 +668,7 @@ func TestDisablethingCmd(t *testing.T) { desc: "delete thing with invalid thing ID", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -667,6 +679,7 @@ func TestDisablethingCmd(t *testing.T) { desc: "disable thing with invalid args", args: []string{ thing.ID, + domainID, validToken, extraArg, }, @@ -676,7 +689,7 @@ func TestDisablethingCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("DisableThing", tc.args[0], tc.args[1]).Return(tc.thing, tc.sdkErr) + sdkCall := sdkMock.On("DisableThing", tc.args[0], tc.args[1], tc.args[2]).Return(tc.thing, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{disableCmd}, tc.args...)...) switch tc.logType { @@ -717,6 +730,7 @@ func TestUsersThingCmd(t *testing.T) { desc: "get thing's users successfully", args: []string{ thing.ID, + domainID, token, }, page: sdk.UsersPage{ @@ -733,16 +747,18 @@ func TestUsersThingCmd(t *testing.T) { desc: "list thing users' with invalid args", args: []string{ thing.ID, + domainID, token, extraArg, }, logType: usageLog, }, { - desc: "list thing users' without domain token", + desc: "list thing users' with invalid domain", args: []string{ thing.ID, - tokenWithoutDomain, + invalidID, + token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), @@ -752,22 +768,13 @@ func TestUsersThingCmd(t *testing.T) { desc: "list thing 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, }, - { - desc: "list thing users' without domain token", - args: []string{ - thing.ID, - tokenWithoutDomain, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), - logType: errLog, - }, } for _, tc := range cases { @@ -810,6 +817,7 @@ func TestConnectThingCmd(t *testing.T) { args: []string{ thing.ID, channel.ID, + domainID, token, }, logType: okLog, @@ -819,6 +827,7 @@ func TestConnectThingCmd(t *testing.T) { args: []string{ thing.ID, channel.ID, + domainID, token, extraArg, }, @@ -829,6 +838,7 @@ func TestConnectThingCmd(t *testing.T) { args: []string{ invalidID, channel.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -840,6 +850,7 @@ func TestConnectThingCmd(t *testing.T) { args: []string{ thing.ID, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -847,11 +858,12 @@ func TestConnectThingCmd(t *testing.T) { logType: errLog, }, { - desc: "list thing users' without domain token", + desc: "list thing users' with invalid domain", args: []string{ thing.ID, channel.ID, - tokenWithoutDomain, + invalidID, + token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), @@ -861,7 +873,7 @@ func TestConnectThingCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Connect", mock.Anything, tc.args[2]).Return(tc.sdkErr) + sdkCall := sdkMock.On("Connect", mock.Anything, tc.args[2], tc.args[3]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{connCmd}, tc.args...)...) switch tc.logType { @@ -895,6 +907,7 @@ func TestDisconnectThingCmd(t *testing.T) { args: []string{ thing.ID, channel.ID, + domainID, token, }, logType: okLog, @@ -904,6 +917,7 @@ func TestDisconnectThingCmd(t *testing.T) { args: []string{ thing.ID, channel.ID, + domainID, token, extraArg, }, @@ -914,6 +928,7 @@ func TestDisconnectThingCmd(t *testing.T) { args: []string{ invalidID, channel.ID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -925,6 +940,7 @@ func TestDisconnectThingCmd(t *testing.T) { args: []string{ thing.ID, invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -932,11 +948,12 @@ func TestDisconnectThingCmd(t *testing.T) { logType: errLog, }, { - desc: "disconnect thing without domain token", + desc: "disconnect thing with invalid domain", args: []string{ thing.ID, channel.ID, - tokenWithoutDomain, + invalidID, + token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrDomainAuthorization, http.StatusForbidden)), @@ -946,7 +963,7 @@ func TestDisconnectThingCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Disconnect", mock.Anything, tc.args[2]).Return(tc.sdkErr) + sdkCall := sdkMock.On("Disconnect", mock.Anything, tc.args[2], tc.args[3]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{disconnCmd}, tc.args...)...) switch tc.logType { @@ -981,6 +998,7 @@ func TestListConnectionCmd(t *testing.T) { desc: "list connections successfully", args: []string{ thing.ID, + domainID, token, }, page: sdk.ChannelsPage{ @@ -997,6 +1015,7 @@ func TestListConnectionCmd(t *testing.T) { desc: "list connections with invalid args", args: []string{ thing.ID, + domainID, token, extraArg, }, @@ -1006,6 +1025,7 @@ func TestListConnectionCmd(t *testing.T) { desc: "list connections with invalid thing ID", args: []string{ invalidID, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -1016,6 +1036,7 @@ func TestListConnectionCmd(t *testing.T) { desc: "list connections with invalid token", args: []string{ thing.ID, + domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), @@ -1025,7 +1046,7 @@ func TestListConnectionCmd(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ChannelsByThing", tc.args[0], mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) + sdkCall := sdkMock.On("ChannelsByThing", tc.args[0], mock.Anything, tc.args[1], tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{connsCmd}, tc.args...)...) switch tc.logType { @@ -1065,6 +1086,7 @@ func TestShareThingCmd(t *testing.T) { thing.ID, user.ID, relation, + domainID, token, }, logType: okLog, @@ -1075,6 +1097,7 @@ func TestShareThingCmd(t *testing.T) { thing.ID, invalidID, relation, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAddPolicies, http.StatusBadRequest), @@ -1087,6 +1110,7 @@ func TestShareThingCmd(t *testing.T) { invalidID, user.ID, relation, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -1099,6 +1123,7 @@ func TestShareThingCmd(t *testing.T) { thing.ID, user.ID, relation, + domainID, token, extraArg, }, @@ -1110,6 +1135,7 @@ func TestShareThingCmd(t *testing.T) { thing.ID, user.ID, "invalid", + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusBadRequest), @@ -1119,7 +1145,7 @@ func TestShareThingCmd(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ShareThing", tc.args[0], mock.Anything, tc.args[3]).Return(tc.sdkErr) + sdkCall := sdkMock.On("ShareThing", tc.args[0], mock.Anything, tc.args[3], tc.args[4]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{shrCmd}, tc.args...)...) switch tc.logType { @@ -1154,6 +1180,7 @@ func TestUnshareThingCmd(t *testing.T) { thing.ID, user.ID, relation, + domainID, token, }, logType: okLog, @@ -1164,6 +1191,7 @@ func TestUnshareThingCmd(t *testing.T) { invalidID, user.ID, relation, + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), @@ -1176,6 +1204,7 @@ func TestUnshareThingCmd(t *testing.T) { thing.ID, user.ID, relation, + domainID, token, extraArg, }, @@ -1187,6 +1216,7 @@ func TestUnshareThingCmd(t *testing.T) { thing.ID, user.ID, "invalid", + domainID, token, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusBadRequest), @@ -1196,7 +1226,7 @@ func TestUnshareThingCmd(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("UnshareThing", tc.args[0], mock.Anything, tc.args[3]).Return(tc.sdkErr) + sdkCall := sdkMock.On("UnshareThing", tc.args[0], mock.Anything, tc.args[3], tc.args[4]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{unshrCmd}, tc.args...)...) switch tc.logType { diff --git a/consumers/notifiers/api/transport.go b/consumers/notifiers/api/transport.go index af604d654e..2f6e258b44 100644 --- a/consumers/notifiers/api/transport.go +++ b/consumers/notifiers/api/transport.go @@ -75,7 +75,6 @@ func MakeHandler(svc notifiers.Service, logger *slog.Logger, instanceID string) opts..., ), "delete").ServeHTTP) }) - mux.Get("/health", magistrala.Health("notifier", instanceID)) mux.Handle("/metrics", promhttp.Handler()) diff --git a/http/api/transport.go b/http/api/transport.go index d59155dae7..52ed24208a 100644 --- a/http/api/transport.go +++ b/http/api/transport.go @@ -46,7 +46,6 @@ func MakeHandler(logger *slog.Logger, instanceID string) http.Handler { api.EncodeResponse, opts..., ), "publish").ServeHTTP) - r.Get("/health", magistrala.Health("http", instanceID)) r.Handle("/metrics", promhttp.Handler()) @@ -60,7 +59,6 @@ func decodeRequest(_ context.Context, r *http.Request) (interface{}, error) { } var req publishReq - _, pass, ok := r.BasicAuth() switch { case ok: diff --git a/internal/api/auth.go b/internal/api/auth.go index 631073ce5d..086bb99a04 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -9,6 +9,7 @@ import ( "github.com/absmach/magistrala/pkg/apiutil" mgauthn "github.com/absmach/magistrala/pkg/authn" + "github.com/go-chi/chi/v5" ) type sessionKeyType string @@ -36,3 +37,36 @@ func AuthenticateMiddleware(authn mgauthn.Authentication) func(http.Handler) htt }) } } + +func AuthenticateMiddlewareDomain(authn mgauthn.Authentication) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := apiutil.ExtractBearerToken(r) + if token == "" { + EncodeError(r.Context(), apiutil.ErrBearerToken, w) + return + } + domain := chi.URLParam(r, "domainID") + if domain == "" { + EncodeError(r.Context(), apiutil.ErrMissingDomainID, w) + return + } + + resp, err := authn.Authenticate(r.Context(), token) + if err != nil { + EncodeError(r.Context(), err, w) + return + } + + if domain != resp.DomainID { + resp = mgauthn.Session{} + EncodeError(r.Context(), apiutil.ErrValidation, w) + return + } + + ctx := context.WithValue(r.Context(), SessionKey, resp) + + next.ServeHTTP(w, r.WithContext(ctx)) + }) + } +} diff --git a/internal/api/common.go b/internal/api/common.go index 891fb31c70..facb67a68c 100644 --- a/internal/api/common.go +++ b/internal/api/common.go @@ -164,6 +164,7 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) { errors.Contains(err, svcerr.ErrSearch), errors.Contains(err, apiutil.ErrEmptySearchQuery), errors.Contains(err, apiutil.ErrLenSearchQuery), + errors.Contains(err, apiutil.ErrMissingDomainID), errors.Contains(err, certs.ErrFailedReadFromPKI): err = unwrap(err) w.WriteHeader(http.StatusBadRequest) diff --git a/invitations/api/endpoint.go b/invitations/api/endpoint.go index e030efe86d..580391b631 100644 --- a/invitations/api/endpoint.go +++ b/invitations/api/endpoint.go @@ -105,7 +105,7 @@ func acceptInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { return nil, svcerr.ErrAuthorization } - if err := svc.AcceptInvitation(ctx, session, req.DomainID); err != nil { + if err := svc.AcceptInvitation(ctx, session, req.domainID); err != nil { return nil, err } @@ -125,7 +125,7 @@ func rejectInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { return nil, svcerr.ErrAuthorization } - if err := svc.RejectInvitation(ctx, session, req.DomainID); err != nil { + if err := svc.RejectInvitation(ctx, session, req.domainID); err != nil { return nil, err } diff --git a/invitations/api/endpoint_test.go b/invitations/api/endpoint_test.go index 20ffc4991d..e4b5dbe135 100644 --- a/invitations/api/endpoint_test.go +++ b/invitations/api/endpoint_test.go @@ -28,6 +28,7 @@ var ( validToken = "valid" validContenType = "application/json" validID = testsutil.GenerateUUID(&testing.T{}) + domainID = testsutil.GenerateUUID(&testing.T{}) ) type testRequest struct { @@ -69,6 +70,7 @@ func TestSendInvitation(t *testing.T) { cases := []struct { desc string + domainID string token string data string contentType string @@ -79,8 +81,9 @@ func TestSendInvitation(t *testing.T) { }{ { desc: "valid request", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"user_id": "%s", "domain_id": "%s", "relation": "%s"}`, validID, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, status: http.StatusCreated, contentType: validContenType, @@ -88,22 +91,34 @@ func TestSendInvitation(t *testing.T) { }, { desc: "invalid token", + domainID: domainID, token: "", - data: fmt.Sprintf(`{"user_id": "%s", "domain_id": "%s", "relation": "%s"}`, validID, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), status: http.StatusUnauthorized, contentType: validContenType, svcErr: nil, }, + { + desc: "empty domain_id", + domainID: "", + token: validToken, + data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), + status: http.StatusBadRequest, + contentType: validContenType, + svcErr: nil, + }, { desc: "invalid content type", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"user_id": "%s", "domain_id": "%s", "relation": "%s"}`, validID, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), status: http.StatusUnsupportedMediaType, contentType: "text/plain", svcErr: nil, }, { desc: "invalid data", + domainID: domainID, token: validToken, data: `data`, status: http.StatusBadRequest, @@ -112,8 +127,9 @@ func TestSendInvitation(t *testing.T) { }, { desc: "with service error", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"user_id": "%s", "domain_id": "%s", "relation": "%s"}`, validID, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), status: http.StatusForbidden, contentType: validContenType, svcErr: svcerr.ErrAuthorization, @@ -121,22 +137,24 @@ func TestSendInvitation(t *testing.T) { } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("SendInvitation", mock.Anything, tc.authnRes, mock.Anything).Return(tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodPost, - url: is.URL + "/invitations", - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(tc.data), - } - - res, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, res.StatusCode, tc.desc) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("SendInvitation", mock.Anything, tc.authnRes, mock.Anything).Return(tc.svcErr) + req := testRequest{ + client: is.Client(), + method: http.MethodPost, + url: is.URL + "/" + tc.domainID + "/invitations", + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(tc.data), + } + + res, err := req.make() + assert.Nil(t, err, tc.desc) + assert.Equal(t, tc.status, res.StatusCode, tc.desc) + repoCall.Unset() + authnCall.Unset() + }) } } @@ -145,6 +163,7 @@ func TestListInvitation(t *testing.T) { cases := []struct { desc string + domainID string token string query string contentType string @@ -155,6 +174,7 @@ func TestListInvitation(t *testing.T) { }{ { desc: "valid request", + domainID: domainID, token: validToken, status: http.StatusOK, contentType: validContenType, @@ -162,6 +182,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "invalid token", + domainID: domainID, token: "", status: http.StatusUnauthorized, contentType: validContenType, @@ -169,6 +190,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with offset", + domainID: domainID, token: validToken, query: "offset=1", status: http.StatusOK, @@ -177,6 +199,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invalid offset", + domainID: domainID, token: validToken, query: "offset=invalid", status: http.StatusBadRequest, @@ -185,6 +208,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with limit", + domainID: domainID, token: validToken, query: "limit=1", status: http.StatusOK, @@ -193,6 +217,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invalid limit", + domainID: domainID, token: validToken, query: "limit=invalid", status: http.StatusBadRequest, @@ -201,6 +226,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with user_id", + domainID: domainID, token: validToken, query: fmt.Sprintf("user_id=%s", validID), status: http.StatusOK, @@ -209,6 +235,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate user_id", + domainID: domainID, token: validToken, query: "user_id=1&user_id=2", status: http.StatusBadRequest, @@ -217,6 +244,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invited_by", + domainID: domainID, token: validToken, query: fmt.Sprintf("invited_by=%s", validID), status: http.StatusOK, @@ -225,6 +253,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate invited_by", + domainID: domainID, token: validToken, query: "invited_by=1&invited_by=2", status: http.StatusBadRequest, @@ -233,6 +262,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with relation", + domainID: domainID, token: validToken, query: fmt.Sprintf("relation=%s", "relation"), status: http.StatusOK, @@ -241,6 +271,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate relation", + domainID: domainID, token: validToken, query: "relation=1&relation=2", status: http.StatusBadRequest, @@ -248,23 +279,16 @@ func TestListInvitation(t *testing.T) { svcErr: nil, }, { - desc: "with domain_id", - token: validToken, - query: fmt.Sprintf("domain_id=%s", validID), - status: http.StatusOK, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "with duplicate domain_id", + desc: "with empty domain_id", + domainID: "", token: validToken, - query: "domain_id=1&domain_id=2", status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, }, { desc: "with state", + domainID: domainID, token: validToken, query: "state=pending", status: http.StatusOK, @@ -273,6 +297,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invalid state", + domainID: domainID, token: validToken, query: "state=invalid", status: http.StatusBadRequest, @@ -281,6 +306,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate state", + domainID: domainID, token: validToken, query: "state=all&state=all", status: http.StatusBadRequest, @@ -289,6 +315,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with service error", + domainID: domainID, token: validToken, status: http.StatusForbidden, contentType: validContenType, @@ -297,20 +324,22 @@ func TestListInvitation(t *testing.T) { } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("ListInvitations", mock.Anything, tc.authnRes, mock.Anything).Return(invitations.InvitationPage{}, tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodGet, - url: is.URL + "/invitations?" + tc.query, - token: tc.token, - contentType: tc.contentType, - } - res, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, res.StatusCode, tc.desc) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("ListInvitations", mock.Anything, tc.authnRes, mock.Anything).Return(invitations.InvitationPage{}, tc.svcErr) + req := testRequest{ + client: is.Client(), + method: http.MethodGet, + url: is.URL + "/" + tc.domainID + "/invitations?" + tc.query, + token: tc.token, + contentType: tc.contentType, + } + res, err := req.make() + assert.Nil(t, err, tc.desc) + assert.Equal(t, tc.status, res.StatusCode, tc.desc) + repoCall.Unset() + authnCall.Unset() + }) } } @@ -360,7 +389,7 @@ func TestViewInvitation(t *testing.T) { token: validToken, userID: "", domainID: validID, - status: http.StatusBadRequest, + status: http.StatusNotFound, contentType: validContenType, svcErr: nil, }, @@ -369,7 +398,7 @@ func TestViewInvitation(t *testing.T) { token: validToken, userID: validID, domainID: "", - status: http.StatusNotFound, + status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, }, @@ -385,21 +414,23 @@ func TestViewInvitation(t *testing.T) { } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("ViewInvitation", mock.Anything, tc.authnRes, tc.userID, tc.domainID).Return(invitations.Invitation{}, tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodGet, - url: is.URL + "/invitations/" + tc.userID + "/" + tc.domainID, - token: tc.token, - contentType: tc.contentType, - } - - res, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, res.StatusCode, tc.desc) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("ViewInvitation", mock.Anything, tc.authnRes, tc.userID, tc.domainID).Return(invitations.Invitation{}, tc.svcErr) + req := testRequest{ + client: is.Client(), + method: http.MethodGet, + url: is.URL + "/" + tc.domainID + "/invitations/users/" + tc.userID, + token: tc.token, + contentType: tc.contentType, + } + + res, err := req.make() + assert.Nil(t, err, tc.desc) + assert.Equal(t, tc.status, res.StatusCode, tc.desc) + repoCall.Unset() + authnCall.Unset() + }) } } @@ -450,7 +481,7 @@ func TestDeleteInvitation(t *testing.T) { token: validToken, userID: "", domainID: validID, - status: http.StatusBadRequest, + status: http.StatusNotFound, contentType: validContenType, svcErr: nil, }, @@ -459,7 +490,7 @@ func TestDeleteInvitation(t *testing.T) { token: validToken, userID: validID, domainID: "", - status: http.StatusNotFound, + status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, }, @@ -475,21 +506,23 @@ func TestDeleteInvitation(t *testing.T) { } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("DeleteInvitation", mock.Anything, tc.authnRes, tc.userID, tc.domainID).Return(tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodDelete, - url: is.URL + "/invitations/" + tc.userID + "/" + tc.domainID, - token: tc.token, - contentType: tc.contentType, - } - - res, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, res.StatusCode, tc.desc) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("DeleteInvitation", mock.Anything, tc.authnRes, tc.userID, tc.domainID).Return(tc.svcErr) + req := testRequest{ + client: is.Client(), + method: http.MethodDelete, + url: is.URL + "/" + tc.domainID + "/invitations/users/" + tc.userID, + token: tc.token, + contentType: tc.contentType, + } + + res, err := req.make() + assert.Nil(t, err, tc.desc) + assert.Equal(t, tc.status, res.StatusCode, tc.desc) + repoCall.Unset() + authnCall.Unset() + }) } } @@ -498,6 +531,7 @@ func TestAcceptInvitation(t *testing.T) { _ = authn cases := []struct { desc string + domainID string token string data string contentType string @@ -508,40 +542,40 @@ func TestAcceptInvitation(t *testing.T) { }{ { desc: "valid request", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusNoContent, contentType: validContenType, svcErr: nil, }, { desc: "invalid token", + domainID: domainID, token: "", - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusUnauthorized, contentType: validContenType, svcErr: nil, }, { desc: "with service error", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusForbidden, contentType: validContenType, svcErr: svcerr.ErrAuthorization, }, { desc: "invalid content type", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusUnsupportedMediaType, contentType: "text/plain", svcErr: nil, }, { - desc: "invalid data", + desc: "empty domain", + domainID: "", token: validToken, - data: `data`, status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, @@ -549,22 +583,23 @@ func TestAcceptInvitation(t *testing.T) { } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("AcceptInvitation", mock.Anything, tc.authnRes, mock.Anything).Return(tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodPost, - url: is.URL + "/invitations/accept", - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(tc.data), - } - - res, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, res.StatusCode, tc.desc) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("AcceptInvitation", mock.Anything, tc.authnRes, mock.Anything).Return(tc.svcErr) + req := testRequest{ + client: is.Client(), + method: http.MethodPost, + url: is.URL + "/" + tc.domainID + "/invitations/accept", + token: tc.token, + contentType: tc.contentType, + } + + res, err := req.make() + assert.Nil(t, err, tc.desc) + assert.Equal(t, tc.status, res.StatusCode, tc.desc) + repoCall.Unset() + authnCall.Unset() + }) } } @@ -574,8 +609,8 @@ func TestRejectInvitation(t *testing.T) { cases := []struct { desc string + domainID string token string - data string contentType string status int svcErr error @@ -584,40 +619,40 @@ func TestRejectInvitation(t *testing.T) { }{ { desc: "valid request", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusNoContent, contentType: validContenType, svcErr: nil, }, { desc: "invalid token", + domainID: domainID, token: "", - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusUnauthorized, contentType: validContenType, svcErr: nil, }, { desc: "unauthorized error", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"domain_id": "%s"}`, "invalid"), status: http.StatusForbidden, contentType: validContenType, svcErr: svcerr.ErrAuthorization, }, { desc: "invalid content type", + domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), status: http.StatusUnsupportedMediaType, contentType: "text/plain", svcErr: nil, }, { - desc: "invalid data", + desc: "empty domain", + domainID: "", token: validToken, - data: `data`, status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, @@ -625,21 +660,22 @@ func TestRejectInvitation(t *testing.T) { } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("RejectInvitation", mock.Anything, tc.authnRes, mock.Anything).Return(tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodPost, - url: is.URL + "/invitations/reject", - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(tc.data), - } - - res, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, res.StatusCode, tc.desc) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("RejectInvitation", mock.Anything, tc.authnRes, mock.Anything).Return(tc.svcErr) + req := testRequest{ + client: is.Client(), + method: http.MethodPost, + url: is.URL + "/" + tc.domainID + "/invitations/reject", + token: tc.token, + contentType: tc.contentType, + } + + res, err := req.make() + assert.Nil(t, err, tc.desc) + assert.Equal(t, tc.status, res.StatusCode, tc.desc) + repoCall.Unset() + authnCall.Unset() + }) } } diff --git a/invitations/api/requests.go b/invitations/api/requests.go index 2379b8540a..2d7a030734 100644 --- a/invitations/api/requests.go +++ b/invitations/api/requests.go @@ -4,20 +4,16 @@ package api import ( - "errors" - "github.com/absmach/magistrala/invitations" "github.com/absmach/magistrala/pkg/apiutil" ) const maxLimitSize = 100 -var errMissingDomain = errors.New("missing domain") - type sendInvitationReq struct { token string - UserID string `json:"user_id,omitempty"` DomainID string `json:"domain_id,omitempty"` + UserID string `json:"user_id,omitempty"` Relation string `json:"relation,omitempty"` Resend bool `json:"resend,omitempty"` } @@ -30,7 +26,7 @@ func (req *sendInvitationReq) validate() error { return apiutil.ErrMissingID } if req.DomainID == "" { - return errMissingDomain + return apiutil.ErrMissingDomainID } if err := invitations.CheckRelation(req.Relation); err != nil { return err @@ -48,6 +44,10 @@ func (req *listInvitationsReq) validate() error { if req.token == "" { return apiutil.ErrBearerToken } + if req.Page.DomainID == "" { + return apiutil.ErrMissingDomainID + } + if req.Page.Limit > maxLimitSize || req.Page.Limit < 1 { return apiutil.ErrLimitSize } @@ -57,15 +57,15 @@ func (req *listInvitationsReq) validate() error { type acceptInvitationReq struct { token string - DomainID string `json:"domain_id,omitempty"` + domainID string } func (req *acceptInvitationReq) validate() error { if req.token == "" { return apiutil.ErrBearerToken } - if req.DomainID == "" { - return errMissingDomain + if req.domainID == "" { + return apiutil.ErrMissingDomainID } return nil @@ -85,7 +85,7 @@ func (req *invitationReq) validate() error { return apiutil.ErrMissingID } if req.domainID == "" { - return errMissingDomain + return apiutil.ErrMissingDomainID } return nil diff --git a/invitations/api/requests_test.go b/invitations/api/requests_test.go index 771c3085b1..0b94b67343 100644 --- a/invitations/api/requests_test.go +++ b/invitations/api/requests_test.go @@ -63,7 +63,7 @@ func TestSendInvitationReqValidation(t *testing.T) { Relation: policies.DomainRelation, Resend: true, }, - err: errMissingDomain, + err: apiutil.ErrMissingDomainID, }, { desc: "missing relation", @@ -90,8 +90,10 @@ func TestSendInvitationReqValidation(t *testing.T) { } for _, tc := range cases { - err := tc.req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + }) } } @@ -105,15 +107,29 @@ func TestListInvitationsReq(t *testing.T) { desc: "valid request", req: listInvitationsReq{ token: valid, - Page: invitations.Page{Limit: 1}, + Page: invitations.Page{ + Limit: 1, + DomainID: valid, + }, }, err: nil, }, + { + desc: "empty domainID", + req: listInvitationsReq{ + token: valid, + Page: invitations.Page{Limit: 1}, + }, + err: apiutil.ErrMissingDomainID, + }, { desc: "empty token", req: listInvitationsReq{ token: "", - Page: invitations.Page{Limit: 1}, + Page: invitations.Page{ + Limit: 1, + DomainID: valid, + }, }, err: apiutil.ErrBearerToken, }, @@ -121,15 +137,20 @@ func TestListInvitationsReq(t *testing.T) { desc: "invalid limit", req: listInvitationsReq{ token: valid, - Page: invitations.Page{Limit: 1000}, + Page: invitations.Page{ + Limit: 1000, + DomainID: valid, + }, }, err: apiutil.ErrLimitSize, }, } for _, tc := range cases { - err := tc.req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + }) } } @@ -143,7 +164,7 @@ func TestAcceptInvitationReq(t *testing.T) { desc: "valid request", req: acceptInvitationReq{ token: valid, - DomainID: valid, + domainID: valid, }, err: nil, }, @@ -158,15 +179,17 @@ func TestAcceptInvitationReq(t *testing.T) { desc: "empty domain_id", req: acceptInvitationReq{ token: valid, - DomainID: "", + domainID: "", }, - err: errMissingDomain, + err: apiutil.ErrMissingDomainID, }, } for _, tc := range cases { - err := tc.req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + }) } } @@ -210,12 +233,14 @@ func TestInvitationReqValidation(t *testing.T) { userID: valid, domainID: "", }, - err: errMissingDomain, + err: apiutil.ErrMissingDomainID, }, } for _, tc := range cases { - err := tc.req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) + }) } } diff --git a/invitations/api/transport.go b/invitations/api/transport.go index 259ae470d2..c51d49c90f 100644 --- a/invitations/api/transport.go +++ b/invitations/api/transport.go @@ -40,7 +40,7 @@ func MakeHandler(svc invitations.Service, logger *slog.Logger, authn mgauthn.Aut mux.Group(func(r chi.Router) { r.Use(api.AuthenticateMiddleware(authn)) - r.Route("/invitations", func(r chi.Router) { + r.Route("/{domainID}/invitations", func(r chi.Router) { r.Post("/", otelhttp.NewHandler(kithttp.NewServer( sendInvitationEndpoint(svc), decodeSendInvitationReq, @@ -53,7 +53,7 @@ func MakeHandler(svc invitations.Service, logger *slog.Logger, authn mgauthn.Aut api.EncodeResponse, opts..., ), "list_invitations").ServeHTTP) - r.Route("/{user_id}/{domain_id}", func(r chi.Router) { + r.Route("/users/{user_id}", func(r chi.Router) { r.Get("/", otelhttp.NewHandler(kithttp.NewServer( viewInvitationEndpoint(svc), decodeInvitationReq, @@ -94,6 +94,7 @@ func decodeSendInvitationReq(_ context.Context, r *http.Request) (interface{}, e } var req sendInvitationReq + req.DomainID = chi.URLParam(r, "domainID") if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) } @@ -123,10 +124,6 @@ func decodeListInvitationsReq(_ context.Context, r *http.Request) (interface{}, if err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) } - domainID, err := apiutil.ReadStringQuery(r, domainIDKey, "") - if err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } st, err := apiutil.ReadStringQuery(r, stateKey, invitations.All.String()) if err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) @@ -144,7 +141,7 @@ func decodeListInvitationsReq(_ context.Context, r *http.Request) (interface{}, InvitedBy: invitedBy, UserID: userID, Relation: relation, - DomainID: domainID, + DomainID: chi.URLParam(r, "domainID"), State: state, }, } @@ -157,20 +154,17 @@ func decodeAcceptInvitationReq(_ context.Context, r *http.Request) (interface{}, return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) } - var req acceptInvitationReq - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) - } - req.token = apiutil.ExtractBearerToken(r) - - return req, nil + return acceptInvitationReq{ + token: apiutil.ExtractBearerToken(r), + domainID: chi.URLParam(r, "domainID"), + }, nil } func decodeInvitationReq(_ context.Context, r *http.Request) (interface{}, error) { req := invitationReq{ token: apiutil.ExtractBearerToken(r), userID: chi.URLParam(r, "user_id"), - domainID: chi.URLParam(r, "domain_id"), + domainID: chi.URLParam(r, "domainID"), } return req, nil diff --git a/invitations/service_test.go b/invitations/service_test.go index cd97b77c78..92538652c3 100644 --- a/invitations/service_test.go +++ b/invitations/service_test.go @@ -108,15 +108,17 @@ func TestSendInvitation(t *testing.T) { } for _, tc := range cases { - repocall1 := token.On("Issue", context.Background(), mock.Anything).Return(&magistrala.Token{AccessToken: tc.req.Token}, tc.issueErr) - repocall2 := repo.On("Create", context.Background(), mock.Anything).Return(tc.repoErr) - if tc.req.Resend { - repocall2 = repo.On("UpdateToken", context.Background(), mock.Anything).Return(tc.repoErr) - } - err := svc.SendInvitation(context.Background(), tc.session, tc.req) - assert.Equal(t, tc.err, err, tc.desc) - repocall1.Unset() - repocall2.Unset() + t.Run(tc.desc, func(t *testing.T) { + repocall1 := token.On("Issue", context.Background(), mock.Anything).Return(&magistrala.Token{AccessToken: tc.req.Token}, tc.issueErr) + repocall2 := repo.On("Create", context.Background(), mock.Anything).Return(tc.repoErr) + if tc.req.Resend { + repocall2 = repo.On("UpdateToken", context.Background(), mock.Anything).Return(tc.repoErr) + } + err := svc.SendInvitation(context.Background(), tc.session, tc.req) + assert.Equal(t, tc.err, err, tc.desc) + repocall1.Unset() + repocall2.Unset() + }) } } @@ -194,11 +196,13 @@ func TestViewInvitation(t *testing.T) { } for _, tc := range cases { - repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.repoErr) - inv, err := svc.ViewInvitation(context.Background(), tc.session, tc.userID, tc.domainID) - assert.Equal(t, tc.err, err, tc.desc) - assert.Equal(t, tc.resp, inv, tc.desc) - repocall1.Unset() + t.Run(tc.desc, func(t *testing.T) { + repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.repoErr) + inv, err := svc.ViewInvitation(context.Background(), tc.session, tc.userID, tc.domainID) + assert.Equal(t, tc.err, err, tc.desc) + assert.Equal(t, tc.resp, inv, tc.desc) + repocall1.Unset() + }) } } @@ -248,7 +252,6 @@ func TestListInvitations(t *testing.T) { { desc: "list invitations unsuccessful", session: authn.Session{DomainUserID: validDomainUserID, DomainID: validDomainID, UserID: validUserID}, - // page: invitations.Page{DomainID: testsutil.GenerateUUID(t)}, page: validPage, err: repoerr.ErrViewEntity, resp: invitations.InvitationPage{}, @@ -257,11 +260,13 @@ func TestListInvitations(t *testing.T) { } for _, tc := range cases { - repocall1 := repo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.resp, tc.repoErr) - resp, err := svc.ListInvitations(context.Background(), tc.session, tc.page) - assert.Equal(t, tc.err, err, tc.desc) - assert.Equal(t, tc.resp, resp, tc.desc) - repocall1.Unset() + t.Run(tc.desc, func(t *testing.T) { + repocall1 := repo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.resp, tc.repoErr) + resp, err := svc.ListInvitations(context.Background(), tc.session, tc.page) + assert.Equal(t, tc.err, err, tc.desc) + assert.Equal(t, tc.resp, resp, tc.desc) + repocall1.Unset() + }) } } @@ -368,14 +373,16 @@ func TestAcceptInvitation(t *testing.T) { } for _, tc := range cases { - repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, tc.domainID).Return(tc.resp, tc.repoErr) - sdkcall := sdksvc.On("AddUserToDomain", mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) - repocall2 := repo.On("UpdateConfirmation", context.Background(), mock.Anything).Return(tc.repoErr1) - err := svc.AcceptInvitation(context.Background(), tc.session, tc.domainID) - assert.Equal(t, tc.err, err, tc.desc) - repocall1.Unset() - sdkcall.Unset() - repocall2.Unset() + t.Run(tc.desc, func(t *testing.T) { + repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, tc.domainID).Return(tc.resp, tc.repoErr) + sdkcall := sdksvc.On("AddUserToDomain", mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) + repocall2 := repo.On("UpdateConfirmation", context.Background(), mock.Anything).Return(tc.repoErr1) + err := svc.AcceptInvitation(context.Background(), tc.session, tc.domainID) + assert.Equal(t, tc.err, err, tc.desc) + repocall1.Unset() + sdkcall.Unset() + repocall2.Unset() + }) } } @@ -431,12 +438,14 @@ func TestDeleteInvitation(t *testing.T) { } for _, tc := range cases { - repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.repoErr) - repocall2 := repo.On("Delete", context.Background(), mock.Anything, mock.Anything).Return(tc.repoErr) - err := svc.DeleteInvitation(context.Background(), authn.Session{}, tc.userID, tc.domainID) - assert.Equal(t, tc.err, err, tc.desc) - repocall1.Unset() - repocall2.Unset() + t.Run(tc.desc, func(t *testing.T) { + repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.repoErr) + repocall2 := repo.On("Delete", context.Background(), mock.Anything, mock.Anything).Return(tc.repoErr) + err := svc.DeleteInvitation(context.Background(), authn.Session{}, tc.userID, tc.domainID) + assert.Equal(t, tc.err, err, tc.desc) + repocall1.Unset() + repocall2.Unset() + }) } } @@ -494,11 +503,13 @@ func TestRejectInvitation(t *testing.T) { } for _, tc := range cases { - repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.repoErr) - repocall3 := repo.On("UpdateRejection", context.Background(), mock.Anything).Return(tc.repoErr1) - err := svc.RejectInvitation(context.Background(), tc.session, tc.domainID) - assert.Equal(t, tc.err, err, tc.desc) - repocall1.Unset() - repocall3.Unset() + t.Run(tc.desc, func(t *testing.T) { + repocall1 := repo.On("Retrieve", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.repoErr) + repocall3 := repo.On("UpdateRejection", context.Background(), mock.Anything).Return(tc.repoErr1) + err := svc.RejectInvitation(context.Background(), tc.session, tc.domainID) + assert.Equal(t, tc.err, err, tc.desc) + repocall1.Unset() + repocall3.Unset() + }) } } diff --git a/pkg/apiutil/errors.go b/pkg/apiutil/errors.go index cceba23528..f9b96af53c 100644 --- a/pkg/apiutil/errors.go +++ b/pkg/apiutil/errors.go @@ -185,4 +185,7 @@ var ( // ErrLenSearchQuery indicates search query length. ErrLenSearchQuery = errors.New("search query must be at least 3 characters") + + // ErrMissingDomainID indicates missing domainID. + ErrMissingDomainID = errors.New("missing domainID") ) diff --git a/pkg/sdk/go/bootstrap.go b/pkg/sdk/go/bootstrap.go index c9639df9a7..0719f8e053 100644 --- a/pkg/sdk/go/bootstrap.go +++ b/pkg/sdk/go/bootstrap.go @@ -95,13 +95,13 @@ func (ts *BootstrapConfig) UnmarshalJSON(data []byte) error { return nil } -func (sdk mgSDK) AddBootstrap(cfg BootstrapConfig, token string) (string, errors.SDKError) { +func (sdk mgSDK) AddBootstrap(cfg BootstrapConfig, domainID, token string) (string, errors.SDKError) { data, err := json.Marshal(cfg) if err != nil { return "", errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.bootstrapURL, configsEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint) headers, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK, http.StatusCreated) if sdkerr != nil { @@ -114,7 +114,8 @@ func (sdk mgSDK) AddBootstrap(cfg BootstrapConfig, token string) (string, errors } func (sdk mgSDK) Bootstraps(pm PageMetadata, token string) (BootstrapPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.bootstrapURL, configsEndpoint, pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, configsEndpoint) + url, err := sdk.withQueryParams(sdk.bootstrapURL, endpoint, pm) if err != nil { return BootstrapPage{}, errors.NewSDKError(err) } @@ -132,7 +133,7 @@ func (sdk mgSDK) Bootstraps(pm PageMetadata, token string) (BootstrapPage, error return bb, nil } -func (sdk mgSDK) Whitelist(thingID string, state int, token string) errors.SDKError { +func (sdk mgSDK) Whitelist(thingID string, state int, domainID, token string) errors.SDKError { if thingID == "" { return errors.NewSDKError(apiutil.ErrMissingID) } @@ -142,18 +143,18 @@ func (sdk mgSDK) Whitelist(thingID string, state int, token string) errors.SDKEr return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, whitelistEndpoint, thingID) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, whitelistEndpoint, thingID) _, _, sdkerr := sdk.processRequest(http.MethodPut, url, token, data, nil, http.StatusCreated, http.StatusOK) return sdkerr } -func (sdk mgSDK) ViewBootstrap(id, token string) (BootstrapConfig, errors.SDKError) { +func (sdk mgSDK) ViewBootstrap(id, domainID, token string) (BootstrapConfig, errors.SDKError) { if id == "" { return BootstrapConfig{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, configsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint, id) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -168,11 +169,11 @@ func (sdk mgSDK) ViewBootstrap(id, token string) (BootstrapConfig, errors.SDKErr return bc, nil } -func (sdk mgSDK) UpdateBootstrap(cfg BootstrapConfig, token string) errors.SDKError { +func (sdk mgSDK) UpdateBootstrap(cfg BootstrapConfig, domainID, token string) errors.SDKError { if cfg.ThingID == "" { return errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, configsEndpoint, cfg.ThingID) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint, cfg.ThingID) data, err := json.Marshal(cfg) if err != nil { @@ -184,11 +185,11 @@ func (sdk mgSDK) UpdateBootstrap(cfg BootstrapConfig, token string) errors.SDKEr return sdkerr } -func (sdk mgSDK) UpdateBootstrapCerts(id, clientCert, clientKey, ca, token string) (BootstrapConfig, errors.SDKError) { +func (sdk mgSDK) UpdateBootstrapCerts(id, clientCert, clientKey, ca, domainID, token string) (BootstrapConfig, errors.SDKError) { if id == "" { return BootstrapConfig{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, bootstrapCertsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, bootstrapCertsEndpoint, id) request := BootstrapConfig{ ClientCert: clientCert, ClientKey: clientKey, @@ -213,11 +214,11 @@ func (sdk mgSDK) UpdateBootstrapCerts(id, clientCert, clientKey, ca, token strin return bc, nil } -func (sdk mgSDK) UpdateBootstrapConnection(id string, channels []string, token string) errors.SDKError { +func (sdk mgSDK) UpdateBootstrapConnection(id string, channels []string, domainID, token string) errors.SDKError { if id == "" { return errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, bootstrapConnEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, bootstrapConnEndpoint, id) request := map[string][]string{ "channels": channels, } @@ -230,11 +231,11 @@ func (sdk mgSDK) UpdateBootstrapConnection(id string, channels []string, token s return sdkerr } -func (sdk mgSDK) RemoveBootstrap(id, token string) errors.SDKError { +func (sdk mgSDK) RemoveBootstrap(id, domainID, token string) errors.SDKError { if id == "" { return errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, configsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint, id) _, _, err := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent) return err diff --git a/pkg/sdk/go/bootstrap_test.go b/pkg/sdk/go/bootstrap_test.go index 23b0f1c82b..4fd27864c7 100644 --- a/pkg/sdk/go/bootstrap_test.go +++ b/pkg/sdk/go/bootstrap_test.go @@ -153,6 +153,7 @@ func TestAddBootstrap(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session cfg sdk.BootstrapConfig @@ -164,26 +165,29 @@ func TestAddBootstrap(t *testing.T) { err errors.SDKError }{ { - desc: "add successfully", - token: validToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrapConfig, - svcRes: bootstrapConfig, - svcErr: nil, - err: nil, + desc: "add successfully", + domainID: domainID, + token: validToken, + cfg: sdkBootstrapConfig, + svcReq: bootstrapConfig, + svcRes: bootstrapConfig, + svcErr: nil, + err: nil, }, { - desc: "add with invalid token", - token: invalidToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrapConfig, - svcRes: bootstrap.Config{}, - svcErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), + desc: "add with invalid token", + domainID: domainID, + token: invalidToken, + cfg: sdkBootstrapConfig, + svcReq: bootstrapConfig, + svcRes: bootstrap.Config{}, + svcErr: svcerr.ErrAuthentication, + err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "add with config that cannot be marshalled", - token: validToken, + desc: "add with config that cannot be marshalled", + domainID: domainID, + token: validToken, cfg: sdk.BootstrapConfig{ Channels: map[string]interface{}{ "channel1": make(chan int), @@ -204,42 +208,45 @@ func TestAddBootstrap(t *testing.T) { err: errors.NewSDKError(errMarshalChan), }, { - desc: "add an existing config", - token: validToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrapConfig, - svcRes: bootstrap.Config{}, - svcErr: svcerr.ErrConflict, - err: errors.NewSDKErrorWithStatus(svcerr.ErrConflict, http.StatusConflict), + desc: "add an existing config", + domainID: domainID, + token: validToken, + cfg: sdkBootstrapConfig, + svcReq: bootstrapConfig, + svcRes: bootstrap.Config{}, + svcErr: svcerr.ErrConflict, + err: errors.NewSDKErrorWithStatus(svcerr.ErrConflict, http.StatusConflict), }, { - desc: "add empty config", - token: validToken, - cfg: sdk.BootstrapConfig{}, - svcReq: bootstrap.Config{}, - svcRes: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), + desc: "add empty config", + domainID: domainID, + token: validToken, + cfg: sdk.BootstrapConfig{}, + svcReq: bootstrap.Config{}, + svcRes: bootstrap.Config{}, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "add with non-existent thing Id", - token: validToken, - cfg: neID, - svcReq: neReqId, - svcRes: bootstrap.Config{}, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + desc: "add with non-existent thing Id", + domainID: domainID, + token: validToken, + cfg: neID, + svcReq: neReqId, + svcRes: bootstrap.Config{}, + svcErr: svcerr.ErrNotFound, + err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("Add", mock.Anything, tc.session, tc.token, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.AddBootstrap(tc.cfg, tc.token) + resp, err := mgsdk.AddBootstrap(tc.cfg, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if err == nil { assert.Equal(t, bootstrapConfig.ThingID, resp) @@ -301,8 +308,9 @@ func TestListBootstraps(t *testing.T) { desc: "list successfully", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcResp: bootstrap.ConfigsPage{ Total: 1, @@ -321,8 +329,9 @@ func TestListBootstraps(t *testing.T) { desc: "list with invalid token", token: invalidToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcResp: bootstrap.ConfigsPage{}, svcErr: svcerr.ErrAuthentication, @@ -333,8 +342,9 @@ func TestListBootstraps(t *testing.T) { desc: "list with empty token", token: "", pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcResp: bootstrap.ConfigsPage{}, svcErr: nil, @@ -345,8 +355,9 @@ func TestListBootstraps(t *testing.T) { desc: "list with invalid query params", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 1, - Limit: 10, + Offset: 1, + Limit: 10, + DomainID: domainID, Metadata: map[string]interface{}{ "test": make(chan int), }, @@ -360,8 +371,9 @@ func TestListBootstraps(t *testing.T) { desc: "list with response that cannot be unmarshalled", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcResp: bootstrap.ConfigsPage{ Total: 1, @@ -376,7 +388,7 @@ func TestListBootstraps(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("List", mock.Anything, tc.session, mock.Anything, tc.pageMeta.Offset, tc.pageMeta.Limit).Return(tc.svcResp, tc.svcErr) @@ -407,6 +419,7 @@ func TestWhiteList(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -417,25 +430,28 @@ func TestWhiteList(t *testing.T) { err errors.SDKError }{ { - desc: "whitelist to active state successfully", - token: validToken, - thingID: thingId, - state: active, - svcReq: bootstrap.Active, - svcErr: nil, - err: nil, + desc: "whitelist to active state successfully", + domainID: domainID, + token: validToken, + thingID: thingId, + state: active, + svcReq: bootstrap.Active, + svcErr: nil, + err: nil, }, { - desc: "whitelist to inactive state successfully", - token: validToken, - thingID: thingId, - state: inactive, - svcReq: bootstrap.Inactive, - svcErr: nil, - err: nil, + desc: "whitelist to inactive state successfully", + domainID: domainID, + token: validToken, + thingID: thingId, + state: inactive, + svcReq: bootstrap.Inactive, + svcErr: nil, + err: nil, }, { desc: "whitelist with invalid token", + domainID: domainID, token: invalidToken, thingID: thingId, state: active, @@ -444,41 +460,44 @@ func TestWhiteList(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "whitelist with empty token", - token: "", - thingID: thingId, - state: active, - svcReq: bootstrap.Active, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "whitelist with empty token", + domainID: domainID, + token: "", + thingID: thingId, + state: active, + svcReq: bootstrap.Active, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "whitelist with invalid state", - token: validToken, - thingID: thingId, - state: -1, - svcReq: bootstrap.Active, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrBootstrapState), http.StatusBadRequest), + desc: "whitelist with invalid state", + domainID: domainID, + token: validToken, + thingID: thingId, + state: -1, + svcReq: bootstrap.Active, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrBootstrapState), http.StatusBadRequest), }, { - desc: "whitelist with empty thing Id", - token: validToken, - thingID: "", - state: 1, - svcReq: bootstrap.Active, - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), + desc: "whitelist with empty thing Id", + domainID: domainID, + token: validToken, + thingID: "", + state: 1, + svcReq: bootstrap.Active, + svcErr: nil, + err: errors.NewSDKError(apiutil.ErrMissingID), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("ChangeState", mock.Anything, tc.session, tc.token, tc.thingID, tc.svcReq).Return(tc.svcErr) - err := mgsdk.Whitelist(tc.thingID, tc.state, tc.token) + err := mgsdk.Whitelist(tc.thingID, tc.state, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "ChangeState", mock.Anything, tc.session, tc.token, tc.thingID, tc.svcReq) @@ -511,6 +530,7 @@ func TestViewBootstrap(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session id string @@ -522,6 +542,7 @@ func TestViewBootstrap(t *testing.T) { }{ { desc: "view successfully", + domainID: domainID, token: validToken, id: thingId, svcResp: bootstrapConfig, @@ -531,6 +552,7 @@ func TestViewBootstrap(t *testing.T) { }, { desc: "view with invalid token", + domainID: domainID, token: invalidToken, id: thingId, svcResp: bootstrap.Config{}, @@ -540,6 +562,7 @@ func TestViewBootstrap(t *testing.T) { }, { desc: "view with empty token", + domainID: domainID, token: "", id: thingId, svcResp: bootstrap.Config{}, @@ -549,6 +572,7 @@ func TestViewBootstrap(t *testing.T) { }, { desc: "view with non-existent thing Id", + domainID: domainID, token: validToken, id: invalid, svcResp: bootstrap.Config{}, @@ -557,9 +581,10 @@ func TestViewBootstrap(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrViewEntity, http.StatusBadRequest), }, { - desc: "view with response that cannot be unmarshalled", - token: validToken, - id: thingId, + desc: "view with response that cannot be unmarshalled", + domainID: domainID, + token: validToken, + id: thingId, svcResp: bootstrap.Config{ ThingID: thingId, Channels: []bootstrap.Channel{ @@ -577,6 +602,7 @@ func TestViewBootstrap(t *testing.T) { }, { desc: "view with empty thing Id", + domainID: domainID, token: validToken, id: "", svcResp: bootstrap.Config{}, @@ -588,11 +614,11 @@ func TestViewBootstrap(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("View", mock.Anything, tc.session, tc.id).Return(tc.svcResp, tc.svcErr) - resp, err := mgsdk.ViewBootstrap(tc.id, tc.token) + resp, err := mgsdk.ViewBootstrap(tc.id, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if err == nil { @@ -616,6 +642,7 @@ func TestUpdateBootstrap(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session cfg sdk.BootstrapConfig @@ -625,9 +652,10 @@ func TestUpdateBootstrap(t *testing.T) { err errors.SDKError }{ { - desc: "update successfully", - token: validToken, - cfg: sdkBootstrapConfig, + desc: "update successfully", + domainID: domainID, + token: validToken, + cfg: sdkBootstrapConfig, svcReq: bootstrap.Config{ ThingID: thingId, Name: bsName, @@ -637,9 +665,10 @@ func TestUpdateBootstrap(t *testing.T) { err: nil, }, { - desc: "update with invalid token", - token: invalidToken, - cfg: sdkBootstrapConfig, + desc: "update with invalid token", + domainID: domainID, + token: invalidToken, + cfg: sdkBootstrapConfig, svcReq: bootstrap.Config{ ThingID: thingId, Name: bsName, @@ -649,16 +678,18 @@ func TestUpdateBootstrap(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "update with empty token", - token: "", - cfg: sdkBootstrapConfig, - svcReq: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "update with empty token", + domainID: domainID, + token: "", + cfg: sdkBootstrapConfig, + svcReq: bootstrap.Config{}, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "update with config that cannot be marshalled", - token: validToken, + desc: "update with config that cannot be marshalled", + domainID: domainID, + token: validToken, cfg: sdk.BootstrapConfig{ Channels: map[string]interface{}{ "channel1": make(chan int), @@ -682,8 +713,9 @@ func TestUpdateBootstrap(t *testing.T) { err: errors.NewSDKError(errMarshalChan), }, { - desc: "update with non-existent thing Id", - token: validToken, + desc: "update with non-existent thing Id", + domainID: domainID, + token: validToken, cfg: sdk.BootstrapConfig{ ThingID: invalid, Channels: []sdk.Channel{ @@ -705,8 +737,9 @@ func TestUpdateBootstrap(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "update with empty thing Id", - token: validToken, + desc: "update with empty thing Id", + domainID: domainID, + token: validToken, cfg: sdk.BootstrapConfig{ ThingID: "", Channels: []sdk.Channel{ @@ -728,8 +761,9 @@ func TestUpdateBootstrap(t *testing.T) { err: errors.NewSDKError(apiutil.ErrMissingID), }, { - desc: "update with config with only thing Id", - token: validToken, + desc: "update with config with only thing Id", + domainID: domainID, + token: validToken, cfg: sdk.BootstrapConfig{ ThingID: thingId, }, @@ -743,11 +777,11 @@ func TestUpdateBootstrap(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticationErr) svcCall := bsvc.On("Update", mock.Anything, tc.session, tc.svcReq).Return(tc.svcErr) - err := mgsdk.UpdateBootstrap(tc.cfg, tc.token) + err := mgsdk.UpdateBootstrap(tc.cfg, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Update", mock.Anything, tc.session, tc.svcReq) @@ -777,6 +811,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session id string @@ -791,6 +826,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { }{ { desc: "update certs successfully", + domainID: domainID, token: validToken, id: thingId, clientCert: clientCert, @@ -803,6 +839,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { }, { desc: "update certs with invalid token", + domainID: domainID, token: validToken, id: thingId, clientCert: clientCert, @@ -814,6 +851,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { }, { desc: "update certs with empty token", + domainID: domainID, token: "", id: thingId, clientCert: clientCert, @@ -825,6 +863,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { }, { desc: "update certs with non-existent thing Id", + domainID: domainID, token: validToken, id: invalid, clientCert: clientCert, @@ -836,6 +875,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { }, { desc: "update certs with empty certs", + domainID: domainID, token: validToken, id: thingId, clientCert: "", @@ -847,6 +887,7 @@ func TestUpdateBootstrapCerts(t *testing.T) { }, { desc: "update certs with empty id", + domainID: domainID, token: validToken, id: "", clientCert: clientCert, @@ -859,11 +900,11 @@ func TestUpdateBootstrapCerts(t *testing.T) { } for _, tc := range cases { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("UpdateCert", mock.Anything, tc.session, tc.id, tc.clientCert, tc.clientKey, tc.caCert).Return(tc.svcResp, tc.svcErr) - resp, err := mgsdk.UpdateBootstrapCerts(tc.id, tc.clientCert, tc.clientKey, tc.caCert, tc.token) + resp, err := mgsdk.UpdateBootstrapCerts(tc.id, tc.clientCert, tc.clientKey, tc.caCert, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if err == nil { assert.Equal(t, tc.response, resp) @@ -884,6 +925,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session id string @@ -895,6 +937,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }{ { desc: "update connection successfully", + domainID: domainID, token: validToken, id: thingId, channels: []string{channel1Id, channel2Id}, @@ -903,6 +946,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }, { desc: "update connection with invalid token", + domainID: domainID, token: invalidToken, id: thingId, channels: []string{channel1Id, channel2Id}, @@ -911,6 +955,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }, { desc: "update connection with empty token", + domainID: domainID, token: "", id: thingId, channels: []string{channel1Id, channel2Id}, @@ -919,6 +964,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }, { desc: "update connection with non-existent thing Id", + domainID: domainID, token: validToken, id: invalid, channels: []string{channel1Id, channel2Id}, @@ -927,6 +973,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }, { desc: "update connection with non-existent channel Id", + domainID: domainID, token: validToken, id: thingId, channels: []string{invalid}, @@ -935,6 +982,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }, { desc: "update connection with empty channels", + domainID: domainID, token: validToken, id: thingId, channels: []string{}, @@ -943,6 +991,7 @@ func TestUpdateBootstrapConnection(t *testing.T) { }, { desc: "update connection with empty id", + domainID: domainID, token: validToken, id: "", channels: []string{channel1Id, channel2Id}, @@ -953,11 +1002,11 @@ func TestUpdateBootstrapConnection(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("UpdateConnections", mock.Anything, tc.session, tc.token, tc.id, tc.channels).Return(tc.svcErr) - err := mgsdk.UpdateBootstrapConnection(tc.id, tc.channels, tc.token) + err := mgsdk.UpdateBootstrapConnection(tc.id, tc.channels, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "UpdateConnections", mock.Anything, tc.session, tc.token, tc.id, tc.channels) @@ -980,6 +1029,7 @@ func TestRemoveBootstrap(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session id string @@ -988,56 +1038,62 @@ func TestRemoveBootstrap(t *testing.T) { err errors.SDKError }{ { - desc: "remove successfully", - token: validToken, - id: thingId, - svcErr: nil, - err: nil, + desc: "remove successfully", + domainID: domainID, + token: validToken, + id: thingId, + svcErr: nil, + err: nil, }, { desc: "remove with invalid token", + domainID: domainID, token: invalidToken, id: thingId, authenticateErr: svcerr.ErrAuthentication, err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "remove with non-existent thing Id", - token: validToken, - id: invalid, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + desc: "remove with non-existent thing Id", + domainID: domainID, + token: validToken, + id: invalid, + svcErr: svcerr.ErrNotFound, + err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "remove removed bootstrap", - token: validToken, - id: thingId, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + desc: "remove removed bootstrap", + domainID: domainID, + token: validToken, + id: thingId, + svcErr: svcerr.ErrNotFound, + err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "remove with empty token", - token: "", - id: thingId, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "remove with empty token", + domainID: domainID, + token: "", + id: thingId, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "remove with empty id", - token: validToken, - id: "", - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), + desc: "remove with empty id", + domainID: domainID, + token: validToken, + id: "", + svcErr: nil, + err: errors.NewSDKError(apiutil.ErrMissingID), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := bsvc.On("Remove", mock.Anything, tc.session, tc.id).Return(tc.svcErr) - err := mgsdk.RemoveBootstrap(tc.id, tc.token) + err := mgsdk.RemoveBootstrap(tc.id, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Remove", mock.Anything, tc.session, tc.id) diff --git a/pkg/sdk/go/certs.go b/pkg/sdk/go/certs.go index f934caa9a8..35d68509a2 100644 --- a/pkg/sdk/go/certs.go +++ b/pkg/sdk/go/certs.go @@ -28,7 +28,7 @@ type Cert struct { ThingID string `json:"thing_id,omitempty"` } -func (sdk mgSDK) IssueCert(thingID, validity, token string) (Cert, errors.SDKError) { +func (sdk mgSDK) IssueCert(thingID, validity, domainID, token string) (Cert, errors.SDKError) { r := certReq{ ThingID: thingID, Validity: validity, @@ -38,7 +38,7 @@ func (sdk mgSDK) IssueCert(thingID, validity, token string) (Cert, errors.SDKErr return Cert{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.certsURL, certsEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.certsURL, domainID, certsEndpoint) _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, d, nil, http.StatusCreated) if sdkerr != nil { @@ -52,8 +52,8 @@ func (sdk mgSDK) IssueCert(thingID, validity, token string) (Cert, errors.SDKErr return c, nil } -func (sdk mgSDK) ViewCert(id, token string) (Cert, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s", sdk.certsURL, certsEndpoint, id) +func (sdk mgSDK) ViewCert(id, domainID, token string) (Cert, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s", sdk.certsURL, domainID, certsEndpoint, id) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -68,11 +68,11 @@ func (sdk mgSDK) ViewCert(id, token string) (Cert, errors.SDKError) { return cert, nil } -func (sdk mgSDK) ViewCertByThing(thingID, token string) (CertSerials, errors.SDKError) { +func (sdk mgSDK) ViewCertByThing(thingID, domainID, token string) (CertSerials, errors.SDKError) { if thingID == "" { return CertSerials{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.certsURL, serialsEndpoint, thingID) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.certsURL, domainID, serialsEndpoint, thingID) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -86,8 +86,8 @@ func (sdk mgSDK) ViewCertByThing(thingID, token string) (CertSerials, errors.SDK return cs, nil } -func (sdk mgSDK) RevokeCert(id, token string) (time.Time, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s", sdk.certsURL, certsEndpoint, id) +func (sdk mgSDK) RevokeCert(id, domainID, token string) (time.Time, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s", sdk.certsURL, domainID, certsEndpoint, id) _, body, err := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusOK) if err != nil { diff --git a/pkg/sdk/go/certs_test.go b/pkg/sdk/go/certs_test.go index 3b013ce730..13055db6e2 100644 --- a/pkg/sdk/go/certs_test.go +++ b/pkg/sdk/go/certs_test.go @@ -85,6 +85,7 @@ func TestIssueCert(t *testing.T) { desc string thingID string duration string + domainID string token string session mgauthn.Session authenticateErr error @@ -96,6 +97,7 @@ func TestIssueCert(t *testing.T) { desc: "create new cert with thing id and duration", thingID: thingID, duration: ttl, + domainID: validID, token: validToken, svcRes: certs.Cert{SerialNumber: serial}, svcErr: nil, @@ -105,6 +107,7 @@ func TestIssueCert(t *testing.T) { desc: "create new cert with empty thing id and duration", thingID: "", duration: ttl, + domainID: validID, token: validToken, svcRes: certs.Cert{}, svcErr: errors.Wrap(certs.ErrFailedCertCreation, apiutil.ErrMissingID), @@ -114,6 +117,7 @@ func TestIssueCert(t *testing.T) { desc: "create new cert with invalid thing id and duration", thingID: invalid, duration: ttl, + domainID: validID, token: validToken, svcRes: certs.Cert{}, svcErr: errors.Wrap(certs.ErrFailedCertCreation, apiutil.ErrValidation), @@ -123,6 +127,7 @@ func TestIssueCert(t *testing.T) { desc: "create new cert with thing id and empty duration", thingID: thingID, duration: "", + domainID: validID, token: validToken, svcRes: certs.Cert{}, svcErr: errors.Wrap(certs.ErrFailedCertCreation, apiutil.ErrMissingCertData), @@ -132,6 +137,7 @@ func TestIssueCert(t *testing.T) { desc: "create new cert with thing id and malformed duration", thingID: thingID, duration: invalid, + domainID: validID, token: validToken, svcRes: certs.Cert{}, svcErr: errors.Wrap(certs.ErrFailedCertCreation, apiutil.ErrInvalidCertData), @@ -141,6 +147,7 @@ func TestIssueCert(t *testing.T) { desc: "create new cert with empty token", thingID: thingID, duration: ttl, + domainID: validID, token: "", svcRes: certs.Cert{}, svcErr: errors.Wrap(certs.ErrFailedCertCreation, svcerr.ErrAuthentication), @@ -149,6 +156,7 @@ func TestIssueCert(t *testing.T) { { desc: "create new cert with invalid token", thingID: thingID, + domainID: domainID, duration: ttl, token: invalidToken, svcRes: certs.Cert{}, @@ -159,6 +167,7 @@ func TestIssueCert(t *testing.T) { desc: "create new empty cert", thingID: "", duration: "", + domainID: validID, token: validToken, svcRes: certs.Cert{}, svcErr: errors.Wrap(certs.ErrFailedCertCreation, certs.ErrFailedCertCreation), @@ -172,12 +181,12 @@ func TestIssueCert(t *testing.T) { tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("IssueCert", mock.Anything, tc.token, tc.thingID, tc.duration).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.IssueCert(tc.thingID, tc.duration, tc.token) + svcCall := svc.On("IssueCert", mock.Anything, tc.domainID, tc.token, tc.thingID, tc.duration).Return(tc.svcRes, tc.svcErr) + resp, err := mgsdk.IssueCert(tc.thingID, tc.duration, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { assert.Equal(t, tc.svcRes.SerialNumber, resp.SerialNumber) - ok := svcCall.Parent.AssertCalled(t, "IssueCert", mock.Anything, tc.token, tc.thingID, tc.duration) + ok := svcCall.Parent.AssertCalled(t, "IssueCert", mock.Anything, tc.domainID, tc.token, tc.thingID, tc.duration) assert.True(t, ok) } svcCall.Unset() @@ -204,6 +213,7 @@ func TestViewCert(t *testing.T) { cases := []struct { desc string certID string + domainID string token string session mgauthn.Session authenticateErr error @@ -212,36 +222,40 @@ func TestViewCert(t *testing.T) { err errors.SDKError }{ { - desc: "view existing cert", - certID: validID, - token: token, - svcRes: cert, - svcErr: nil, - err: nil, + desc: "view existing cert", + certID: validID, + domainID: validID, + token: validToken, + svcRes: cert, + svcErr: nil, + err: nil, }, { - desc: "view non-existent cert", - certID: invalid, - token: token, - svcRes: certs.Cert{}, - svcErr: errors.Wrap(svcerr.ErrNotFound, repoerr.ErrNotFound), - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, svcerr.ErrNotFound), http.StatusNotFound), + desc: "view non-existent cert", + certID: invalid, + domainID: validID, + token: validToken, + svcRes: certs.Cert{}, + svcErr: errors.Wrap(svcerr.ErrNotFound, repoerr.ErrNotFound), + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, svcerr.ErrNotFound), http.StatusNotFound), }, { desc: "view cert with invalid token", certID: validID, + domainID: domainID, token: invalidToken, svcRes: certs.Cert{}, authenticateErr: svcerr.ErrAuthentication, err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "view cert with empty token", - certID: validID, - token: "", - svcRes: certs.Cert{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "view cert with empty token", + certID: validID, + domainID: domainID, + token: "", + svcRes: certs.Cert{}, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, } @@ -252,7 +266,7 @@ func TestViewCert(t *testing.T) { } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ViewCert", mock.Anything, tc.certID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.ViewCert(tc.certID, tc.token) + resp, err := mgsdk.ViewCert(tc.certID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if err == nil { assert.Equal(t, viewCertRes, resp) @@ -285,6 +299,7 @@ func TestViewCertByThing(t *testing.T) { cases := []struct { desc string thingID string + domainID string token string session mgauthn.Session authenticateErr error @@ -293,44 +308,49 @@ func TestViewCertByThing(t *testing.T) { err errors.SDKError }{ { - desc: "view existing cert", - thingID: thingID, - token: validToken, - svcRes: certs.CertPage{Certificates: []certs.Cert{{SerialNumber: serial}}}, - svcErr: nil, - err: nil, + desc: "view existing cert", + thingID: thingID, + domainID: domainID, + token: validToken, + svcRes: certs.CertPage{Certificates: []certs.Cert{{SerialNumber: serial}}}, + svcErr: nil, + err: nil, }, { - desc: "view non-existent cert", - thingID: invalid, - token: validToken, - svcRes: certs.CertPage{Certificates: []certs.Cert{}}, - svcErr: errors.Wrap(svcerr.ErrNotFound, repoerr.ErrNotFound), - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, svcerr.ErrNotFound), http.StatusNotFound), + desc: "view non-existent cert", + thingID: invalid, + domainID: domainID, + token: validToken, + svcRes: certs.CertPage{Certificates: []certs.Cert{}}, + svcErr: errors.Wrap(svcerr.ErrNotFound, repoerr.ErrNotFound), + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, svcerr.ErrNotFound), http.StatusNotFound), }, { desc: "view cert with invalid token", thingID: thingID, + domainID: domainID, token: invalidToken, svcRes: certs.CertPage{Certificates: []certs.Cert{}}, authenticateErr: svcerr.ErrAuthentication, err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "view cert with empty token", - thingID: thingID, - token: "", - svcRes: certs.CertPage{Certificates: []certs.Cert{}}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "view cert with empty token", + thingID: thingID, + domainID: domainID, + token: "", + svcRes: certs.CertPage{Certificates: []certs.Cert{}}, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "view cert with empty thing id", - thingID: "", - token: validToken, - svcRes: certs.CertPage{Certificates: []certs.Cert{}}, - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), + desc: "view cert with empty thing id", + thingID: "", + domainID: domainID, + token: validToken, + svcRes: certs.CertPage{Certificates: []certs.Cert{}}, + svcErr: nil, + err: errors.NewSDKError(apiutil.ErrMissingID), }, } for _, tc := range cases { @@ -340,7 +360,7 @@ func TestViewCertByThing(t *testing.T) { } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ListSerials", mock.Anything, tc.thingID, certs.PageMetadata{Revoked: defRevoke, Offset: defOffset, Limit: defLimit}).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.ViewCertByThing(tc.thingID, tc.token) + resp, err := mgsdk.ViewCertByThing(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { assert.Equal(t, viewCertThingRes, resp) @@ -368,6 +388,7 @@ func TestRevokeCert(t *testing.T) { cases := []struct { desc string thingID string + domainID string token string session mgauthn.Session svcResp certs.Revoke @@ -376,44 +397,49 @@ func TestRevokeCert(t *testing.T) { err errors.SDKError }{ { - desc: "revoke cert successfully", - thingID: thingID, - token: validToken, - svcResp: certs.Revoke{RevocationTime: time.Now()}, - svcErr: nil, - err: nil, + desc: "revoke cert successfully", + thingID: thingID, + domainID: validID, + token: validToken, + svcResp: certs.Revoke{RevocationTime: time.Now()}, + svcErr: nil, + err: nil, }, { desc: "revoke cert with invalid token", thingID: thingID, + domainID: validID, token: invalidToken, svcResp: certs.Revoke{}, authenticateErr: svcerr.ErrAuthentication, err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "revoke non-existing cert", - thingID: invalid, - token: token, - svcResp: certs.Revoke{}, - svcErr: errors.Wrap(certs.ErrFailedCertRevocation, svcerr.ErrNotFound), - err: errors.NewSDKErrorWithStatus(certs.ErrFailedCertRevocation, http.StatusNotFound), + desc: "revoke non-existing cert", + thingID: invalid, + domainID: validID, + token: validToken, + svcResp: certs.Revoke{}, + svcErr: errors.Wrap(certs.ErrFailedCertRevocation, svcerr.ErrNotFound), + err: errors.NewSDKErrorWithStatus(certs.ErrFailedCertRevocation, http.StatusNotFound), }, { - desc: "revoke cert with empty token", - thingID: thingID, - token: "", - svcResp: certs.Revoke{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "revoke cert with empty token", + thingID: thingID, + domainID: validID, + token: "", + svcResp: certs.Revoke{}, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "revoke deleted cert", - thingID: thingID, - token: token, - svcResp: certs.Revoke{}, - svcErr: errors.Wrap(certs.ErrFailedToRemoveCertFromDB, svcerr.ErrNotFound), - err: errors.NewSDKErrorWithStatus(certs.ErrFailedToRemoveCertFromDB, http.StatusNotFound), + desc: "revoke deleted cert", + thingID: thingID, + domainID: validID, + token: validToken, + svcResp: certs.Revoke{}, + svcErr: errors.Wrap(certs.ErrFailedToRemoveCertFromDB, svcerr.ErrNotFound), + err: errors.NewSDKErrorWithStatus(certs.ErrFailedToRemoveCertFromDB, http.StatusNotFound), }, } for _, tc := range cases { @@ -422,12 +448,12 @@ func TestRevokeCert(t *testing.T) { tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) - svcCall := svc.On("RevokeCert", mock.Anything, tc.token, tc.thingID).Return(tc.svcResp, tc.svcErr) - resp, err := mgsdk.RevokeCert(tc.thingID, tc.token) + svcCall := svc.On("RevokeCert", mock.Anything, tc.domainID, tc.token, tc.thingID).Return(tc.svcResp, tc.svcErr) + resp, err := mgsdk.RevokeCert(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if err == nil { assert.NotEmpty(t, resp) - ok := svcCall.Parent.AssertCalled(t, "RevokeCert", mock.Anything, tc.token, tc.thingID) + ok := svcCall.Parent.AssertCalled(t, "RevokeCert", mock.Anything, tc.domainID, tc.token, tc.thingID) assert.True(t, ok) } svcCall.Unset() diff --git a/pkg/sdk/go/channels.go b/pkg/sdk/go/channels.go index 43131e9b7f..092f9a9a6d 100644 --- a/pkg/sdk/go/channels.go +++ b/pkg/sdk/go/channels.go @@ -32,12 +32,12 @@ type Channel struct { Permissions []string `json:"permissions,omitempty"` } -func (sdk mgSDK) CreateChannel(c Channel, token string) (Channel, errors.SDKError) { +func (sdk mgSDK) CreateChannel(c Channel, domainID, token string) (Channel, errors.SDKError) { data, err := json.Marshal(c) if err != nil { return Channel{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.thingsURL, channelsEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint) _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) if sdkerr != nil { @@ -53,7 +53,8 @@ func (sdk mgSDK) CreateChannel(c Channel, token string) (Channel, errors.SDKErro } func (sdk mgSDK) Channels(pm PageMetadata, token string) (ChannelsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.thingsURL, channelsEndpoint, pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, channelsEndpoint) + url, err := sdk.withQueryParams(sdk.thingsURL, endpoint, pm) if err != nil { return ChannelsPage{}, errors.NewSDKError(err) } @@ -71,8 +72,8 @@ func (sdk mgSDK) Channels(pm PageMetadata, token string) (ChannelsPage, errors.S return cp, nil } -func (sdk mgSDK) ChannelsByThing(thingID string, pm PageMetadata, token string) (ChannelsPage, errors.SDKError) { - url, err := sdk.withQueryParams(fmt.Sprintf("%s/things/%s", sdk.thingsURL, thingID), channelsEndpoint, pm) +func (sdk mgSDK) ChannelsByThing(thingID string, pm PageMetadata, domainID, token string) (ChannelsPage, errors.SDKError) { + url, err := sdk.withQueryParams(fmt.Sprintf("%s/%s/things/%s", sdk.thingsURL, domainID, thingID), channelsEndpoint, pm) if err != nil { return ChannelsPage{}, errors.NewSDKError(err) } @@ -90,11 +91,11 @@ func (sdk mgSDK) ChannelsByThing(thingID string, pm PageMetadata, token string) return cp, nil } -func (sdk mgSDK) Channel(id, token string) (Channel, errors.SDKError) { +func (sdk mgSDK) Channel(id, domainID, token string) (Channel, errors.SDKError) { if id == "" { return Channel{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, channelsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, id) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -109,8 +110,8 @@ func (sdk mgSDK) Channel(id, token string) (Channel, errors.SDKError) { return c, nil } -func (sdk mgSDK) ChannelPermissions(id, token string) (Channel, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, id, permissionsEndpoint) +func (sdk mgSDK) ChannelPermissions(id, domainID, token string) (Channel, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, id, permissionsEndpoint) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -125,11 +126,11 @@ func (sdk mgSDK) ChannelPermissions(id, token string) (Channel, errors.SDKError) return c, nil } -func (sdk mgSDK) UpdateChannel(c Channel, token string) (Channel, errors.SDKError) { +func (sdk mgSDK) UpdateChannel(c Channel, domainID, token string) (Channel, errors.SDKError) { if c.ID == "" { return Channel{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, channelsEndpoint, c.ID) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, c.ID) data, err := json.Marshal(c) if err != nil { @@ -149,32 +150,32 @@ func (sdk mgSDK) UpdateChannel(c Channel, token string) (Channel, errors.SDKErro return c, nil } -func (sdk mgSDK) AddUserToChannel(channelID string, req UsersRelationRequest, token string) errors.SDKError { +func (sdk mgSDK) AddUserToChannel(channelID string, req UsersRelationRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, usersEndpoint, assignEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, channelID, usersEndpoint, assignEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) return sdkerr } -func (sdk mgSDK) RemoveUserFromChannel(channelID string, req UsersRelationRequest, token string) errors.SDKError { +func (sdk mgSDK) RemoveUserFromChannel(channelID string, req UsersRelationRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, usersEndpoint, unassignEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, channelID, usersEndpoint, unassignEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) ListChannelUsers(channelID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", channelsEndpoint, channelID, usersEndpoint), pm) + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, channelsEndpoint, channelID, usersEndpoint), pm) if err != nil { return UsersPage{}, errors.NewSDKError(err) } @@ -190,32 +191,32 @@ func (sdk mgSDK) ListChannelUsers(channelID string, pm PageMetadata, token strin return up, nil } -func (sdk mgSDK) AddUserGroupToChannel(channelID string, req UserGroupsRequest, token string) errors.SDKError { +func (sdk mgSDK) AddUserGroupToChannel(channelID string, req UserGroupsRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, groupsEndpoint, assignEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, channelID, groupsEndpoint, assignEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) return sdkerr } -func (sdk mgSDK) RemoveUserGroupFromChannel(channelID string, req UserGroupsRequest, token string) errors.SDKError { +func (sdk mgSDK) RemoveUserGroupFromChannel(channelID string, req UserGroupsRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, groupsEndpoint, unassignEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, channelID, groupsEndpoint, unassignEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) ListChannelUserGroups(channelID string, pm PageMetadata, token string) (GroupsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", channelsEndpoint, channelID, groupsEndpoint), pm) + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, channelsEndpoint, channelID, groupsEndpoint), pm) if err != nil { return GroupsPage{}, errors.NewSDKError(err) } @@ -231,67 +232,67 @@ func (sdk mgSDK) ListChannelUserGroups(channelID string, pm PageMetadata, token return gp, nil } -func (sdk mgSDK) Connect(conn Connection, token string) errors.SDKError { +func (sdk mgSDK) Connect(conn Connection, domainID, token string) errors.SDKError { data, err := json.Marshal(conn) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.thingsURL, connectEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, domainID, connectEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) return sdkerr } -func (sdk mgSDK) Disconnect(connIDs Connection, token string) errors.SDKError { +func (sdk mgSDK) Disconnect(connIDs Connection, domainID, token string) errors.SDKError { data, err := json.Marshal(connIDs) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.thingsURL, disconnectEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, domainID, disconnectEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } -func (sdk mgSDK) ConnectThing(thingID, channelID, token string) errors.SDKError { - url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, thingsEndpoint, thingID, connectEndpoint) +func (sdk mgSDK) ConnectThing(thingID, channelID, domainID, token string) errors.SDKError { + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, channelID, thingsEndpoint, thingID, connectEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusCreated) return sdkerr } -func (sdk mgSDK) DisconnectThing(thingID, channelID, token string) errors.SDKError { - url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, thingsEndpoint, thingID, disconnectEndpoint) +func (sdk mgSDK) DisconnectThing(thingID, channelID, domainID, token string) errors.SDKError { + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, channelID, thingsEndpoint, thingID, disconnectEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent) return sdkerr } -func (sdk mgSDK) EnableChannel(id, token string) (Channel, errors.SDKError) { - return sdk.changeChannelStatus(id, enableEndpoint, token) +func (sdk mgSDK) EnableChannel(id, domainID, token string) (Channel, errors.SDKError) { + return sdk.changeChannelStatus(id, enableEndpoint, domainID, token) } -func (sdk mgSDK) DisableChannel(id, token string) (Channel, errors.SDKError) { - return sdk.changeChannelStatus(id, disableEndpoint, token) +func (sdk mgSDK) DisableChannel(id, domainID, token string) (Channel, errors.SDKError) { + return sdk.changeChannelStatus(id, disableEndpoint, domainID, token) } -func (sdk mgSDK) DeleteChannel(id, token string) errors.SDKError { +func (sdk mgSDK) DeleteChannel(id, domainID, token string) errors.SDKError { if id == "" { return errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, channelsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, id) _, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent) return sdkerr } -func (sdk mgSDK) changeChannelStatus(id, status, token string) (Channel, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, id, status) +func (sdk mgSDK) changeChannelStatus(id, status, domainID, token string) (Channel, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, domainID, channelsEndpoint, id, status) _, body, err := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusOK) if err != nil { diff --git a/pkg/sdk/go/channels_test.go b/pkg/sdk/go/channels_test.go index 5a15ea73ac..6344173728 100644 --- a/pkg/sdk/go/channels_test.go +++ b/pkg/sdk/go/channels_test.go @@ -94,6 +94,7 @@ func TestCreateChannel(t *testing.T) { cases := []struct { desc string channelReq sdk.Channel + domainID string token string session mgauthn.Session createGroupReq groups.Group @@ -107,6 +108,7 @@ func TestCreateChannel(t *testing.T) { { desc: "create channel successfully", channelReq: channelReq, + domainID: domainID, token: validToken, createGroupReq: createGroupReq, svcRes: group, @@ -117,6 +119,7 @@ func TestCreateChannel(t *testing.T) { { desc: "create channel with existing name", channelReq: channelReq, + domainID: domainID, token: validToken, createGroupReq: createGroupReq, svcRes: groups.Group{}, @@ -132,6 +135,7 @@ func TestCreateChannel(t *testing.T) { "test": make(chan int), }, }, + domainID: domainID, token: validToken, createGroupReq: groups.Group{}, svcRes: groups.Group{}, @@ -146,7 +150,8 @@ func TestCreateChannel(t *testing.T) { ParentID: parentID, Status: mgclients.EnabledStatus.String(), }, - token: validToken, + domainID: domainID, + token: validToken, createGroupReq: groups.Group{ Name: channel.Name, Parent: parentID, @@ -164,7 +169,8 @@ func TestCreateChannel(t *testing.T) { ParentID: wrongID, Status: mgclients.EnabledStatus.String(), }, - token: validToken, + domainID: domainID, + token: validToken, createGroupReq: groups.Group{ Name: channel.Name, Parent: wrongID, @@ -180,6 +186,7 @@ func TestCreateChannel(t *testing.T) { channelReq: sdk.Channel{ Status: mgclients.EnabledStatus.String(), }, + domainID: domainID, token: validToken, createGroupReq: groups.Group{}, svcRes: groups.Group{}, @@ -199,7 +206,8 @@ func TestCreateChannel(t *testing.T) { UpdatedAt: group.UpdatedAt, Status: mgclients.EnabledStatus.String(), }, - token: validToken, + domainID: domainID, + token: validToken, createGroupReq: groups.Group{ ID: group.ID, Parent: parentID, @@ -218,6 +226,7 @@ func TestCreateChannel(t *testing.T) { { desc: "create channel with response that can't be unmarshalled", channelReq: channelReq, + domainID: domainID, token: validToken, createGroupReq: createGroupReq, svcRes: iGroup, @@ -229,11 +238,11 @@ func TestCreateChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("CreateGroup", mock.Anything, tc.session, channelKind, tc.createGroupReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.CreateChannel(tc.channelReq, tc.token) + resp, err := mgsdk.CreateChannel(tc.channelReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -268,6 +277,7 @@ func TestListChannels(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session status mgclients.Status @@ -286,11 +296,12 @@ func TestListChannels(t *testing.T) { err errors.SDKError }{ { - desc: "list channels successfully", - token: validToken, - limit: limit, - offset: offset, - total: total, + desc: "list channels successfully", + token: validToken, + domainID: domainID, + limit: limit, + offset: offset, + total: total, groupsPageMeta: groups.Page{ PageMeta: groups.PageMeta{ Offset: offset, @@ -314,10 +325,11 @@ func TestListChannels(t *testing.T) { err: nil, }, { - desc: "list channels with invalid token", - token: invalidToken, - offset: offset, - limit: limit, + desc: "list channels with invalid token", + token: invalidToken, + domainID: domainID, + offset: offset, + limit: limit, groupsPageMeta: groups.Page{ PageMeta: groups.PageMeta{ Offset: offset, @@ -334,6 +346,7 @@ func TestListChannels(t *testing.T) { { desc: "list channels with empty token", token: "", + domainID: validID, offset: offset, limit: limit, groupsPageMeta: groups.Page{}, @@ -343,10 +356,11 @@ func TestListChannels(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "list channels with zero limit", - token: token, - offset: offset, - limit: 0, + desc: "list channels with zero limit", + token: validToken, + domainID: domainID, + offset: offset, + limit: 0, groupsPageMeta: groups.Page{ PageMeta: groups.PageMeta{ Offset: offset, @@ -372,7 +386,8 @@ func TestListChannels(t *testing.T) { }, { desc: "list channels with limit greater than max", - token: token, + token: validToken, + domainID: domainID, offset: offset, limit: 110, groupsPageMeta: groups.Page{}, @@ -382,11 +397,12 @@ func TestListChannels(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrLimitSize), http.StatusBadRequest), }, { - desc: "list channels with level", - token: token, - offset: 0, - limit: 1, - level: 1, + desc: "list channels with level", + token: validToken, + domainID: domainID, + offset: 0, + limit: 1, + level: 1, groupsPageMeta: groups.Page{ PageMeta: groups.PageMeta{ Offset: offset, @@ -413,7 +429,8 @@ func TestListChannels(t *testing.T) { }, { desc: "list channels with metadata", - token: token, + token: validToken, + domainID: domainID, offset: 0, limit: 10, metadata: sdk.Metadata{"name": "thing_89"}, @@ -442,10 +459,11 @@ func TestListChannels(t *testing.T) { err: nil, }, { - desc: "list channels with invalid metadata", - token: token, - offset: 0, - limit: 10, + desc: "list channels with invalid metadata", + token: validToken, + domainID: domainID, + offset: 0, + limit: 10, metadata: sdk.Metadata{ "test": make(chan int), }, @@ -456,10 +474,11 @@ func TestListChannels(t *testing.T) { err: errors.NewSDKError(errors.New("json: unsupported type: chan int")), }, { - desc: "list channels with service response that can't be unmarshalled", - token: token, - offset: 0, - limit: 10, + desc: "list channels with service response that can't be unmarshalled", + token: validToken, + domainID: domainID, + offset: 0, + limit: 10, groupsPageMeta: groups.Page{ PageMeta: groups.PageMeta{ Offset: 0, @@ -492,9 +511,10 @@ func TestListChannels(t *testing.T) { Limit: tc.limit, Level: uint64(tc.level), Metadata: tc.metadata, + DomainID: tc.domainID, } if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.UsersKind, "", tc.groupsPageMeta).Return(tc.svcRes, tc.svcErr) @@ -523,6 +543,7 @@ func TestViewChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -534,6 +555,7 @@ func TestViewChannel(t *testing.T) { }{ { desc: "view channel successfully", + domainID: domainID, token: validToken, channelID: groupRes.ID, svcRes: groupRes, @@ -543,6 +565,7 @@ func TestViewChannel(t *testing.T) { }, { desc: "view channel with invalid token", + domainID: domainID, token: invalidToken, channelID: groupRes.ID, svcRes: groups.Group{}, @@ -552,6 +575,7 @@ func TestViewChannel(t *testing.T) { }, { desc: "view channel with empty token", + domainID: domainID, token: "", channelID: groupRes.ID, svcRes: groups.Group{}, @@ -561,6 +585,7 @@ func TestViewChannel(t *testing.T) { }, { desc: "view channel for wrong id", + domainID: domainID, token: validToken, channelID: wrongID, svcRes: groups.Group{}, @@ -570,6 +595,7 @@ func TestViewChannel(t *testing.T) { }, { desc: "view channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", svcRes: groups.Group{}, @@ -579,6 +605,7 @@ func TestViewChannel(t *testing.T) { }, { desc: "view channel with service response that can't be unmarshalled", + domainID: domainID, token: validToken, channelID: groupRes.ID, svcRes: groups.Group{ @@ -596,11 +623,11 @@ func TestViewChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ViewGroup", mock.Anything, tc.session, tc.channelID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.Channel(tc.channelID, tc.token) + resp, err := mgsdk.Channel(tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -653,6 +680,7 @@ func TestUpdateChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelReq sdk.Channel @@ -664,8 +692,9 @@ func TestUpdateChannel(t *testing.T) { err errors.SDKError }{ { - desc: "update channel name", - token: validToken, + desc: "update channel name", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Name: newName, @@ -680,8 +709,9 @@ func TestUpdateChannel(t *testing.T) { err: nil, }, { - desc: "update channel description", - token: validToken, + desc: "update channel description", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Description: newDescription, @@ -696,8 +726,9 @@ func TestUpdateChannel(t *testing.T) { err: nil, }, { - desc: "update channel metadata", - token: validToken, + desc: "update channel metadata", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Metadata: sdk.Metadata{ @@ -714,8 +745,9 @@ func TestUpdateChannel(t *testing.T) { err: nil, }, { - desc: "update channel with every field defined", - token: validToken, + desc: "update channel with every field defined", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Name: newName, @@ -734,8 +766,9 @@ func TestUpdateChannel(t *testing.T) { err: nil, }, { - desc: "update channel name with invalid channel id", - token: validToken, + desc: "update channel name with invalid channel id", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: wrongID, Name: newName, @@ -750,8 +783,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "update channel description with invalid channel id", - token: validToken, + desc: "update channel description with invalid channel id", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: wrongID, Description: newDescription, @@ -766,8 +800,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "update channel metadata with invalid channel id", - token: validToken, + desc: "update channel metadata with invalid channel id", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: wrongID, Metadata: sdk.Metadata{ @@ -784,8 +819,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "update channel with invalid token", - token: invalidToken, + desc: "update channel with invalid token", + domainID: domainID, + token: invalidToken, channelReq: sdk.Channel{ ID: channel.ID, Name: newName, @@ -800,8 +836,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "update channel with empty token", - token: "", + desc: "update channel with empty token", + domainID: domainID, + token: "", channelReq: sdk.Channel{ ID: channel.ID, Name: newName, @@ -816,8 +853,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "update channel with name that is too long", - token: validToken, + desc: "update channel with name that is too long", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Name: strings.Repeat("a", 1025), @@ -829,8 +867,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrNameSize), http.StatusBadRequest), }, { - desc: "update channel that can't be marshalled", - token: validToken, + desc: "update channel that can't be marshalled", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Name: "test", @@ -845,8 +884,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKError(errors.New("json: unsupported type: chan int")), }, { - desc: "update channel with service response that can't be unmarshalled", - token: validToken, + desc: "update channel with service response that can't be unmarshalled", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ ID: channel.ID, Name: newName, @@ -866,8 +906,9 @@ func TestUpdateChannel(t *testing.T) { err: errors.NewSDKError(errors.New("unexpected end of JSON input")), }, { - desc: "update channel with empty channel id", - token: validToken, + desc: "update channel with empty channel id", + domainID: domainID, + token: validToken, channelReq: sdk.Channel{ Name: newName, }, @@ -881,11 +922,11 @@ func TestUpdateChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("UpdateGroup", mock.Anything, tc.session, tc.updateGroupReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.UpdateChannel(tc.channelReq, tc.token) + resp, err := mgsdk.UpdateChannel(tc.channelReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -922,6 +963,7 @@ func TestListChannelsByThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -935,6 +977,7 @@ func TestListChannelsByThing(t *testing.T) { }{ { desc: "list channels successfully", + domainID: domainID, token: validToken, thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{}, @@ -962,9 +1005,10 @@ func TestListChannelsByThing(t *testing.T) { err: nil, }, { - desc: "list channel with offset and limit", - token: validToken, - thingID: testsutil.GenerateUUID(t), + desc: "list channel with offset and limit", + domainID: domainID, + token: validToken, + thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{ Offset: 6, Limit: nChannels, @@ -993,9 +1037,10 @@ func TestListChannelsByThing(t *testing.T) { err: nil, }, { - desc: "list channel with given name", - token: validToken, - thingID: testsutil.GenerateUUID(t), + desc: "list channel with given name", + domainID: domainID, + token: validToken, + thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{ Name: "membership_8@example.com", Offset: 0, @@ -1027,6 +1072,7 @@ func TestListChannelsByThing(t *testing.T) { }, { desc: "list channels with invalid token", + domainID: domainID, token: invalidToken, thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{}, @@ -1045,6 +1091,7 @@ func TestListChannelsByThing(t *testing.T) { }, { desc: "list channels with empty token", + domainID: domainID, token: "", thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{}, @@ -1055,9 +1102,10 @@ func TestListChannelsByThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "list channels with limit greater than max", - token: validToken, - thingID: testsutil.GenerateUUID(t), + desc: "list channels with limit greater than max", + domainID: domainID, + token: validToken, + thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{ Limit: 110, }, @@ -1068,9 +1116,10 @@ func TestListChannelsByThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrLimitSize), http.StatusBadRequest), }, { - desc: "list channels with invalid metadata", - token: validToken, - thingID: testsutil.GenerateUUID(t), + desc: "list channels with invalid metadata", + domainID: domainID, + token: validToken, + thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{ Metadata: sdk.Metadata{ "test": make(chan int), @@ -1083,9 +1132,10 @@ func TestListChannelsByThing(t *testing.T) { err: errors.NewSDKError(errors.New("json: unsupported type: chan int")), }, { - desc: "list channels with service response that can't be unmarshalled", - token: validToken, - thingID: testsutil.GenerateUUID(t), + desc: "list channels with service response that can't be unmarshalled", + domainID: domainID, + token: validToken, + thingID: testsutil.GenerateUUID(t), pageMeta: sdk.PageMetadata{ Offset: 0, Limit: 10, @@ -1117,11 +1167,11 @@ func TestListChannelsByThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.ThingsKind, tc.thingID, tc.listGroupsReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.ChannelsByThing(tc.thingID, tc.pageMeta, tc.token) + resp, err := mgsdk.ChannelsByThing(tc.thingID, tc.pageMeta, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1146,6 +1196,7 @@ func TestEnableChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1157,6 +1208,7 @@ func TestEnableChannel(t *testing.T) { }{ { desc: "enable channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, svcRes: group, @@ -1166,6 +1218,7 @@ func TestEnableChannel(t *testing.T) { }, { desc: "enable channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, svcRes: groups.Group{}, @@ -1175,6 +1228,7 @@ func TestEnableChannel(t *testing.T) { }, { desc: "enable channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, svcRes: groups.Group{}, @@ -1184,6 +1238,7 @@ func TestEnableChannel(t *testing.T) { }, { desc: "enable channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, svcRes: groups.Group{}, @@ -1193,6 +1248,7 @@ func TestEnableChannel(t *testing.T) { }, { desc: "enable channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", svcRes: groups.Group{}, @@ -1202,6 +1258,7 @@ func TestEnableChannel(t *testing.T) { }, { desc: "enable channel with service response that can't be unmarshalled", + domainID: domainID, token: validToken, channelID: channel.ID, svcRes: groups.Group{ @@ -1218,11 +1275,11 @@ func TestEnableChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("EnableGroup", mock.Anything, tc.session, tc.channelID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.EnableChannel(tc.channelID, tc.token) + resp, err := mgsdk.EnableChannel(tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1252,6 +1309,7 @@ func TestDisableChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1263,6 +1321,7 @@ func TestDisableChannel(t *testing.T) { }{ { desc: "disable channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, svcRes: dGroup, @@ -1272,6 +1331,7 @@ func TestDisableChannel(t *testing.T) { }, { desc: "disable channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, svcRes: groups.Group{}, @@ -1281,6 +1341,7 @@ func TestDisableChannel(t *testing.T) { }, { desc: "disable channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, svcRes: groups.Group{}, @@ -1290,6 +1351,7 @@ func TestDisableChannel(t *testing.T) { }, { desc: "disable channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, svcRes: groups.Group{}, @@ -1299,6 +1361,7 @@ func TestDisableChannel(t *testing.T) { }, { desc: "disable channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", svcRes: groups.Group{}, @@ -1308,6 +1371,7 @@ func TestDisableChannel(t *testing.T) { }, { desc: "disable channel with service response that can't be unmarshalled", + domainID: domainID, token: validToken, channelID: channel.ID, svcRes: groups.Group{ @@ -1324,11 +1388,11 @@ func TestDisableChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("DisableGroup", mock.Anything, tc.session, tc.channelID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.DisableChannel(tc.channelID, tc.token) + resp, err := mgsdk.DisableChannel(tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1352,6 +1416,7 @@ func TestDeleteChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1361,6 +1426,7 @@ func TestDeleteChannel(t *testing.T) { }{ { desc: "delete channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, svcErr: nil, @@ -1368,6 +1434,7 @@ func TestDeleteChannel(t *testing.T) { }, { desc: "delete channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, authenticateErr: svcerr.ErrAuthentication, @@ -1375,6 +1442,7 @@ func TestDeleteChannel(t *testing.T) { }, { desc: "delete channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, svcErr: nil, @@ -1382,6 +1450,7 @@ func TestDeleteChannel(t *testing.T) { }, { desc: "delete channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, svcErr: svcerr.ErrRemoveEntity, @@ -1389,6 +1458,7 @@ func TestDeleteChannel(t *testing.T) { }, { desc: "delete channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", svcErr: svcerr.ErrRemoveEntity, @@ -1398,11 +1468,11 @@ func TestDeleteChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("DeleteGroup", mock.Anything, tc.session, tc.channelID).Return(tc.svcErr) - err := mgsdk.DeleteChannel(tc.channelID, tc.token) + err := mgsdk.DeleteChannel(tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "DeleteGroup", mock.Anything, tc.session, tc.channelID) @@ -1425,6 +1495,7 @@ func TestChannelPermissions(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1436,6 +1507,7 @@ func TestChannelPermissions(t *testing.T) { }{ { desc: "view channel permissions successfully", + domainID: domainID, token: validToken, channelID: channel.ID, svcRes: []string{"view"}, @@ -1447,6 +1519,7 @@ func TestChannelPermissions(t *testing.T) { }, { desc: "view channel permissions with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, svcRes: []string{}, @@ -1456,6 +1529,7 @@ func TestChannelPermissions(t *testing.T) { }, { desc: "view channel permissions with empty token", + domainID: domainID, token: "", channelID: channel.ID, svcRes: []string{}, @@ -1465,6 +1539,7 @@ func TestChannelPermissions(t *testing.T) { }, { desc: "view channel permissions with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, svcRes: []string{}, @@ -1474,6 +1549,7 @@ func TestChannelPermissions(t *testing.T) { }, { desc: "view channel permissions with empty channel id", + domainID: domainID, token: validToken, channelID: "", svcRes: []string{}, @@ -1486,11 +1562,11 @@ func TestChannelPermissions(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ViewGroupPerms", mock.Anything, tc.session, tc.channelID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.ChannelPermissions(tc.channelID, tc.token) + resp, err := mgsdk.ChannelPermissions(tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1514,6 +1590,7 @@ func TestAddUserToChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1524,6 +1601,7 @@ func TestAddUserToChannel(t *testing.T) { }{ { desc: "add user to channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, addUserReq: sdk.UsersRelationRequest{ @@ -1535,6 +1613,7 @@ func TestAddUserToChannel(t *testing.T) { }, { desc: "add user to channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, addUserReq: sdk.UsersRelationRequest{ @@ -1546,6 +1625,7 @@ func TestAddUserToChannel(t *testing.T) { }, { desc: "add user to channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, addUserReq: sdk.UsersRelationRequest{ @@ -1557,6 +1637,7 @@ func TestAddUserToChannel(t *testing.T) { }, { desc: "add user to channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, addUserReq: sdk.UsersRelationRequest{ @@ -1568,6 +1649,7 @@ func TestAddUserToChannel(t *testing.T) { }, { desc: "add user to channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", addUserReq: sdk.UsersRelationRequest{ @@ -1579,6 +1661,7 @@ func TestAddUserToChannel(t *testing.T) { }, { desc: "add users to channel with empty relation", + domainID: domainID, token: validToken, channelID: channel.ID, addUserReq: sdk.UsersRelationRequest{ @@ -1590,6 +1673,7 @@ func TestAddUserToChannel(t *testing.T) { }, { desc: "add users to channel with empty user ids", + domainID: domainID, token: validToken, channelID: channel.ID, addUserReq: sdk.UsersRelationRequest{ @@ -1603,11 +1687,11 @@ func TestAddUserToChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Assign", mock.Anything, tc.session, tc.channelID, tc.addUserReq.Relation, policies.UsersKind, tc.addUserReq.UserIDs).Return(tc.svcErr) - err := mgsdk.AddUserToChannel(tc.channelID, tc.addUserReq, tc.token) + err := mgsdk.AddUserToChannel(tc.channelID, tc.addUserReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Assign", mock.Anything, tc.session, tc.channelID, tc.addUserReq.Relation, policies.UsersKind, tc.addUserReq.UserIDs) @@ -1630,6 +1714,7 @@ func TestRemoveUserFromChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1640,6 +1725,7 @@ func TestRemoveUserFromChannel(t *testing.T) { }{ { desc: "remove user from channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, removeUserReq: sdk.UsersRelationRequest{ @@ -1651,6 +1737,7 @@ func TestRemoveUserFromChannel(t *testing.T) { }, { desc: "remove user from channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, removeUserReq: sdk.UsersRelationRequest{ @@ -1662,6 +1749,7 @@ func TestRemoveUserFromChannel(t *testing.T) { }, { desc: "remove user from channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, removeUserReq: sdk.UsersRelationRequest{ @@ -1673,6 +1761,7 @@ func TestRemoveUserFromChannel(t *testing.T) { }, { desc: "remove user from channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, removeUserReq: sdk.UsersRelationRequest{ @@ -1684,6 +1773,7 @@ func TestRemoveUserFromChannel(t *testing.T) { }, { desc: "remove user from channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", removeUserReq: sdk.UsersRelationRequest{ @@ -1695,6 +1785,7 @@ func TestRemoveUserFromChannel(t *testing.T) { }, { desc: "remove users from channel with empty user ids", + domainID: domainID, token: validToken, channelID: channel.ID, removeUserReq: sdk.UsersRelationRequest{ @@ -1708,11 +1799,11 @@ func TestRemoveUserFromChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Unassign", mock.Anything, tc.session, tc.channelID, tc.removeUserReq.Relation, policies.UsersKind, tc.removeUserReq.UserIDs).Return(tc.svcErr) - err := mgsdk.RemoveUserFromChannel(tc.channelID, tc.removeUserReq, tc.token) + err := mgsdk.RemoveUserFromChannel(tc.channelID, tc.removeUserReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Unassign", mock.Anything, tc.session, tc.channelID, tc.removeUserReq.Relation, policies.UsersKind, tc.removeUserReq.UserIDs) @@ -1739,6 +1830,7 @@ func TestAddUserGroupToChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1749,6 +1841,7 @@ func TestAddUserGroupToChannel(t *testing.T) { }{ { desc: "add user group to channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, addUserGroupReq: sdk.UserGroupsRequest{ @@ -1759,6 +1852,7 @@ func TestAddUserGroupToChannel(t *testing.T) { }, { desc: "add user group to channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, addUserGroupReq: sdk.UserGroupsRequest{ @@ -1769,6 +1863,7 @@ func TestAddUserGroupToChannel(t *testing.T) { }, { desc: "add user group to channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, addUserGroupReq: sdk.UserGroupsRequest{ @@ -1779,6 +1874,7 @@ func TestAddUserGroupToChannel(t *testing.T) { }, { desc: "add user group to channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, addUserGroupReq: sdk.UserGroupsRequest{ @@ -1789,6 +1885,7 @@ func TestAddUserGroupToChannel(t *testing.T) { }, { desc: "add user group to channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", addUserGroupReq: sdk.UserGroupsRequest{ @@ -1799,6 +1896,7 @@ func TestAddUserGroupToChannel(t *testing.T) { }, { desc: "add user group to channel with empty group ids", + domainID: domainID, token: validToken, channelID: channel.ID, addUserGroupReq: sdk.UserGroupsRequest{ @@ -1811,11 +1909,11 @@ func TestAddUserGroupToChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Assign", mock.Anything, tc.session, tc.channelID, relation, policies.ChannelsKind, tc.addUserGroupReq.UserGroupIDs).Return(tc.svcErr) - err := mgsdk.AddUserGroupToChannel(tc.channelID, tc.addUserGroupReq, tc.token) + err := mgsdk.AddUserGroupToChannel(tc.channelID, tc.addUserGroupReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Assign", mock.Anything, tc.session, tc.channelID, relation, policies.ChannelsKind, tc.addUserGroupReq.UserGroupIDs) @@ -1842,6 +1940,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -1852,6 +1951,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { }{ { desc: "remove user group from channel successfully", + domainID: domainID, token: validToken, channelID: channel.ID, removeUserGroupReq: sdk.UserGroupsRequest{ @@ -1862,6 +1962,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { }, { desc: "remove user group from channel with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, removeUserGroupReq: sdk.UserGroupsRequest{ @@ -1872,6 +1973,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { }, { desc: "remove user group from channel with empty token", + domainID: domainID, token: "", channelID: channel.ID, removeUserGroupReq: sdk.UserGroupsRequest{ @@ -1882,6 +1984,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { }, { desc: "remove user group from channel with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, removeUserGroupReq: sdk.UserGroupsRequest{ @@ -1892,6 +1995,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { }, { desc: "remove user group from channel with empty channel id", + domainID: domainID, token: validToken, channelID: "", removeUserGroupReq: sdk.UserGroupsRequest{ @@ -1902,6 +2006,7 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { }, { desc: "remove user group from channel with empty group ids", + domainID: domainID, token: validToken, channelID: channel.ID, removeUserGroupReq: sdk.UserGroupsRequest{ @@ -1914,11 +2019,11 @@ func TestRemoveUserGroupFromChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Unassign", mock.Anything, tc.session, tc.channelID, relation, policies.ChannelsKind, tc.removeUserGroupReq.UserGroupIDs).Return(tc.svcErr) - err := mgsdk.RemoveUserGroupFromChannel(tc.channelID, tc.removeUserGroupReq, tc.token) + err := mgsdk.RemoveUserGroupFromChannel(tc.channelID, tc.removeUserGroupReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Unassign", mock.Anything, tc.session, tc.channelID, relation, policies.ChannelsKind, tc.removeUserGroupReq.UserGroupIDs) @@ -1969,7 +2074,9 @@ func TestListChannelUserGroups(t *testing.T) { desc: "list user groups successfully", token: validToken, channelID: channel.ID, - pageMeta: sdk.PageMetadata{}, + pageMeta: sdk.PageMetadata{ + DomainID: domainID, + }, listGroupsReq: groups.Page{ PageMeta: groups.PageMeta{ Offset: 0, @@ -1998,8 +2105,9 @@ func TestListChannelUserGroups(t *testing.T) { token: validToken, channelID: channel.ID, pageMeta: sdk.PageMetadata{ - Offset: 6, - Limit: nGroups, + Offset: 6, + Limit: nGroups, + DomainID: domainID, }, listGroupsReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2028,7 +2136,9 @@ func TestListChannelUserGroups(t *testing.T) { desc: "list user groups with invalid token", token: invalidToken, channelID: channel.ID, - pageMeta: sdk.PageMetadata{}, + pageMeta: sdk.PageMetadata{ + DomainID: domainID, + }, listGroupsReq: groups.Page{ PageMeta: groups.PageMeta{ Offset: 0, @@ -2046,7 +2156,9 @@ func TestListChannelUserGroups(t *testing.T) { desc: "list user groups with empty token", token: "", channelID: channel.ID, - pageMeta: sdk.PageMetadata{}, + pageMeta: sdk.PageMetadata{ + DomainID: domainID, + }, listGroupsReq: groups.Page{ PageMeta: groups.PageMeta{ Offset: 0, @@ -2065,7 +2177,8 @@ func TestListChannelUserGroups(t *testing.T) { token: validToken, channelID: channel.ID, pageMeta: sdk.PageMetadata{ - Limit: 110, + Limit: 110, + DomainID: domainID, }, listGroupsReq: groups.Page{}, svcRes: groups.Page{}, @@ -2077,7 +2190,9 @@ func TestListChannelUserGroups(t *testing.T) { desc: "list user groups with invalid channel id", token: validToken, channelID: wrongID, - pageMeta: sdk.PageMetadata{}, + pageMeta: sdk.PageMetadata{ + DomainID: domainID, + }, listGroupsReq: groups.Page{ PageMeta: groups.PageMeta{ Offset: 0, @@ -2096,7 +2211,8 @@ func TestListChannelUserGroups(t *testing.T) { token: validToken, channelID: channel.ID, pageMeta: sdk.PageMetadata{ - Level: 10, + Level: 10, + DomainID: domainID, }, listGroupsReq: groups.Page{}, svcRes: groups.Page{}, @@ -2109,8 +2225,9 @@ func TestListChannelUserGroups(t *testing.T) { token: validToken, channelID: channel.ID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, Metadata: sdk.Metadata{ "test": make(chan int), }, @@ -2125,7 +2242,9 @@ func TestListChannelUserGroups(t *testing.T) { desc: "list user groups with service response that can't be unmarshalled", token: validToken, channelID: channel.ID, - pageMeta: sdk.PageMetadata{}, + pageMeta: sdk.PageMetadata{ + DomainID: domainID, + }, listGroupsReq: groups.Page{ PageMeta: groups.PageMeta{ Offset: 0, @@ -2153,7 +2272,7 @@ func TestListChannelUserGroups(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.ChannelsKind, tc.channelID, tc.listGroupsReq).Return(tc.svcRes, tc.svcErr) @@ -2183,6 +2302,7 @@ func TestConnect(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session connection sdk.Connection @@ -2192,8 +2312,9 @@ func TestConnect(t *testing.T) { err errors.SDKError }{ { - desc: "connect successfully", - token: validToken, + desc: "connect successfully", + domainID: domainID, + token: validToken, connection: sdk.Connection{ ChannelID: channel.ID, ThingID: thingID, @@ -2202,8 +2323,9 @@ func TestConnect(t *testing.T) { err: nil, }, { - desc: "connect with invalid token", - token: invalidToken, + desc: "connect with invalid token", + domainID: domainID, + token: invalidToken, connection: sdk.Connection{ ChannelID: channel.ID, ThingID: thingID, @@ -2212,8 +2334,9 @@ func TestConnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "connect with empty token", - token: "", + desc: "connect with empty token", + domainID: domainID, + token: "", connection: sdk.Connection{ ChannelID: channel.ID, ThingID: thingID, @@ -2221,8 +2344,9 @@ func TestConnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "connect with invalid channel id", - token: validToken, + desc: "connect with invalid channel id", + domainID: domainID, + token: validToken, connection: sdk.Connection{ ChannelID: wrongID, ThingID: thingID, @@ -2231,8 +2355,9 @@ func TestConnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "connect with empty channel id", - token: validToken, + desc: "connect with empty channel id", + domainID: domainID, + token: validToken, connection: sdk.Connection{ ChannelID: "", ThingID: thingID, @@ -2241,8 +2366,9 @@ func TestConnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "connect with empty thing id", - token: validToken, + desc: "connect with empty thing id", + domainID: domainID, + token: validToken, connection: sdk.Connection{ ChannelID: channel.ID, ThingID: "", @@ -2254,11 +2380,11 @@ func TestConnect(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Assign", mock.Anything, tc.session, tc.connection.ChannelID, policies.GroupRelation, policies.ThingsKind, []string{tc.connection.ThingID}).Return(tc.svcErr) - err := mgsdk.Connect(tc.connection, tc.token) + err := mgsdk.Connect(tc.connection, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Assign", mock.Anything, tc.session, tc.connection.ChannelID, policies.GroupRelation, policies.ThingsKind, []string{tc.connection.ThingID}) @@ -2283,6 +2409,7 @@ func TestDisconnect(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session disconnect sdk.Connection @@ -2292,8 +2419,9 @@ func TestDisconnect(t *testing.T) { err errors.SDKError }{ { - desc: "disconnect successfully", - token: validToken, + desc: "disconnect successfully", + domainID: domainID, + token: validToken, disconnect: sdk.Connection{ ChannelID: channel.ID, ThingID: thingID, @@ -2302,8 +2430,9 @@ func TestDisconnect(t *testing.T) { err: nil, }, { - desc: "disconnect with invalid token", - token: invalidToken, + desc: "disconnect with invalid token", + domainID: domainID, + token: invalidToken, disconnect: sdk.Connection{ ChannelID: channel.ID, ThingID: thingID, @@ -2312,8 +2441,9 @@ func TestDisconnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "disconnect with empty token", - token: "", + desc: "disconnect with empty token", + domainID: domainID, + token: "", disconnect: sdk.Connection{ ChannelID: channel.ID, ThingID: thingID, @@ -2321,8 +2451,9 @@ func TestDisconnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "disconnect with invalid channel id", - token: validToken, + desc: "disconnect with invalid channel id", + domainID: domainID, + token: validToken, disconnect: sdk.Connection{ ChannelID: wrongID, ThingID: thingID, @@ -2331,8 +2462,9 @@ func TestDisconnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "disconnect with empty channel id", - token: validToken, + desc: "disconnect with empty channel id", + domainID: domainID, + token: validToken, disconnect: sdk.Connection{ ChannelID: "", ThingID: thingID, @@ -2341,8 +2473,9 @@ func TestDisconnect(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "disconnect with empty thing id", - token: validToken, + desc: "disconnect with empty thing id", + domainID: domainID, + token: validToken, disconnect: sdk.Connection{ ChannelID: channel.ID, ThingID: "", @@ -2354,11 +2487,11 @@ func TestDisconnect(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Unassign", mock.Anything, tc.session, tc.disconnect.ChannelID, policies.GroupRelation, policies.ThingsKind, []string{tc.disconnect.ThingID}).Return(tc.svcErr) - err := mgsdk.Disconnect(tc.disconnect, tc.token) + err := mgsdk.Disconnect(tc.disconnect, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Unassign", mock.Anything, tc.session, tc.disconnect.ChannelID, policies.GroupRelation, policies.ThingsKind, []string{tc.disconnect.ThingID}) @@ -2383,6 +2516,7 @@ func TestConnectThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -2394,6 +2528,7 @@ func TestConnectThing(t *testing.T) { }{ { desc: "connect successfully", + domainID: domainID, token: validToken, channelID: channel.ID, thingID: thingID, @@ -2402,6 +2537,7 @@ func TestConnectThing(t *testing.T) { }, { desc: "connect with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, thingID: thingID, @@ -2410,6 +2546,7 @@ func TestConnectThing(t *testing.T) { }, { desc: "connect with empty token", + domainID: domainID, token: "", channelID: channel.ID, thingID: thingID, @@ -2417,6 +2554,7 @@ func TestConnectThing(t *testing.T) { }, { desc: "connect with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, thingID: thingID, @@ -2425,6 +2563,7 @@ func TestConnectThing(t *testing.T) { }, { desc: "connect with empty channel id", + domainID: domainID, token: validToken, channelID: "", thingID: thingID, @@ -2433,6 +2572,7 @@ func TestConnectThing(t *testing.T) { }, { desc: "connect with empty thing id", + domainID: domainID, token: validToken, channelID: channel.ID, thingID: "", @@ -2443,11 +2583,11 @@ func TestConnectThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Assign", mock.Anything, tc.session, tc.channelID, policies.GroupRelation, policies.ThingsKind, []string{tc.thingID}).Return(tc.svcErr) - err := mgsdk.ConnectThing(tc.thingID, tc.channelID, tc.token) + err := mgsdk.ConnectThing(tc.thingID, tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Assign", mock.Anything, tc.session, tc.channelID, policies.GroupRelation, policies.ThingsKind, []string{tc.thingID}) @@ -2472,6 +2612,7 @@ func TestDisconnectThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session channelID string @@ -2482,6 +2623,7 @@ func TestDisconnectThing(t *testing.T) { }{ { desc: "disconnect successfully", + domainID: domainID, token: validToken, channelID: channel.ID, thingID: thingID, @@ -2490,6 +2632,7 @@ func TestDisconnectThing(t *testing.T) { }, { desc: "disconnect with invalid token", + domainID: domainID, token: invalidToken, channelID: channel.ID, thingID: thingID, @@ -2498,6 +2641,7 @@ func TestDisconnectThing(t *testing.T) { }, { desc: "disconnect with empty token", + domainID: domainID, token: "", channelID: channel.ID, thingID: thingID, @@ -2505,6 +2649,7 @@ func TestDisconnectThing(t *testing.T) { }, { desc: "disconnect with invalid channel id", + domainID: domainID, token: validToken, channelID: wrongID, thingID: thingID, @@ -2513,6 +2658,7 @@ func TestDisconnectThing(t *testing.T) { }, { desc: "disconnect with empty channel id", + domainID: domainID, token: validToken, channelID: "", thingID: thingID, @@ -2521,6 +2667,7 @@ func TestDisconnectThing(t *testing.T) { }, { desc: "disconnect with empty thing id", + domainID: domainID, token: validToken, channelID: channel.ID, thingID: "", @@ -2531,11 +2678,11 @@ func TestDisconnectThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Unassign", mock.Anything, tc.session, tc.channelID, policies.GroupRelation, policies.ThingsKind, []string{tc.thingID}).Return(tc.svcErr) - err := mgsdk.DisconnectThing(tc.thingID, tc.channelID, tc.token) + err := mgsdk.DisconnectThing(tc.thingID, tc.channelID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Unassign", mock.Anything, tc.session, tc.channelID, policies.GroupRelation, policies.ThingsKind, []string{tc.thingID}) @@ -2581,8 +2728,9 @@ func TestListGroupChannels(t *testing.T) { token: validToken, groupID: group.ID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2612,8 +2760,9 @@ func TestListGroupChannels(t *testing.T) { token: invalidToken, groupID: group.ID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2633,8 +2782,9 @@ func TestListGroupChannels(t *testing.T) { token: "", groupID: group.ID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -2647,8 +2797,9 @@ func TestListGroupChannels(t *testing.T) { token: validToken, groupID: wrongID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2668,8 +2819,9 @@ func TestListGroupChannels(t *testing.T) { token: validToken, groupID: group.ID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, Metadata: sdk.Metadata{ "test": make(chan int), }, @@ -2685,8 +2837,9 @@ func TestListGroupChannels(t *testing.T) { token: validToken, groupID: group.ID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2715,7 +2868,7 @@ func TestListGroupChannels(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.GroupsKind, tc.groupID, tc.svcReq).Return(tc.svcRes, tc.svcErr) diff --git a/pkg/sdk/go/groups.go b/pkg/sdk/go/groups.go index f0bb09d51e..83fd7ade14 100644 --- a/pkg/sdk/go/groups.go +++ b/pkg/sdk/go/groups.go @@ -39,12 +39,12 @@ type Group struct { Permissions []string `json:"permissions,omitempty"` } -func (sdk mgSDK) CreateGroup(g Group, token string) (Group, errors.SDKError) { +func (sdk mgSDK) CreateGroup(g Group, domainID, token string) (Group, errors.SDKError) { data, err := json.Marshal(g) if err != nil { return Group{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.usersURL, groupsEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint) _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) if sdkerr != nil { @@ -60,7 +60,8 @@ func (sdk mgSDK) CreateGroup(g Group, token string) (Group, errors.SDKError) { } func (sdk mgSDK) Groups(pm PageMetadata, token string) (GroupsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, groupsEndpoint, pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, groupsEndpoint) + url, err := sdk.withQueryParams(sdk.usersURL, endpoint, pm) if err != nil { return GroupsPage{}, errors.NewSDKError(err) } @@ -70,7 +71,8 @@ func (sdk mgSDK) Groups(pm PageMetadata, token string) (GroupsPage, errors.SDKEr func (sdk mgSDK) Parents(id string, pm PageMetadata, token string) (GroupsPage, errors.SDKError) { pm.Level = MaxLevel - url, err := sdk.withQueryParams(fmt.Sprintf("%s/%s/%s", sdk.usersURL, groupsEndpoint, id), "parents", pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, groupsEndpoint) + url, err := sdk.withQueryParams(fmt.Sprintf("%s/%s/%s", sdk.usersURL, endpoint, id), "parents", pm) if err != nil { return GroupsPage{}, errors.NewSDKError(err) } @@ -80,7 +82,8 @@ func (sdk mgSDK) Parents(id string, pm PageMetadata, token string) (GroupsPage, func (sdk mgSDK) Children(id string, pm PageMetadata, token string) (GroupsPage, errors.SDKError) { pm.Level = MaxLevel - url, err := sdk.withQueryParams(fmt.Sprintf("%s/%s/%s", sdk.usersURL, groupsEndpoint, id), "children", pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, groupsEndpoint) + url, err := sdk.withQueryParams(fmt.Sprintf("%s/%s/%s", sdk.usersURL, endpoint, id), "children", pm) if err != nil { return GroupsPage{}, errors.NewSDKError(err) } @@ -102,12 +105,12 @@ func (sdk mgSDK) getGroups(url, token string) (GroupsPage, errors.SDKError) { return tp, nil } -func (sdk mgSDK) Group(id, token string) (Group, errors.SDKError) { +func (sdk mgSDK) Group(id, domainID, token string) (Group, errors.SDKError) { if id == "" { return Group{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, groupsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, id) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -122,8 +125,8 @@ func (sdk mgSDK) Group(id, token string) (Group, errors.SDKError) { return t, nil } -func (sdk mgSDK) GroupPermissions(id, token string) (Group, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, id, permissionsEndpoint) +func (sdk mgSDK) GroupPermissions(id, domainID, token string) (Group, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, id, permissionsEndpoint) _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if err != nil { @@ -138,7 +141,7 @@ func (sdk mgSDK) GroupPermissions(id, token string) (Group, errors.SDKError) { return t, nil } -func (sdk mgSDK) UpdateGroup(g Group, token string) (Group, errors.SDKError) { +func (sdk mgSDK) UpdateGroup(g Group, domainID, token string) (Group, errors.SDKError) { data, err := json.Marshal(g) if err != nil { return Group{}, errors.NewSDKError(err) @@ -147,7 +150,7 @@ func (sdk mgSDK) UpdateGroup(g Group, token string) (Group, errors.SDKError) { if g.ID == "" { return Group{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, groupsEndpoint, g.ID) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, g.ID) _, body, sdkerr := sdk.processRequest(http.MethodPut, url, token, data, nil, http.StatusOK) if sdkerr != nil { @@ -162,40 +165,40 @@ func (sdk mgSDK) UpdateGroup(g Group, token string) (Group, errors.SDKError) { return g, nil } -func (sdk mgSDK) EnableGroup(id, token string) (Group, errors.SDKError) { - return sdk.changeGroupStatus(id, enableEndpoint, token) +func (sdk mgSDK) EnableGroup(id, domainID, token string) (Group, errors.SDKError) { + return sdk.changeGroupStatus(id, enableEndpoint, domainID, token) } -func (sdk mgSDK) DisableGroup(id, token string) (Group, errors.SDKError) { - return sdk.changeGroupStatus(id, disableEndpoint, token) +func (sdk mgSDK) DisableGroup(id, domainID, token string) (Group, errors.SDKError) { + return sdk.changeGroupStatus(id, disableEndpoint, domainID, token) } -func (sdk mgSDK) AddUserToGroup(groupID string, req UsersRelationRequest, token string) errors.SDKError { +func (sdk mgSDK) AddUserToGroup(groupID string, req UsersRelationRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, groupID, usersEndpoint, assignEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, groupID, usersEndpoint, assignEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) return sdkerr } -func (sdk mgSDK) RemoveUserFromGroup(groupID string, req UsersRelationRequest, token string) errors.SDKError { +func (sdk mgSDK) RemoveUserFromGroup(groupID string, req UsersRelationRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, groupID, usersEndpoint, unassignEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, groupID, usersEndpoint, unassignEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) ListGroupUsers(groupID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", groupsEndpoint, groupID, usersEndpoint), pm) + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, groupsEndpoint, groupID, usersEndpoint), pm) if err != nil { return UsersPage{}, errors.NewSDKError(err) } @@ -212,7 +215,7 @@ func (sdk mgSDK) ListGroupUsers(groupID string, pm PageMetadata, token string) ( } func (sdk mgSDK) ListGroupChannels(groupID string, pm PageMetadata, token string) (ChannelsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/%s/%s", groupsEndpoint, groupID, channelsEndpoint), pm) + url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, groupsEndpoint, groupID, channelsEndpoint), pm) if err != nil { return ChannelsPage{}, errors.NewSDKError(err) } @@ -228,17 +231,17 @@ func (sdk mgSDK) ListGroupChannels(groupID string, pm PageMetadata, token string return cp, nil } -func (sdk mgSDK) DeleteGroup(id, token string) errors.SDKError { +func (sdk mgSDK) DeleteGroup(id, domainID, token string) errors.SDKError { if id == "" { return errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.usersURL, groupsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, id) _, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent) return sdkerr } -func (sdk mgSDK) changeGroupStatus(id, status, token string) (Group, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, id, status) +func (sdk mgSDK) changeGroupStatus(id, status, domainID, token string) (Group, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.usersURL, domainID, groupsEndpoint, id, status) _, body, err := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusOK) if err != nil { diff --git a/pkg/sdk/go/groups_test.go b/pkg/sdk/go/groups_test.go index 44e07b8ea5..f429dfd640 100644 --- a/pkg/sdk/go/groups_test.go +++ b/pkg/sdk/go/groups_test.go @@ -79,6 +79,7 @@ func TestCreateGroup(t *testing.T) { } cases := []struct { desc string + domainID string token string session mgauthn.Session groupReq sdk.Group @@ -91,6 +92,7 @@ func TestCreateGroup(t *testing.T) { }{ { desc: "create group successfully", + domainID: domainID, token: validToken, groupReq: createGroupReq, svcReq: groups.Group{ @@ -105,6 +107,7 @@ func TestCreateGroup(t *testing.T) { }, { desc: "create group with existing name", + domainID: domainID, token: validToken, groupReq: createGroupReq, svcReq: groups.Group{ @@ -118,8 +121,9 @@ func TestCreateGroup(t *testing.T) { err: nil, }, { - desc: "create group with parent", - token: validToken, + desc: "create group with parent", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ Name: gName, Description: description, @@ -138,8 +142,9 @@ func TestCreateGroup(t *testing.T) { err: nil, }, { - desc: "create group with invalid parent", - token: validToken, + desc: "create group with invalid parent", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ Name: gName, Description: description, @@ -158,8 +163,9 @@ func TestCreateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "create group with invalid token", - token: invalidToken, + desc: "create group with invalid token", + domainID: domainID, + token: invalidToken, groupReq: sdk.Group{ Name: gName, Description: description, @@ -176,8 +182,9 @@ func TestCreateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "create group with empty token", - token: "", + desc: "create group with empty token", + domainID: domainID, + token: "", groupReq: sdk.Group{ Name: gName, Description: description, @@ -190,8 +197,9 @@ func TestCreateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "create group with missing name", - token: validToken, + desc: "create group with missing name", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ Description: description, Metadata: validMetadata, @@ -203,8 +211,9 @@ func TestCreateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrNameSize), http.StatusBadRequest), }, { - desc: "create group with name that is too long", - token: validToken, + desc: "create group with name that is too long", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ Name: strings.Repeat("a", 1025), Description: description, @@ -217,8 +226,9 @@ func TestCreateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrNameSize), http.StatusBadRequest), }, { - desc: "create group with request that cannot be marshalled", - token: validToken, + desc: "create group with request that cannot be marshalled", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ Name: gName, Description: description, @@ -233,8 +243,9 @@ func TestCreateGroup(t *testing.T) { err: errors.NewSDKError(errors.New("json: unsupported type: chan int")), }, { - desc: "create group with service response that cannot be unmarshalled", - token: validToken, + desc: "create group with service response that cannot be unmarshalled", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ Name: gName, Description: description, @@ -254,11 +265,11 @@ func TestCreateGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("CreateGroup", mock.Anything, tc.session, policies.NewGroupKind, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.CreateGroup(tc.groupReq, tc.token) + resp, err := mgsdk.CreateGroup(tc.groupReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -307,8 +318,9 @@ func TestListGroups(t *testing.T) { desc: "list groups successfully", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 100, + Offset: offset, + Limit: 100, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -336,8 +348,9 @@ func TestListGroups(t *testing.T) { desc: "list groups with invalid token", token: invalidToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 100, + Offset: offset, + Limit: 100, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -347,16 +360,17 @@ func TestListGroups(t *testing.T) { Permission: policies.ViewPermission, Direction: -1, }, - svcRes: groups.Page{}, - svcErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), + svcRes: groups.Page{}, + authenticateErr: svcerr.ErrAuthentication, + err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { desc: "list groups with empty token", token: "", pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 100, + Offset: offset, + Limit: 100, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -368,8 +382,9 @@ func TestListGroups(t *testing.T) { desc: "list groups with zero limit", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 0, + Offset: offset, + Limit: 0, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -398,8 +413,9 @@ func TestListGroups(t *testing.T) { desc: "list groups with limit greater than max", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 110, + Offset: offset, + Limit: 110, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -409,10 +425,11 @@ func TestListGroups(t *testing.T) { }, { desc: "list groups with given name", - token: token, + token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, Metadata: sdk.Metadata{ "name": "user_89", }, @@ -447,9 +464,10 @@ func TestListGroups(t *testing.T) { desc: "list groups with invalid level", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 100, - Level: 6, + Offset: offset, + Limit: 100, + Level: 6, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -466,6 +484,7 @@ func TestListGroups(t *testing.T) { Metadata: sdk.Metadata{ "key": make(chan int), }, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -477,8 +496,9 @@ func TestListGroups(t *testing.T) { desc: "list groups with service response that cannot be unmarshalled", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -508,7 +528,7 @@ func TestListGroups(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.UsersKind, "", tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -567,8 +587,9 @@ func TestListParentGroups(t *testing.T) { token: validToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -599,8 +620,9 @@ func TestListParentGroups(t *testing.T) { token: invalidToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -622,8 +644,9 @@ func TestListParentGroups(t *testing.T) { token: "", parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -636,8 +659,9 @@ func TestListParentGroups(t *testing.T) { token: validToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 0, + Offset: offset, + Limit: 0, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -668,8 +692,9 @@ func TestListParentGroups(t *testing.T) { token: validToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 110, + Offset: offset, + Limit: 110, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -682,8 +707,9 @@ func TestListParentGroups(t *testing.T) { token: validToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, Metadata: sdk.Metadata{ "name": "user_89", }, @@ -720,8 +746,9 @@ func TestListParentGroups(t *testing.T) { token: validToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, Metadata: sdk.Metadata{ "key": make(chan int), }, @@ -737,8 +764,9 @@ func TestListParentGroups(t *testing.T) { token: validToken, parentID: parentID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -771,7 +799,7 @@ func TestListParentGroups(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.UsersKind, "", tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -831,8 +859,9 @@ func TestListChildrenGroups(t *testing.T) { token: validToken, childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -863,8 +892,9 @@ func TestListChildrenGroups(t *testing.T) { token: invalidToken, childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -886,8 +916,9 @@ func TestListChildrenGroups(t *testing.T) { token: "", childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -900,8 +931,9 @@ func TestListChildrenGroups(t *testing.T) { token: validToken, childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 0, + Offset: offset, + Limit: 0, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -931,8 +963,9 @@ func TestListChildrenGroups(t *testing.T) { desc: "list children groups with limit greater than max", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: 110, + Offset: offset, + Limit: 110, + DomainID: domainID, }, svcReq: groups.Page{}, svcRes: groups.Page{}, @@ -945,8 +978,9 @@ func TestListChildrenGroups(t *testing.T) { token: validToken, childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, Metadata: sdk.Metadata{ "name": "user_89", }, @@ -983,8 +1017,9 @@ func TestListChildrenGroups(t *testing.T) { token: validToken, childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, Metadata: sdk.Metadata{ "key": make(chan int), }, @@ -1000,8 +1035,9 @@ func TestListChildrenGroups(t *testing.T) { token: validToken, childID: childID, pageMeta: sdk.PageMetadata{ - Offset: offset, - Limit: limit, + Offset: offset, + Limit: limit, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -1034,7 +1070,7 @@ func TestListChildrenGroups(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ListGroups", mock.Anything, tc.session, policies.UsersKind, "", tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -1062,6 +1098,7 @@ func TestViewGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1073,6 +1110,7 @@ func TestViewGroup(t *testing.T) { }{ { desc: "view group successfully", + domainID: domainID, token: validToken, groupID: group.ID, svcRes: group, @@ -1082,6 +1120,7 @@ func TestViewGroup(t *testing.T) { }, { desc: "view group with invalid token", + domainID: domainID, token: invalidToken, groupID: group.ID, svcRes: groups.Group{}, @@ -1091,6 +1130,7 @@ func TestViewGroup(t *testing.T) { }, { desc: "view group with empty token", + domainID: domainID, token: "", groupID: group.ID, svcRes: groups.Group{}, @@ -1100,6 +1140,7 @@ func TestViewGroup(t *testing.T) { }, { desc: "view group with invalid group id", + domainID: domainID, token: validToken, groupID: wrongID, svcRes: groups.Group{}, @@ -1108,9 +1149,10 @@ func TestViewGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrViewEntity, http.StatusBadRequest), }, { - desc: "view group with service response that cannot be unmarshalled", - token: validToken, - groupID: group.ID, + desc: "view group with service response that cannot be unmarshalled", + domainID: domainID, + token: validToken, + groupID: group.ID, svcRes: groups.Group{ ID: group.ID, Name: "group_1", @@ -1124,6 +1166,7 @@ func TestViewGroup(t *testing.T) { }, { desc: "view group with empty id", + domainID: domainID, token: validToken, groupID: "", svcRes: groups.Group{}, @@ -1136,11 +1179,11 @@ func TestViewGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ViewGroup", mock.Anything, tc.session, tc.groupID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.Group(tc.groupID, tc.token) + resp, err := mgsdk.Group(tc.groupID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1164,6 +1207,7 @@ func TestViewGroupPermissions(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1174,11 +1218,12 @@ func TestViewGroupPermissions(t *testing.T) { err errors.SDKError }{ { - desc: "view group permissions successfully", - token: validToken, - groupID: group.ID, - svcRes: []string{policies.ViewPermission, policies.MembershipPermission}, - svcErr: nil, + desc: "view group permissions successfully", + domainID: domainID, + token: validToken, + groupID: group.ID, + svcRes: []string{policies.ViewPermission, policies.MembershipPermission}, + svcErr: nil, response: sdk.Group{ Permissions: []string{policies.ViewPermission, policies.MembershipPermission}, }, @@ -1186,6 +1231,7 @@ func TestViewGroupPermissions(t *testing.T) { }, { desc: "view group permissions with invalid token", + domainID: domainID, token: invalidToken, groupID: group.ID, svcRes: []string{}, @@ -1195,6 +1241,7 @@ func TestViewGroupPermissions(t *testing.T) { }, { desc: "view group permissions with empty token", + domainID: domainID, token: "", groupID: group.ID, svcRes: []string{}, @@ -1204,6 +1251,7 @@ func TestViewGroupPermissions(t *testing.T) { }, { desc: "view group permissions with invalid group id", + domainID: domainID, token: validToken, groupID: wrongID, svcRes: []string{}, @@ -1213,6 +1261,7 @@ func TestViewGroupPermissions(t *testing.T) { }, { desc: "view group permissions with empty id", + domainID: domainID, token: validToken, groupID: "", svcRes: []string{}, @@ -1224,11 +1273,11 @@ func TestViewGroupPermissions(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("ViewGroupPerms", mock.Anything, tc.session, tc.groupID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.GroupPermissions(tc.groupID, tc.token) + resp, err := mgsdk.GroupPermissions(tc.groupID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1259,6 +1308,7 @@ func TestUpdateGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupReq sdk.Group @@ -1270,8 +1320,9 @@ func TestUpdateGroup(t *testing.T) { err errors.SDKError }{ { - desc: "update group successfully", - token: validToken, + desc: "update group successfully", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ ID: group.ID, Name: updatedName, @@ -1290,8 +1341,9 @@ func TestUpdateGroup(t *testing.T) { err: nil, }, { - desc: "update group name with invalid group id", - token: validToken, + desc: "update group name with invalid group id", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ ID: wrongID, Name: updatedName, @@ -1310,8 +1362,9 @@ func TestUpdateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), }, { - desc: "update group name with invalid token", - token: invalidToken, + desc: "update group name with invalid token", + domainID: domainID, + token: invalidToken, groupReq: sdk.Group{ ID: group.ID, Name: updatedName, @@ -1330,8 +1383,9 @@ func TestUpdateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "update group name with empty token", - token: "", + desc: "update group name with empty token", + domainID: domainID, + token: "", groupReq: sdk.Group{ ID: group.ID, Name: updatedName, @@ -1345,8 +1399,9 @@ func TestUpdateGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "update group with empty id", - token: validToken, + desc: "update group with empty id", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ ID: "", Name: updatedName, @@ -1360,8 +1415,9 @@ func TestUpdateGroup(t *testing.T) { err: errors.NewSDKError(apiutil.ErrMissingID), }, { - desc: "update group with request that can't be marshalled", - token: validToken, + desc: "update group with request that can't be marshalled", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ ID: group.ID, Name: updatedName, @@ -1375,8 +1431,9 @@ func TestUpdateGroup(t *testing.T) { err: errors.NewSDKError(errors.New("json: unsupported type: chan int")), }, { - desc: "update group with service response that cannot be unmarshalled", - token: validToken, + desc: "update group with service response that cannot be unmarshalled", + domainID: domainID, + token: validToken, groupReq: sdk.Group{ ID: group.ID, Name: updatedName, @@ -1405,11 +1462,11 @@ func TestUpdateGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("UpdateGroup", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.UpdateGroup(tc.groupReq, tc.token) + resp, err := mgsdk.UpdateGroup(tc.groupReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1436,6 +1493,7 @@ func TestEnableGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1447,6 +1505,7 @@ func TestEnableGroup(t *testing.T) { }{ { desc: "enable group successfully", + domainID: domainID, token: validToken, groupID: group.ID, svcRes: convertGroup(enGroup), @@ -1456,6 +1515,7 @@ func TestEnableGroup(t *testing.T) { }, { desc: "enable group with invalid group id", + domainID: domainID, token: validToken, groupID: wrongID, svcRes: groups.Group{}, @@ -1465,6 +1525,7 @@ func TestEnableGroup(t *testing.T) { }, { desc: "enable group with invalid token", + domainID: domainID, token: invalidToken, groupID: group.ID, svcRes: groups.Group{}, @@ -1474,6 +1535,7 @@ func TestEnableGroup(t *testing.T) { }, { desc: "enable group with empty token", + domainID: domainID, token: "", groupID: group.ID, svcRes: groups.Group{}, @@ -1483,6 +1545,7 @@ func TestEnableGroup(t *testing.T) { }, { desc: "enable group with empty id", + domainID: domainID, token: validToken, groupID: "", svcRes: groups.Group{}, @@ -1491,9 +1554,10 @@ func TestEnableGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "enable group with service response that cannot be unmarshalled", - token: validToken, - groupID: group.ID, + desc: "enable group with service response that cannot be unmarshalled", + domainID: domainID, + token: validToken, + groupID: group.ID, svcRes: groups.Group{ ID: group.ID, Name: "group_1", @@ -1509,11 +1573,11 @@ func TestEnableGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("EnableGroup", mock.Anything, tc.session, tc.groupID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.EnableGroup(tc.groupID, tc.token) + resp, err := mgsdk.EnableGroup(tc.groupID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1540,6 +1604,7 @@ func TestDisableGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1551,6 +1616,7 @@ func TestDisableGroup(t *testing.T) { }{ { desc: "disable group successfully", + domainID: domainID, token: validToken, groupID: group.ID, svcRes: convertGroup(disGroup), @@ -1560,6 +1626,7 @@ func TestDisableGroup(t *testing.T) { }, { desc: "disable group with invalid group id", + domainID: domainID, token: validToken, groupID: wrongID, svcRes: groups.Group{}, @@ -1569,6 +1636,7 @@ func TestDisableGroup(t *testing.T) { }, { desc: "disable group with invalid token", + domainID: domainID, token: invalidToken, groupID: group.ID, svcRes: groups.Group{}, @@ -1578,6 +1646,7 @@ func TestDisableGroup(t *testing.T) { }, { desc: "disable group with empty token", + domainID: domainID, token: "", groupID: group.ID, svcRes: groups.Group{}, @@ -1587,6 +1656,7 @@ func TestDisableGroup(t *testing.T) { }, { desc: "disable group with empty id", + domainID: domainID, token: validToken, groupID: "", svcRes: groups.Group{}, @@ -1595,9 +1665,10 @@ func TestDisableGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "disable group with service response that cannot be unmarshalled", - token: validToken, - groupID: group.ID, + desc: "disable group with service response that cannot be unmarshalled", + domainID: domainID, + token: validToken, + groupID: group.ID, svcRes: groups.Group{ ID: group.ID, Name: "group_1", @@ -1613,11 +1684,11 @@ func TestDisableGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("DisableGroup", mock.Anything, tc.session, tc.groupID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.DisableGroup(tc.groupID, tc.token) + resp, err := mgsdk.DisableGroup(tc.groupID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1641,6 +1712,7 @@ func TestDeleteGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1649,49 +1721,54 @@ func TestDeleteGroup(t *testing.T) { err errors.SDKError }{ { - desc: "delete group successfully", - token: validToken, - groupID: group.ID, - svcErr: nil, - err: nil, + desc: "delete group successfully", + domainID: domainID, + token: validToken, + groupID: group.ID, + svcErr: nil, + err: nil, }, { - desc: "delete group with invalid group id", - token: validToken, - groupID: wrongID, - svcErr: svcerr.ErrRemoveEntity, - err: errors.NewSDKErrorWithStatus(svcerr.ErrRemoveEntity, http.StatusUnprocessableEntity), + desc: "delete group with invalid group id", + domainID: domainID, + token: validToken, + groupID: wrongID, + svcErr: svcerr.ErrRemoveEntity, + err: errors.NewSDKErrorWithStatus(svcerr.ErrRemoveEntity, http.StatusUnprocessableEntity), }, { desc: "delete group with invalid token", + domainID: domainID, token: invalidToken, groupID: group.ID, authenticateErr: svcerr.ErrAuthentication, err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "delete group with empty token", - token: "", - groupID: group.ID, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "delete group with empty token", + domainID: domainID, + token: "", + groupID: group.ID, + svcErr: nil, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "delete group with empty id", - token: validToken, - groupID: "", - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), + desc: "delete group with empty id", + domainID: domainID, + token: validToken, + groupID: "", + svcErr: nil, + err: errors.NewSDKError(apiutil.ErrMissingID), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("DeleteGroup", mock.Anything, tc.session, tc.groupID).Return(tc.svcErr) - err := mgsdk.DeleteGroup(tc.groupID, tc.token) + err := mgsdk.DeleteGroup(tc.groupID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "DeleteGroup", mock.Anything, tc.session, tc.groupID) @@ -1714,6 +1791,7 @@ func TestAddUserToGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1723,9 +1801,10 @@ func TestAddUserToGroup(t *testing.T) { err errors.SDKError }{ { - desc: "add user to group successfully", - token: validToken, - groupID: group.ID, + desc: "add user to group successfully", + domainID: domainID, + token: validToken, + groupID: group.ID, addUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1734,9 +1813,10 @@ func TestAddUserToGroup(t *testing.T) { err: nil, }, { - desc: "add user to group with invalid token", - token: invalidToken, - groupID: group.ID, + desc: "add user to group with invalid token", + domainID: domainID, + token: invalidToken, + groupID: group.ID, addUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1745,9 +1825,10 @@ func TestAddUserToGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "add user to group with empty token", - token: "", - groupID: group.ID, + desc: "add user to group with empty token", + domainID: domainID, + token: "", + groupID: group.ID, addUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1756,9 +1837,10 @@ func TestAddUserToGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "add user to group with invalid group id", - token: validToken, - groupID: wrongID, + desc: "add user to group with invalid group id", + domainID: domainID, + token: validToken, + groupID: wrongID, addUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1767,9 +1849,10 @@ func TestAddUserToGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "add user to group with empty group id", - token: validToken, - groupID: "", + desc: "add user to group with empty group id", + domainID: domainID, + token: validToken, + groupID: "", addUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1778,9 +1861,10 @@ func TestAddUserToGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "add users to group with empty relation", - token: validToken, - groupID: group.ID, + desc: "add users to group with empty relation", + domainID: domainID, + token: validToken, + groupID: group.ID, addUserReq: sdk.UsersRelationRequest{ Relation: "", UserIDs: []string{user.ID}, @@ -1789,9 +1873,10 @@ func TestAddUserToGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingRelation), http.StatusBadRequest), }, { - desc: "add users to group with empty user ids", - token: validToken, - groupID: group.ID, + desc: "add users to group with empty user ids", + domainID: domainID, + token: validToken, + groupID: group.ID, addUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{}, @@ -1803,11 +1888,11 @@ func TestAddUserToGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Assign", mock.Anything, tc.session, tc.groupID, tc.addUserReq.Relation, policies.UsersKind, tc.addUserReq.UserIDs).Return(tc.svcErr) - err := mgsdk.AddUserToGroup(tc.groupID, tc.addUserReq, tc.token) + err := mgsdk.AddUserToGroup(tc.groupID, tc.addUserReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Assign", mock.Anything, tc.session, tc.groupID, tc.addUserReq.Relation, policies.UsersKind, tc.addUserReq.UserIDs) @@ -1830,6 +1915,7 @@ func TestRemoveUserFromGroup(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session groupID string @@ -1839,9 +1925,10 @@ func TestRemoveUserFromGroup(t *testing.T) { err errors.SDKError }{ { - desc: "remove user from group successfully", - token: validToken, - groupID: group.ID, + desc: "remove user from group successfully", + domainID: domainID, + token: validToken, + groupID: group.ID, removeUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1850,9 +1937,10 @@ func TestRemoveUserFromGroup(t *testing.T) { err: nil, }, { - desc: "remove user from group with invalid token", - token: invalidToken, - groupID: group.ID, + desc: "remove user from group with invalid token", + domainID: domainID, + token: invalidToken, + groupID: group.ID, removeUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1861,9 +1949,10 @@ func TestRemoveUserFromGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "remove user from group with empty token", - token: "", - groupID: group.ID, + desc: "remove user from group with empty token", + domainID: domainID, + token: "", + groupID: group.ID, removeUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1872,9 +1961,10 @@ func TestRemoveUserFromGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "remove user from group with invalid group id", - token: validToken, - groupID: wrongID, + desc: "remove user from group with invalid group id", + domainID: domainID, + token: validToken, + groupID: wrongID, removeUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1883,9 +1973,10 @@ func TestRemoveUserFromGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "remove user from group with empty group id", - token: validToken, - groupID: "", + desc: "remove user from group with empty group id", + domainID: domainID, + token: validToken, + groupID: "", removeUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{user.ID}, @@ -1894,9 +1985,10 @@ func TestRemoveUserFromGroup(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "remove users from group with empty user ids", - token: validToken, - groupID: group.ID, + desc: "remove users from group with empty user ids", + domainID: domainID, + token: validToken, + groupID: group.ID, removeUserReq: sdk.UsersRelationRequest{ Relation: "member", UserIDs: []string{}, @@ -1908,11 +2000,11 @@ func TestRemoveUserFromGroup(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := gsvc.On("Unassign", mock.Anything, tc.session, tc.groupID, tc.removeUserReq.Relation, policies.UsersKind, tc.removeUserReq.UserIDs).Return(tc.svcErr) - err := mgsdk.RemoveUserFromGroup(tc.groupID, tc.removeUserReq, tc.token) + err := mgsdk.RemoveUserFromGroup(tc.groupID, tc.removeUserReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Unassign", mock.Anything, tc.session, tc.groupID, tc.removeUserReq.Relation, policies.UsersKind, tc.removeUserReq.UserIDs) diff --git a/pkg/sdk/go/invitations.go b/pkg/sdk/go/invitations.go index 97c42255f9..091bc57da7 100644 --- a/pkg/sdk/go/invitations.go +++ b/pkg/sdk/go/invitations.go @@ -5,6 +5,7 @@ package sdk import ( "encoding/json" + "fmt" "net/http" "time" @@ -43,7 +44,7 @@ func (sdk mgSDK) SendInvitation(invitation Invitation, token string) (err error) return errors.NewSDKError(err) } - url := sdk.invitationsURL + "/" + invitationsEndpoint + url := sdk.invitationsURL + "/" + invitation.DomainID + "/" + invitationsEndpoint _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) @@ -51,7 +52,7 @@ func (sdk mgSDK) SendInvitation(invitation Invitation, token string) (err error) } func (sdk mgSDK) Invitation(userID, domainID, token string) (invitation Invitation, err error) { - url := sdk.invitationsURL + "/" + invitationsEndpoint + "/" + userID + "/" + domainID + url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + usersEndpoint + "/" + userID _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if sdkerr != nil { @@ -66,7 +67,9 @@ func (sdk mgSDK) Invitation(userID, domainID, token string) (invitation Invitati } func (sdk mgSDK) Invitations(pm PageMetadata, token string) (invitations InvitationPage, err error) { - url, err := sdk.withQueryParams(sdk.invitationsURL, invitationsEndpoint, pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, invitationsEndpoint) + + url, err := sdk.withQueryParams(sdk.invitationsURL, endpoint, pm) if err != nil { return InvitationPage{}, errors.NewSDKError(err) } @@ -85,43 +88,23 @@ func (sdk mgSDK) Invitations(pm PageMetadata, token string) (invitations Invitat } func (sdk mgSDK) AcceptInvitation(domainID, token string) (err error) { - req := struct { - DomainID string `json:"domain_id"` - }{ - DomainID: domainID, - } - data, err := json.Marshal(req) - if err != nil { - return errors.NewSDKError(err) - } - - url := sdk.invitationsURL + "/" + invitationsEndpoint + "/" + acceptEndpoint + url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + acceptEndpoint - _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) + _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) RejectInvitation(domainID, token string) (err error) { - req := struct { - DomainID string `json:"domain_id"` - }{ - DomainID: domainID, - } - data, err := json.Marshal(req) - if err != nil { - return errors.NewSDKError(err) - } - - url := sdk.invitationsURL + "/" + invitationsEndpoint + "/" + rejectEndpoint + url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + rejectEndpoint - _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) + _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) DeleteInvitation(userID, domainID, token string) (err error) { - url := sdk.invitationsURL + "/" + invitationsEndpoint + "/" + userID + "/" + domainID + url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + usersEndpoint + "/" + userID _, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent) diff --git a/pkg/sdk/go/invitations_test.go b/pkg/sdk/go/invitations_test.go index b4a12db12b..f688f47c14 100644 --- a/pkg/sdk/go/invitations_test.go +++ b/pkg/sdk/go/invitations_test.go @@ -205,16 +205,6 @@ func TestViewInvitation(t *testing.T) { response: sdk.Invitation{}, err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, - { - desc: "view invitation with empty userID", - token: validToken, - userID: "", - domainID: invitation.DomainID, - svcRes: invitations.Invitation{}, - svcErr: nil, - response: sdk.Invitation{}, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), - }, { desc: "view invitation with invalid domainID", token: validToken, @@ -229,7 +219,7 @@ func TestViewInvitation(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == valid { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ViewInvitation", mock.Anything, tc.session, tc.userID, tc.domainID).Return(tc.svcRes, tc.svcErr) @@ -271,12 +261,14 @@ func TestListInvitation(t *testing.T) { desc: "list invitations successfully", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: invitations.Page{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcRes: invitations.InvitationPage{ Total: 1, @@ -293,8 +285,9 @@ func TestListInvitation(t *testing.T) { desc: "list invitations with invalid token", token: invalidToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: invitations.Page{ Offset: 0, @@ -306,20 +299,32 @@ func TestListInvitation(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), }, { - desc: "list invitations with empty token", - token: "", - pageMeta: sdk.PageMetadata{}, + desc: "list invitations with empty token", + token: "", + pageMeta: sdk.PageMetadata{ + DomainID: domainID, + }, svcRes: invitations.InvitationPage{}, svcErr: nil, response: sdk.InvitationPage{}, err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, + { + desc: "list invitations with empty domainID", + token: validToken, + pageMeta: sdk.PageMetadata{}, + svcRes: invitations.InvitationPage{}, + svcErr: nil, + response: sdk.InvitationPage{}, + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingDomainID), http.StatusBadRequest), + }, { desc: "list invitations with limit greater than max limit", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 101, + Offset: 0, + Limit: 101, + DomainID: domainID, }, svcReq: invitations.Page{}, svcRes: invitations.InvitationPage{}, @@ -523,14 +528,6 @@ func TestDeleteInvitation(t *testing.T) { svcErr: nil, err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, - { - desc: "delete invitation with empty userID", - token: validToken, - userID: "", - domainID: invitation.DomainID, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), - }, { desc: "delete invitation with invalid domainID", token: validToken, diff --git a/pkg/sdk/go/sdk.go b/pkg/sdk/go/sdk.go index 267b122b99..7a8e234870 100644 --- a/pkg/sdk/go/sdk.go +++ b/pkg/sdk/go/sdk.go @@ -175,6 +175,7 @@ type SDK interface { // pm := sdk.PageMetadata{ // Offset: 0, // Limit: 10, + // DomainID: "domainID" // } // members, _ := sdk.Members("groupID", pm, "token") // fmt.Println(members) @@ -353,13 +354,13 @@ type SDK interface { // example: // thing := sdk.Thing{ // Name: "My Thing", - // Metadata: sdk.Metadata{ + // Metadata: sdk.Metadata{"domain_1" // "key": "value", // }, // } - // thing, _ := sdk.CreateThing(thing, "token") + // thing, _ := sdk.CreateThing(thing, "domainID", "token") // fmt.Println(thing) - CreateThing(thing Thing, token string) (Thing, errors.SDKError) + CreateThing(thing Thing, domainID, token string) (Thing, errors.SDKError) // CreateThings registers new things and returns their ids. // @@ -378,9 +379,9 @@ type SDK interface { // }, // }, // } - // things, _ := sdk.CreateThings(things, "token") + // things, _ := sdk.CreateThings(things, "domainID", "token") // fmt.Println(things) - CreateThings(things []Thing, token string) ([]Thing, errors.SDKError) + CreateThings(things []Thing, domainID, token string) ([]Thing, errors.SDKError) // Filters things and returns a page result. // @@ -409,16 +410,16 @@ type SDK interface { // Thing returns thing object by id. // // example: - // thing, _ := sdk.Thing("thingID", "token") + // thing, _ := sdk.Thing("thingID", "domainID", "token") // fmt.Println(thing) - Thing(id, token string) (Thing, errors.SDKError) + Thing(id, domainID, token string) (Thing, errors.SDKError) // ThingPermissions returns user permissions on the thing id. // // example: - // thing, _ := sdk.Thing("thingID", "token") + // thing, _ := sdk.Thing("thingID", "domainID", "token") // fmt.Println(thing) - ThingPermissions(id, token string) (Thing, errors.SDKError) + ThingPermissions(id, domainID, token string) (Thing, errors.SDKError) // UpdateThing updates existing thing. // @@ -430,9 +431,9 @@ type SDK interface { // "key": "value", // }, // } - // thing, _ := sdk.UpdateThing(thing, "token") + // thing, _ := sdk.UpdateThing(thing, "domainID", "token") // fmt.Println(thing) - UpdateThing(thing Thing, token string) (Thing, errors.SDKError) + UpdateThing(thing Thing, domainID, token string) (Thing, errors.SDKError) // UpdateThingTags updates the client's tags. // @@ -441,30 +442,30 @@ type SDK interface { // ID: "thingID", // Tags: []string{"tag1", "tag2"}, // } - // thing, _ := sdk.UpdateThingTags(thing, "token") + // thing, _ := sdk.UpdateThingTags(thing, "domainID", "token") // fmt.Println(thing) - UpdateThingTags(thing Thing, token string) (Thing, errors.SDKError) + UpdateThingTags(thing Thing, domainID, token string) (Thing, errors.SDKError) // UpdateThingSecret updates the client's secret // // example: - // thing, err := sdk.UpdateThingSecret("thingID", "newSecret", "token") + // thing, err := sdk.UpdateThingSecret("thingID", "newSecret", "domainID," "token") // fmt.Println(thing) - UpdateThingSecret(id, secret, token string) (Thing, errors.SDKError) + UpdateThingSecret(id, secret, domainID, token string) (Thing, errors.SDKError) // EnableThing changes client status to enabled. // // example: - // thing, _ := sdk.EnableThing("thingID", "token") + // thing, _ := sdk.EnableThing("thingID", "domainID", "token") // fmt.Println(thing) - EnableThing(id, token string) (Thing, errors.SDKError) + EnableThing(id, domainID, token string) (Thing, errors.SDKError) // DisableThing changes client status to disabled - soft delete. // // example: - // thing, _ := sdk.DisableThing("thingID", "token") + // thing, _ := sdk.DisableThing("thingID", "domainID", "token") // fmt.Println(thing) - DisableThing(id, token string) (Thing, errors.SDKError) + DisableThing(id, domainID, token string) (Thing, errors.SDKError) // ShareThing shares thing with other users. // @@ -473,9 +474,9 @@ type SDK interface { // Relation: "contributor", // available options: "owner", "admin", "editor", "contributor", "guest" // UserIDs: ["user_id_1", "user_id_2", "user_id_3"] // } - // err := sdk.ShareThing("thing_id", req, "token") + // err := sdk.ShareThing("thing_id", req, "domainID","token") // fmt.Println(err) - ShareThing(thingID string, req UsersRelationRequest, token string) errors.SDKError + ShareThing(thingID string, req UsersRelationRequest, domainID, token string) errors.SDKError // UnshareThing unshare a thing with other users. // @@ -484,9 +485,9 @@ type SDK interface { // Relation: "contributor", // available options: "owner", "admin", "editor", "contributor", "guest" // UserIDs: ["user_id_1", "user_id_2", "user_id_3"] // } - // err := sdk.UnshareThing("thing_id", req, "token") + // err := sdk.UnshareThing("thing_id", req, "domainID", "token") // fmt.Println(err) - UnshareThing(thingID string, req UsersRelationRequest, token string) errors.SDKError + UnshareThing(thingID string, req UsersRelationRequest, domainID, token string) errors.SDKError // ListThingUsers all users in a thing. // @@ -503,9 +504,9 @@ type SDK interface { // DeleteThing deletes a thing with the given id. // // example: - // err := sdk.DeleteThing("thingID", "token") + // err := sdk.DeleteThing("thingID", "domainID", "token") // fmt.Println(err) - DeleteThing(id, token string) errors.SDKError + DeleteThing(id, domainID, token string) errors.SDKError // CreateGroup creates new group and returns its id. // @@ -516,9 +517,9 @@ type SDK interface { // "key": "value", // }, // } - // group, _ := sdk.CreateGroup(group, "token") + // group, _ := sdk.CreateGroup(group, "domainID", "token") // fmt.Println(group) - CreateGroup(group Group, token string) (Group, errors.SDKError) + CreateGroup(group Group, domainID, token string) (Group, errors.SDKError) // Groups returns page of groups. // @@ -559,16 +560,16 @@ type SDK interface { // Group returns users group object by id. // // example: - // group, _ := sdk.Group("groupID", "token") + // group, _ := sdk.Group("groupID", "domainID", "token") // fmt.Println(group) - Group(id, token string) (Group, errors.SDKError) + Group(id, domainID, token string) (Group, errors.SDKError) // GroupPermissions returns user permissions by group ID. // // example: - // group, _ := sdk.Group("groupID", "token") + // group, _ := sdk.Group("groupID", "domainID" "token") // fmt.Println(group) - GroupPermissions(id, token string) (Group, errors.SDKError) + GroupPermissions(id, domainID, token string) (Group, errors.SDKError) // UpdateGroup updates existing group. // @@ -580,23 +581,23 @@ type SDK interface { // "key": "value", // }, // } - // group, _ := sdk.UpdateGroup(group, "token") + // group, _ := sdk.UpdateGroup(group, "domainID", "token") // fmt.Println(group) - UpdateGroup(group Group, token string) (Group, errors.SDKError) + UpdateGroup(group Group, domainID, token string) (Group, errors.SDKError) // EnableGroup changes group status to enabled. // // example: - // group, _ := sdk.EnableGroup("groupID", "token") + // group, _ := sdk.EnableGroup("groupID", "domainID", "token") // fmt.Println(group) - EnableGroup(id, token string) (Group, errors.SDKError) + EnableGroup(id, domainID, token string) (Group, errors.SDKError) // DisableGroup changes group status to disabled - soft delete. // // example: - // group, _ := sdk.DisableGroup("groupID", "token") + // group, _ := sdk.DisableGroup("groupID", "domainID", "token") // fmt.Println(group) - DisableGroup(id, token string) (Group, errors.SDKError) + DisableGroup(id, domainID, token string) (Group, errors.SDKError) // AddUserToGroup add user to a group. // @@ -605,9 +606,9 @@ type SDK interface { // Relation: "contributor", // available options: "owner", "admin", "editor", "contributor", "guest" // UserIDs: ["user_id_1", "user_id_2", "user_id_3"] // } - // err := sdk.AddUserToGroup("groupID",req, "token") + // err := sdk.AddUserToGroup("groupID",req, "domainID", "token") // fmt.Println(err) - AddUserToGroup(groupID string, req UsersRelationRequest, token string) errors.SDKError + AddUserToGroup(groupID string, req UsersRelationRequest, domainID, token string) errors.SDKError // RemoveUserFromGroup remove user from a group. // @@ -616,9 +617,9 @@ type SDK interface { // Relation: "contributor", // available options: "owner", "admin", "editor", "contributor", "guest" // UserIDs: ["user_id_1", "user_id_2", "user_id_3"] // } - // err := sdk.RemoveUserFromGroup("groupID",req, "token") + // err := sdk.RemoveUserFromGroup("groupID",req, "domainID", "token") // fmt.Println(err) - RemoveUserFromGroup(groupID string, req UsersRelationRequest, token string) errors.SDKError + RemoveUserFromGroup(groupID string, req UsersRelationRequest, domainID, token string) errors.SDKError // ListGroupUsers list all users in the group id . // @@ -638,6 +639,7 @@ type SDK interface { // pm := sdk.PageMetadata{ // Offset: 0, // Limit: 10, + // DomainID: "domain" // Permission: "edit", // available Options: "administrator", "administrator", "delete", edit", "view", "share", "owner", "owner", "admin", "editor", "contributor", "editor", "viewer", "guest", "create" // } // groups, _ := sdk.ListGroupChannels("groupID", pm, "token") @@ -647,9 +649,9 @@ type SDK interface { // DeleteGroup delete given group id. // // example: - // err := sdk.DeleteGroup("groupID", "token") + // err := sdk.DeleteGroup("groupID", "domainID", "token") // fmt.Println(err) - DeleteGroup(id, token string) errors.SDKError + DeleteGroup(id, domainID, token string) errors.SDKError // CreateChannel creates new channel and returns its id. // @@ -660,9 +662,9 @@ type SDK interface { // "key": "value", // }, // } - // channel, _ := sdk.CreateChannel(channel, "token") + // channel, _ := sdk.CreateChannel(channel, "domainID", "token") // fmt.Println(channel) - CreateChannel(channel Channel, token string) (Channel, errors.SDKError) + CreateChannel(channel Channel, domainID, token string) (Channel, errors.SDKError) // Channels returns page of channels. // @@ -671,6 +673,7 @@ type SDK interface { // Offset: 0, // Limit: 10, // Name: "My Channel", + // Domain: "domainID" // } // channels, _ := sdk.Channels(pm, "token") // fmt.Println(channels) @@ -684,23 +687,23 @@ type SDK interface { // Limit: 10, // Name: "My Channel", // } - // channels, _ := sdk.ChannelsByThing("thingID", pm, "token") + // channels, _ := sdk.ChannelsByThing("thingID", pm, "domainID" "token") // fmt.Println(channels) - ChannelsByThing(thingID string, pm PageMetadata, token string) (ChannelsPage, errors.SDKError) + ChannelsByThing(thingID string, pm PageMetadata, domainID, token string) (ChannelsPage, errors.SDKError) // Channel returns channel data by id. // // example: - // channel, _ := sdk.Channel("channelID", "token") + // channel, _ := sdk.Channel("channelID", "domainID", "token") // fmt.Println(channel) - Channel(id, token string) (Channel, errors.SDKError) + Channel(id, domainID, token string) (Channel, errors.SDKError) // ChannelPermissions returns user permissions on the channel ID. // // example: - // channel, _ := sdk.Channel("channelID", "token") + // channel, _ := sdk.Channel("channelID", "domainID", "token") // fmt.Println(channel) - ChannelPermissions(id, token string) (Channel, errors.SDKError) + ChannelPermissions(id, domainID, token string) (Channel, errors.SDKError) // UpdateChannel updates existing channel. // @@ -712,23 +715,23 @@ type SDK interface { // "key": "value", // }, // } - // channel, _ := sdk.UpdateChannel(channel, "token") + // channel, _ := sdk.UpdateChannel(channel, "domainID", "token") // fmt.Println(channel) - UpdateChannel(channel Channel, token string) (Channel, errors.SDKError) + UpdateChannel(channel Channel, domainID, token string) (Channel, errors.SDKError) // EnableChannel changes channel status to enabled. // // example: - // channel, _ := sdk.EnableChannel("channelID", "token") + // channel, _ := sdk.EnableChannel("channelID", "domainID", "token") // fmt.Println(channel) - EnableChannel(id, token string) (Channel, errors.SDKError) + EnableChannel(id, domainID, token string) (Channel, errors.SDKError) // DisableChannel changes channel status to disabled - soft delete. // // example: - // channel, _ := sdk.DisableChannel("channelID", "token") + // channel, _ := sdk.DisableChannel("channelID", "domainID", "token") // fmt.Println(channel) - DisableChannel(id, token string) (Channel, errors.SDKError) + DisableChannel(id, domainID, token string) (Channel, errors.SDKError) // AddUserToChannel add user to a channel. // @@ -737,9 +740,9 @@ type SDK interface { // Relation: "contributor", // available options: "owner", "admin", "editor", "contributor", "guest" // UserIDs: ["user_id_1", "user_id_2", "user_id_3"] // } - // err := sdk.AddUserToChannel("channel_id", req, "token") + // err := sdk.AddUserToChannel("channel_id", req, "domainID", "token") // fmt.Println(err) - AddUserToChannel(channelID string, req UsersRelationRequest, token string) errors.SDKError + AddUserToChannel(channelID string, req UsersRelationRequest, domainID, token string) errors.SDKError // RemoveUserFromChannel remove user from a group. // @@ -748,9 +751,9 @@ type SDK interface { // Relation: "contributor", // available options: "owner", "admin", "editor", "contributor", "guest" // UserIDs: ["user_id_1", "user_id_2", "user_id_3"] // } - // err := sdk.RemoveUserFromChannel("channel_id", req, "token") + // err := sdk.RemoveUserFromChannel("channel_id", req, "domainID", "token") // fmt.Println(err) - RemoveUserFromChannel(channelID string, req UsersRelationRequest, token string) errors.SDKError + RemoveUserFromChannel(channelID string, req UsersRelationRequest, domainID, token string) errors.SDKError // ListChannelUsers list all users in a channel . // @@ -770,9 +773,9 @@ type SDK interface { // req := sdk.UserGroupsRequest{ // GroupsIDs: ["group_id_1", "group_id_2", "group_id_3"] // } - // err := sdk.AddUserGroupToChannel("channel_id",req, "token") + // err := sdk.AddUserGroupToChannel("channel_id",req, "domainID", "token") // fmt.Println(err) - AddUserGroupToChannel(channelID string, req UserGroupsRequest, token string) errors.SDKError + AddUserGroupToChannel(channelID string, req UserGroupsRequest, domainID, token string) errors.SDKError // RemoveUserGroupFromChannel remove user group from a channel. // @@ -780,9 +783,9 @@ type SDK interface { // req := sdk.UserGroupsRequest{ // GroupsIDs: ["group_id_1", "group_id_2", "group_id_3"] // } - // err := sdk.RemoveUserGroupFromChannel("channel_id",req, "token") + // err := sdk.RemoveUserGroupFromChannel("channel_id",req, "domainID", "token") // fmt.Println(err) - RemoveUserGroupFromChannel(channelID string, req UserGroupsRequest, token string) errors.SDKError + RemoveUserGroupFromChannel(channelID string, req UserGroupsRequest, domainID, token string) errors.SDKError // ListChannelUserGroups list all user groups in a channel. // @@ -799,9 +802,9 @@ type SDK interface { // DeleteChannel delete given group id. // // example: - // err := sdk.DeleteChannel("channelID", "token") + // err := sdk.DeleteChannel("channelID", "domainID", "token") // fmt.Println(err) - DeleteChannel(id, token string) errors.SDKError + DeleteChannel(id, domainID, token string) errors.SDKError // Connect bulk connects things to channels specified by id. // @@ -810,9 +813,9 @@ type SDK interface { // ChannelID: "channel_id_1", // ThingID: "thing_id_1", // } - // err := sdk.Connect(conns, "token") + // err := sdk.Connect(conns, "domainID", "token") // fmt.Println(err) - Connect(conns Connection, token string) errors.SDKError + Connect(conns Connection, domainID, token string) errors.SDKError // Disconnect // @@ -821,9 +824,9 @@ type SDK interface { // ChannelID: "channel_id_1", // ThingID: "thing_id_1", // } - // err := sdk.Disconnect(conns, "token") + // err := sdk.Disconnect(conns, "domainID", "token") // fmt.Println(err) - Disconnect(connIDs Connection, token string) errors.SDKError + Disconnect(connIDs Connection, domainID, token string) errors.SDKError // ConnectThing connects thing to specified channel by id. // @@ -832,7 +835,7 @@ type SDK interface { // example: // err := sdk.ConnectThing("thingID", "channelID", "token") // fmt.Println(err) - ConnectThing(thingID, chanID, token string) errors.SDKError + ConnectThing(thingID, chanID, domainID, token string) errors.SDKError // DisconnectThing disconnect thing from specified channel by id. // @@ -841,7 +844,7 @@ type SDK interface { // example: // err := sdk.DisconnectThing("thingID", "channelID", "token") // fmt.Println(err) - DisconnectThing(thingID, chanID, token string) errors.SDKError + DisconnectThing(thingID, chanID, domainID, token string) errors.SDKError // SendMessage send message to specified channel. // @@ -886,16 +889,16 @@ type SDK interface { // ExternalKey: "externalKey", // Channels: []string{"channel1", "channel2"}, // } - // id, _ := sdk.AddBootstrap(cfg, "token") + // id, _ := sdk.AddBootstrap(cfg, "domainID", "token") // fmt.Println(id) - AddBootstrap(cfg BootstrapConfig, token string) (string, errors.SDKError) + AddBootstrap(cfg BootstrapConfig, domainID, token string) (string, errors.SDKError) // View returns Thing Config with given ID belonging to the user identified by the given token. // // example: - // bootstrap, _ := sdk.ViewBootstrap("id", "token") + // bootstrap, _ := sdk.ViewBootstrap("id", "domainID", "token") // fmt.Println(bootstrap) - ViewBootstrap(id, token string) (BootstrapConfig, errors.SDKError) + ViewBootstrap(id, domainID, token string) (BootstrapConfig, errors.SDKError) // Update updates editable fields of the provided Config. // @@ -907,30 +910,30 @@ type SDK interface { // ExternalKey: "externalKey", // Channels: []string{"channel1", "channel2"}, // } - // err := sdk.UpdateBootstrap(cfg, "token") + // err := sdk.UpdateBootstrap(cfg, "domainID", "token") // fmt.Println(err) - UpdateBootstrap(cfg BootstrapConfig, token string) errors.SDKError + UpdateBootstrap(cfg BootstrapConfig, domainID, token string) errors.SDKError // Update bootstrap config certificates. // // example: - // err := sdk.UpdateBootstrapCerts("id", "clientCert", "clientKey", "ca", "token") + // err := sdk.UpdateBootstrapCerts("id", "clientCert", "clientKey", "ca", "domainID", "token") // fmt.Println(err) - UpdateBootstrapCerts(id string, clientCert, clientKey, ca string, token string) (BootstrapConfig, errors.SDKError) + UpdateBootstrapCerts(id string, clientCert, clientKey, ca string, domainID, token string) (BootstrapConfig, errors.SDKError) // UpdateBootstrapConnection updates connections performs update of the channel list corresponding Thing is connected to. // // example: - // err := sdk.UpdateBootstrapConnection("id", []string{"channel1", "channel2"}, "token") + // err := sdk.UpdateBootstrapConnection("id", []string{"channel1", "channel2"}, "domainID", "token") // fmt.Println(err) - UpdateBootstrapConnection(id string, channels []string, token string) errors.SDKError + UpdateBootstrapConnection(id string, channels []string, domainID, token string) errors.SDKError // Remove removes Config with specified token that belongs to the user identified by the given token. // // example: - // err := sdk.RemoveBootstrap("id", "token") + // err := sdk.RemoveBootstrap("id", "domainID", "token") // fmt.Println(err) - RemoveBootstrap(id, token string) errors.SDKError + RemoveBootstrap(id, domainID, token string) errors.SDKError // Bootstrap returns Config to the Thing with provided external ID using external key. // @@ -960,37 +963,37 @@ type SDK interface { // Whitelist updates Thing state Config with given ID belonging to the user identified by the given token. // // example: - // err := sdk.Whitelist("thingID", 1, "token") + // err := sdk.Whitelist("thingID", 1, "domainID", "token") // fmt.Println(err) - Whitelist(thingID string, state int, token string) errors.SDKError + Whitelist(thingID string, state int, domainID, token string) errors.SDKError // IssueCert issues a certificate for a thing required for mTLS. // // example: - // cert, _ := sdk.IssueCert("thingID", "24h", "token") + // cert, _ := sdk.IssueCert("thingID", "24h", "domainID", "token") // fmt.Println(cert) - IssueCert(thingID, validity, token string) (Cert, errors.SDKError) + IssueCert(thingID, validity, domainID, token string) (Cert, errors.SDKError) // ViewCert returns a certificate given certificate ID // // example: - // cert, _ := sdk.ViewCert("certID", "token") + // cert, _ := sdk.ViewCert("certID", "domainID", "token") // fmt.Println(cert) - ViewCert(certID, token string) (Cert, errors.SDKError) + ViewCert(certID, domainID, token string) (Cert, errors.SDKError) // ViewCertByThing retrieves a list of certificates' serial IDs for a given thing ID. // // example: - // cserial, _ := sdk.ViewCertByThing("thingID", "token") + // cserial, _ := sdk.ViewCertByThing("thingID", "domainID", "token") // fmt.Println(cserial) - ViewCertByThing(thingID, token string) (CertSerials, errors.SDKError) + ViewCertByThing(thingID, domainID, token string) (CertSerials, errors.SDKError) // RevokeCert revokes certificate for thing with thingID // // example: - // tm, _ := sdk.RevokeCert("thingID", "token") + // tm, _ := sdk.RevokeCert("thingID", "domainID", "token") // fmt.Println(tm) - RevokeCert(thingID, token string) (time.Time, errors.SDKError) + RevokeCert(thingID, domainID, token string) (time.Time, errors.SDKError) // CreateSubscription creates a new subscription // diff --git a/pkg/sdk/go/setup_test.go b/pkg/sdk/go/setup_test.go index 55a85a7dde..013ba5f9f2 100644 --- a/pkg/sdk/go/setup_test.go +++ b/pkg/sdk/go/setup_test.go @@ -24,7 +24,6 @@ const ( invalidIdentity = "invalididentity" Identity = "identity" secret = "strongsecret" - token = "token" invalidToken = "invalid" contentType = "application/senml+json" invalid = "invalid" diff --git a/pkg/sdk/go/things.go b/pkg/sdk/go/things.go index 8b598898bd..2973ae3731 100644 --- a/pkg/sdk/go/things.go +++ b/pkg/sdk/go/things.go @@ -37,13 +37,13 @@ type Thing struct { Permissions []string `json:"permissions,omitempty"` } -func (sdk mgSDK) CreateThing(thing Thing, token string) (Thing, errors.SDKError) { +func (sdk mgSDK) CreateThing(thing Thing, domainID, token string) (Thing, errors.SDKError) { data, err := json.Marshal(thing) if err != nil { return Thing{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s", sdk.thingsURL, thingsEndpoint) + url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint) _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) if sdkerr != nil { @@ -58,13 +58,13 @@ func (sdk mgSDK) CreateThing(thing Thing, token string) (Thing, errors.SDKError) return thing, nil } -func (sdk mgSDK) CreateThings(things []Thing, token string) ([]Thing, errors.SDKError) { +func (sdk mgSDK) CreateThings(things []Thing, domainID, token string) ([]Thing, errors.SDKError) { data, err := json.Marshal(things) if err != nil { return []Thing{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, thingsEndpoint, "bulk") + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, "bulk") _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK) if sdkerr != nil { @@ -80,7 +80,8 @@ func (sdk mgSDK) CreateThings(things []Thing, token string) ([]Thing, errors.SDK } func (sdk mgSDK) Things(pm PageMetadata, token string) (ThingsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.thingsURL, thingsEndpoint, pm) + endpoint := fmt.Sprintf("%s/%s", pm.DomainID, thingsEndpoint) + url, err := sdk.withQueryParams(sdk.thingsURL, endpoint, pm) if err != nil { return ThingsPage{}, errors.NewSDKError(err) } @@ -99,7 +100,7 @@ func (sdk mgSDK) Things(pm PageMetadata, token string) (ThingsPage, errors.SDKEr } func (sdk mgSDK) ThingsByChannel(chanID string, pm PageMetadata, token string) (ThingsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("channels/%s/%s", chanID, thingsEndpoint), pm) + url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/channels/%s/%s", pm.DomainID, chanID, thingsEndpoint), pm) if err != nil { return ThingsPage{}, errors.NewSDKError(err) } @@ -117,11 +118,11 @@ func (sdk mgSDK) ThingsByChannel(chanID string, pm PageMetadata, token string) ( return tp, nil } -func (sdk mgSDK) Thing(id, token string) (Thing, errors.SDKError) { +func (sdk mgSDK) Thing(id, domainID, token string) (Thing, errors.SDKError) { if id == "" { return Thing{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, thingsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, id) _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if sdkerr != nil { @@ -136,8 +137,8 @@ func (sdk mgSDK) Thing(id, token string) (Thing, errors.SDKError) { return t, nil } -func (sdk mgSDK) ThingPermissions(id, token string) (Thing, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, thingsEndpoint, id, permissionsEndpoint) +func (sdk mgSDK) ThingPermissions(id, domainID, token string) (Thing, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, id, permissionsEndpoint) _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if sdkerr != nil { @@ -152,11 +153,11 @@ func (sdk mgSDK) ThingPermissions(id, token string) (Thing, errors.SDKError) { return t, nil } -func (sdk mgSDK) UpdateThing(t Thing, token string) (Thing, errors.SDKError) { +func (sdk mgSDK) UpdateThing(t Thing, domainID, token string) (Thing, errors.SDKError) { if t.ID == "" { return Thing{}, errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, thingsEndpoint, t.ID) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, t.ID) data, err := json.Marshal(t) if err != nil { @@ -176,13 +177,13 @@ func (sdk mgSDK) UpdateThing(t Thing, token string) (Thing, errors.SDKError) { return t, nil } -func (sdk mgSDK) UpdateThingTags(t Thing, token string) (Thing, errors.SDKError) { +func (sdk mgSDK) UpdateThingTags(t Thing, domainID, token string) (Thing, errors.SDKError) { data, err := json.Marshal(t) if err != nil { return Thing{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/tags", sdk.thingsURL, thingsEndpoint, t.ID) + url := fmt.Sprintf("%s/%s/%s/%s/tags", sdk.thingsURL, domainID, thingsEndpoint, t.ID) _, body, sdkerr := sdk.processRequest(http.MethodPatch, url, token, data, nil, http.StatusOK) if sdkerr != nil { @@ -197,7 +198,7 @@ func (sdk mgSDK) UpdateThingTags(t Thing, token string) (Thing, errors.SDKError) return t, nil } -func (sdk mgSDK) UpdateThingSecret(id, secret, token string) (Thing, errors.SDKError) { +func (sdk mgSDK) UpdateThingSecret(id, secret, domainID, token string) (Thing, errors.SDKError) { ucsr := updateThingSecretReq{Secret: secret} data, err := json.Marshal(ucsr) @@ -205,7 +206,7 @@ func (sdk mgSDK) UpdateThingSecret(id, secret, token string) (Thing, errors.SDKE return Thing{}, errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/secret", sdk.thingsURL, thingsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s/secret", sdk.thingsURL, domainID, thingsEndpoint, id) _, body, sdkerr := sdk.processRequest(http.MethodPatch, url, token, data, nil, http.StatusOK) if sdkerr != nil { @@ -220,16 +221,16 @@ func (sdk mgSDK) UpdateThingSecret(id, secret, token string) (Thing, errors.SDKE return t, nil } -func (sdk mgSDK) EnableThing(id, token string) (Thing, errors.SDKError) { - return sdk.changeThingStatus(id, enableEndpoint, token) +func (sdk mgSDK) EnableThing(id, domainID, token string) (Thing, errors.SDKError) { + return sdk.changeThingStatus(id, enableEndpoint, domainID, token) } -func (sdk mgSDK) DisableThing(id, token string) (Thing, errors.SDKError) { - return sdk.changeThingStatus(id, disableEndpoint, token) +func (sdk mgSDK) DisableThing(id, domainID, token string) (Thing, errors.SDKError) { + return sdk.changeThingStatus(id, disableEndpoint, domainID, token) } -func (sdk mgSDK) changeThingStatus(id, status, token string) (Thing, errors.SDKError) { - url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, thingsEndpoint, id, status) +func (sdk mgSDK) changeThingStatus(id, status, domainID, token string) (Thing, errors.SDKError) { + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, id, status) _, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusOK) if sdkerr != nil { @@ -244,32 +245,32 @@ func (sdk mgSDK) changeThingStatus(id, status, token string) (Thing, errors.SDKE return t, nil } -func (sdk mgSDK) ShareThing(thingID string, req UsersRelationRequest, token string) errors.SDKError { +func (sdk mgSDK) ShareThing(thingID string, req UsersRelationRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, thingsEndpoint, thingID, shareEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, thingID, shareEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) return sdkerr } -func (sdk mgSDK) UnshareThing(thingID string, req UsersRelationRequest, token string) errors.SDKError { +func (sdk mgSDK) UnshareThing(thingID string, req UsersRelationRequest, domainID, token string) errors.SDKError { data, err := json.Marshal(req) if err != nil { return errors.NewSDKError(err) } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, thingsEndpoint, thingID, unshareEndpoint) + url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, thingID, unshareEndpoint) _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) ListThingUsers(thingID string, pm PageMetadata, token string) (UsersPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", thingsEndpoint, thingID, usersEndpoint), pm) + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, thingsEndpoint, thingID, usersEndpoint), pm) if err != nil { return UsersPage{}, errors.NewSDKError(err) } @@ -286,11 +287,11 @@ func (sdk mgSDK) ListThingUsers(thingID string, pm PageMetadata, token string) ( return up, nil } -func (sdk mgSDK) DeleteThing(id, token string) errors.SDKError { +func (sdk mgSDK) DeleteThing(id, domainID, token string) errors.SDKError { if id == "" { return errors.NewSDKError(apiutil.ErrMissingID) } - url := fmt.Sprintf("%s/%s/%s", sdk.thingsURL, thingsEndpoint, id) + url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, domainID, thingsEndpoint, id) _, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent) return sdkerr } diff --git a/pkg/sdk/go/things_test.go b/pkg/sdk/go/things_test.go index aff4413974..1d17fa30f4 100644 --- a/pkg/sdk/go/things_test.go +++ b/pkg/sdk/go/things_test.go @@ -62,6 +62,7 @@ func TestCreateThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session createThingReq sdk.Thing @@ -74,6 +75,7 @@ func TestCreateThing(t *testing.T) { }{ { desc: "create new thing successfully", + domainID: domainID, token: validToken, createThingReq: createThingReq, svcReq: convertThing(createThingReq), @@ -84,6 +86,7 @@ func TestCreateThing(t *testing.T) { }, { desc: "create new thing with invalid token", + domainID: domainID, token: invalidToken, createThingReq: createThingReq, svcReq: convertThing(createThingReq), @@ -94,6 +97,7 @@ func TestCreateThing(t *testing.T) { }, { desc: "create new thing with empty token", + domainID: domainID, token: "", createThingReq: createThingReq, svcReq: convertThing(createThingReq), @@ -104,6 +108,7 @@ func TestCreateThing(t *testing.T) { }, { desc: "create an existing thing", + domainID: domainID, token: validToken, createThingReq: createThingReq, svcReq: convertThing(createThingReq), @@ -113,8 +118,9 @@ func TestCreateThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity), }, { - desc: "create a thing with name too long", - token: validToken, + desc: "create a thing with name too long", + domainID: domainID, + token: validToken, createThingReq: sdk.Thing{ Name: strings.Repeat("a", 1025), Tags: thing.Tags, @@ -129,8 +135,9 @@ func TestCreateThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrNameSize), http.StatusBadRequest), }, { - desc: "create a thing with invalid id", - token: validToken, + desc: "create a thing with invalid id", + domainID: domainID, + token: validToken, createThingReq: sdk.Thing{ ID: "123456789", Name: thing.Name, @@ -146,8 +153,9 @@ func TestCreateThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrInvalidIDFormat), http.StatusBadRequest), }, { - desc: "create a thing with a request that can't be marshalled", - token: validToken, + desc: "create a thing with a request that can't be marshalled", + domainID: domainID, + token: validToken, createThingReq: sdk.Thing{ Name: "test", Metadata: map[string]interface{}{ @@ -162,6 +170,7 @@ func TestCreateThing(t *testing.T) { }, { desc: "create a thing with a response that can't be unmarshalled", + domainID: domainID, token: validToken, createThingReq: createThingReq, svcReq: convertThing(createThingReq), @@ -181,11 +190,11 @@ func TestCreateThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("CreateThings", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.CreateThing(tc.createThingReq, tc.token) + resp, err := mgsdk.CreateThing(tc.createThingReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -215,6 +224,7 @@ func TestCreateThings(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session createThingsRequest []sdk.Thing @@ -227,6 +237,7 @@ func TestCreateThings(t *testing.T) { }{ { desc: "create new things successfully", + domainID: domainID, token: validToken, createThingsRequest: things, svcReq: convertThings(things...), @@ -237,6 +248,7 @@ func TestCreateThings(t *testing.T) { }, { desc: "create new things with invalid token", + domainID: domainID, token: invalidToken, createThingsRequest: things, svcReq: convertThings(things...), @@ -247,6 +259,7 @@ func TestCreateThings(t *testing.T) { }, { desc: "create new things with empty token", + domainID: domainID, token: "", createThingsRequest: things, svcReq: convertThings(things...), @@ -257,6 +270,7 @@ func TestCreateThings(t *testing.T) { }, { desc: "create new things with a request that can't be marshalled", + domainID: domainID, token: validToken, createThingsRequest: []sdk.Thing{{Name: "test", Metadata: map[string]interface{}{"test": make(chan int)}}}, svcReq: convertThings(things...), @@ -267,6 +281,7 @@ func TestCreateThings(t *testing.T) { }, { desc: "create new things with a response that can't be unmarshalled", + domainID: domainID, token: validToken, createThingsRequest: things, svcReq: convertThings(things...), @@ -286,11 +301,11 @@ func TestCreateThings(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("CreateThings", mock.Anything, tc.session, tc.svcReq[0], tc.svcReq[1], tc.svcReq[2]).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.CreateThings(tc.createThingsRequest, tc.token) + resp, err := mgsdk.CreateThings(tc.createThingsRequest, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -338,8 +353,9 @@ func TestListThings(t *testing.T) { desc: "list all things successfully", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -368,8 +384,9 @@ func TestListThings(t *testing.T) { desc: "list all things with an invalid token", token: invalidToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -386,8 +403,9 @@ func TestListThings(t *testing.T) { desc: "list all things with limit greater than max", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 1000, + Offset: 0, + Limit: 1000, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.ClientsPage{}, @@ -399,9 +417,10 @@ func TestListThings(t *testing.T) { desc: "list all things with name size greater than max", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Name: strings.Repeat("a", 1025), + Offset: 0, + Limit: 100, + Name: strings.Repeat("a", 1025), + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.ClientsPage{}, @@ -413,9 +432,10 @@ func TestListThings(t *testing.T) { desc: "list all things with status", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Status: mgclients.DisabledStatus.String(), + Offset: 0, + Limit: 100, + Status: mgclients.DisabledStatus.String(), + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -446,9 +466,10 @@ func TestListThings(t *testing.T) { desc: "list all things with tags", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Tag: "tag1", + Offset: 0, + Limit: 100, + Tag: "tag1", + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -484,6 +505,7 @@ func TestListThings(t *testing.T) { Metadata: map[string]interface{}{ "test": make(chan int), }, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.ClientsPage{}, @@ -495,8 +517,9 @@ func TestListThings(t *testing.T) { desc: "list all things with response that can't be unmarshalled", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -527,7 +550,7 @@ func TestListThings(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("ListClients", mock.Anything, tc.session, mock.Anything, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -580,8 +603,9 @@ func TestListThingsByChannel(t *testing.T) { token: validToken, channelID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -611,8 +635,9 @@ func TestListThingsByChannel(t *testing.T) { token: invalidToken, channelID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -630,8 +655,9 @@ func TestListThingsByChannel(t *testing.T) { token: "", channelID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.MembersPage{}, @@ -644,9 +670,10 @@ func TestListThingsByChannel(t *testing.T) { token: validToken, channelID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Status: mgclients.DisabledStatus.String(), + Offset: 0, + Limit: 100, + Status: mgclients.DisabledStatus.String(), + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -678,8 +705,9 @@ func TestListThingsByChannel(t *testing.T) { token: validToken, channelID: "", pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.MembersPage{}, @@ -697,6 +725,7 @@ func TestListThingsByChannel(t *testing.T) { Metadata: map[string]interface{}{ "test": make(chan int), }, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.MembersPage{}, @@ -709,8 +738,9 @@ func TestListThingsByChannel(t *testing.T) { token: validToken, channelID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -741,7 +771,7 @@ func TestListThingsByChannel(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("ListClientsByGroup", mock.Anything, tc.session, tc.channelID, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -770,6 +800,7 @@ func TestViewThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -781,6 +812,7 @@ func TestViewThing(t *testing.T) { }{ { desc: "view thing successfully", + domainID: domainID, token: validToken, thingID: thing.ID, svcRes: convertThing(thing), @@ -790,6 +822,7 @@ func TestViewThing(t *testing.T) { }, { desc: "view thing with an invalid token", + domainID: domainID, token: invalidToken, thingID: thing.ID, svcRes: mgclients.Client{}, @@ -799,6 +832,7 @@ func TestViewThing(t *testing.T) { }, { desc: "view thing with empty token", + domainID: domainID, token: "", thingID: thing.ID, svcRes: mgclients.Client{}, @@ -808,6 +842,7 @@ func TestViewThing(t *testing.T) { }, { desc: "view thing with an invalid thing id", + domainID: domainID, token: validToken, thingID: wrongID, svcRes: mgclients.Client{}, @@ -817,6 +852,7 @@ func TestViewThing(t *testing.T) { }, { desc: "view thing with empty thing id", + domainID: domainID, token: validToken, thingID: "", svcRes: mgclients.Client{}, @@ -825,9 +861,10 @@ func TestViewThing(t *testing.T) { err: errors.NewSDKError(apiutil.ErrMissingID), }, { - desc: "view thing with response that can't be unmarshalled", - token: validToken, - thingID: thing.ID, + desc: "view thing with response that can't be unmarshalled", + domainID: domainID, + token: validToken, + thingID: thing.ID, svcRes: mgclients.Client{ Name: thing.Name, Tags: thing.Tags, @@ -844,11 +881,11 @@ func TestViewThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("ViewClient", mock.Anything, tc.session, tc.thingID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.Thing(tc.thingID, tc.token) + resp, err := mgsdk.Thing(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -875,6 +912,7 @@ func TestViewThingPermissions(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -886,6 +924,7 @@ func TestViewThingPermissions(t *testing.T) { }{ { desc: "view thing permissions successfully", + domainID: domainID, token: validToken, thingID: validID, svcRes: []string{policies.ViewPermission}, @@ -895,6 +934,7 @@ func TestViewThingPermissions(t *testing.T) { }, { desc: "view thing permissions with an invalid token", + domainID: domainID, token: invalidToken, thingID: validID, svcRes: []string{}, @@ -904,6 +944,7 @@ func TestViewThingPermissions(t *testing.T) { }, { desc: "view thing permissions with empty token", + domainID: domainID, token: "", thingID: thing.ID, svcRes: []string{}, @@ -913,6 +954,7 @@ func TestViewThingPermissions(t *testing.T) { }, { desc: "view thing permissions with an invalid thing id", + domainID: domainID, token: validToken, thingID: wrongID, svcRes: []string{}, @@ -922,6 +964,7 @@ func TestViewThingPermissions(t *testing.T) { }, { desc: "view thing permissions with empty thing id", + domainID: domainID, token: validToken, thingID: "", svcRes: []string{}, @@ -933,11 +976,11 @@ func TestViewThingPermissions(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("ViewClientPerms", mock.Anything, tc.session, tc.thingID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.ThingPermissions(tc.thingID, tc.token) + resp, err := mgsdk.ThingPermissions(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -973,6 +1016,7 @@ func TestUpdateThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session updateThingReq sdk.Thing @@ -985,6 +1029,7 @@ func TestUpdateThing(t *testing.T) { }{ { desc: "update thing successfully", + domainID: domainID, token: validToken, updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -995,6 +1040,7 @@ func TestUpdateThing(t *testing.T) { }, { desc: "update thing with an invalid token", + domainID: domainID, token: invalidToken, updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1005,6 +1051,7 @@ func TestUpdateThing(t *testing.T) { }, { desc: "update thing with empty token", + domainID: domainID, token: "", updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1014,8 +1061,9 @@ func TestUpdateThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "update thing with an invalid thing id", - token: validToken, + desc: "update thing with an invalid thing id", + domainID: domainID, + token: validToken, updateThingReq: sdk.Thing{ ID: wrongID, Name: updatedThing.Name, @@ -1030,8 +1078,9 @@ func TestUpdateThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity), }, { - desc: "update thing with empty thing id", - token: validToken, + desc: "update thing with empty thing id", + domainID: domainID, + token: validToken, updateThingReq: sdk.Thing{ ID: "", @@ -1047,8 +1096,9 @@ func TestUpdateThing(t *testing.T) { err: errors.NewSDKError(apiutil.ErrMissingID), }, { - desc: "update thing with a request that can't be marshalled", - token: validToken, + desc: "update thing with a request that can't be marshalled", + domainID: domainID, + token: validToken, updateThingReq: sdk.Thing{ ID: "test", @@ -1064,6 +1114,7 @@ func TestUpdateThing(t *testing.T) { }, { desc: "update thing with a response that can't be unmarshalled", + domainID: domainID, token: validToken, updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1083,11 +1134,11 @@ func TestUpdateThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("UpdateClient", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.UpdateThing(tc.updateThingReq, tc.token) + resp, err := mgsdk.UpdateThing(tc.updateThingReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1119,6 +1170,7 @@ func TestUpdateThingTags(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session updateThingReq sdk.Thing @@ -1131,6 +1183,7 @@ func TestUpdateThingTags(t *testing.T) { }{ { desc: "update thing tags successfully", + domainID: domainID, token: validToken, updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1141,6 +1194,7 @@ func TestUpdateThingTags(t *testing.T) { }, { desc: "update thing tags with an invalid token", + domainID: domainID, token: invalidToken, updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1151,6 +1205,7 @@ func TestUpdateThingTags(t *testing.T) { }, { desc: "update thing tags with empty token", + domainID: domainID, token: "", updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1160,8 +1215,9 @@ func TestUpdateThingTags(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "update thing tags with an invalid thing id", - token: validToken, + desc: "update thing tags with an invalid thing id", + domainID: domainID, + token: validToken, updateThingReq: sdk.Thing{ ID: wrongID, Tags: updatedThing.Tags, @@ -1176,8 +1232,9 @@ func TestUpdateThingTags(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity), }, { - desc: "update thing tags with empty thing id", - token: validToken, + desc: "update thing tags with empty thing id", + domainID: domainID, + token: validToken, updateThingReq: sdk.Thing{ ID: "", Tags: updatedThing.Tags, @@ -1192,8 +1249,9 @@ func TestUpdateThingTags(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "update thing tags with a request that can't be marshalled", - token: validToken, + desc: "update thing tags with a request that can't be marshalled", + domainID: domainID, + token: validToken, updateThingReq: sdk.Thing{ ID: "test", Metadata: map[string]interface{}{ @@ -1208,6 +1266,7 @@ func TestUpdateThingTags(t *testing.T) { }, { desc: "update thing tags with a response that can't be unmarshalled", + domainID: domainID, token: validToken, updateThingReq: updateThingReq, svcReq: convertThing(updateThingReq), @@ -1227,11 +1286,11 @@ func TestUpdateThingTags(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("UpdateClientTags", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.UpdateThingTags(tc.updateThingReq, tc.token) + resp, err := mgsdk.UpdateThingTags(tc.updateThingReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1260,6 +1319,7 @@ func TestUpdateThingSecret(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -1272,6 +1332,7 @@ func TestUpdateThingSecret(t *testing.T) { }{ { desc: "update thing secret successfully", + domainID: domainID, token: validToken, thingID: thing.ID, newSecret: newSecret, @@ -1282,6 +1343,7 @@ func TestUpdateThingSecret(t *testing.T) { }, { desc: "update thing secret with an invalid token", + domainID: domainID, token: invalidToken, thingID: thing.ID, newSecret: newSecret, @@ -1292,6 +1354,7 @@ func TestUpdateThingSecret(t *testing.T) { }, { desc: "update thing secret with empty token", + domainID: domainID, token: "", thingID: thing.ID, newSecret: newSecret, @@ -1302,6 +1365,7 @@ func TestUpdateThingSecret(t *testing.T) { }, { desc: "update thing secret with an invalid thing id", + domainID: domainID, token: validToken, thingID: wrongID, newSecret: newSecret, @@ -1312,6 +1376,7 @@ func TestUpdateThingSecret(t *testing.T) { }, { desc: "update thing secret with empty thing id", + domainID: domainID, token: validToken, thingID: "", newSecret: newSecret, @@ -1322,6 +1387,7 @@ func TestUpdateThingSecret(t *testing.T) { }, { desc: "update thing with empty new secret", + domainID: domainID, token: validToken, thingID: thing.ID, newSecret: "", @@ -1332,6 +1398,7 @@ func TestUpdateThingSecret(t *testing.T) { }, { desc: "update thing secret with a response that can't be unmarshalled", + domainID: domainID, token: validToken, thingID: thing.ID, newSecret: newSecret, @@ -1351,11 +1418,11 @@ func TestUpdateThingSecret(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("UpdateClientSecret", mock.Anything, tc.session, tc.thingID, tc.newSecret).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.UpdateThingSecret(tc.thingID, tc.newSecret, tc.token) + resp, err := mgsdk.UpdateThingSecret(tc.thingID, tc.newSecret, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1383,6 +1450,7 @@ func TestEnableThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -1394,6 +1462,7 @@ func TestEnableThing(t *testing.T) { }{ { desc: "enable thing successfully", + domainID: domainID, token: validToken, thingID: thing.ID, svcRes: convertThing(enabledThing), @@ -1403,6 +1472,7 @@ func TestEnableThing(t *testing.T) { }, { desc: "enable thing with an invalid token", + domainID: domainID, token: invalidToken, thingID: thing.ID, svcRes: mgclients.Client{}, @@ -1412,6 +1482,7 @@ func TestEnableThing(t *testing.T) { }, { desc: "enable thing with an invalid thing id", + domainID: domainID, token: validToken, thingID: wrongID, svcRes: mgclients.Client{}, @@ -1421,6 +1492,7 @@ func TestEnableThing(t *testing.T) { }, { desc: "enable thing with empty thing id", + domainID: domainID, token: validToken, thingID: "", svcRes: mgclients.Client{}, @@ -1429,9 +1501,10 @@ func TestEnableThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "enable thing with a response that can't be unmarshalled", - token: validToken, - thingID: thing.ID, + desc: "enable thing with a response that can't be unmarshalled", + domainID: domainID, + token: validToken, + thingID: thing.ID, svcRes: mgclients.Client{ Name: enabledThing.Name, Tags: enabledThing.Tags, @@ -1448,11 +1521,11 @@ func TestEnableThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("EnableClient", mock.Anything, tc.session, tc.thingID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.EnableThing(tc.thingID, tc.token) + resp, err := mgsdk.EnableThing(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1480,6 +1553,7 @@ func TestDisableThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -1491,6 +1565,7 @@ func TestDisableThing(t *testing.T) { }{ { desc: "disable thing successfully", + domainID: domainID, token: validToken, thingID: thing.ID, svcRes: convertThing(disabledThing), @@ -1500,6 +1575,7 @@ func TestDisableThing(t *testing.T) { }, { desc: "disable thing with an invalid token", + domainID: domainID, token: invalidToken, thingID: thing.ID, svcRes: mgclients.Client{}, @@ -1509,6 +1585,7 @@ func TestDisableThing(t *testing.T) { }, { desc: "disable thing with an invalid thing id", + domainID: domainID, token: validToken, thingID: wrongID, svcRes: mgclients.Client{}, @@ -1518,6 +1595,7 @@ func TestDisableThing(t *testing.T) { }, { desc: "disable thing with empty thing id", + domainID: domainID, token: validToken, thingID: "", svcRes: mgclients.Client{}, @@ -1526,9 +1604,10 @@ func TestDisableThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "disable thing with a response that can't be unmarshalled", - token: validToken, - thingID: thing.ID, + desc: "disable thing with a response that can't be unmarshalled", + domainID: domainID, + token: validToken, + thingID: thing.ID, svcRes: mgclients.Client{ Name: disabledThing.Name, Tags: disabledThing.Tags, @@ -1545,11 +1624,11 @@ func TestDisableThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("DisableClient", mock.Anything, tc.session, tc.thingID).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.DisableThing(tc.thingID, tc.token) + resp, err := mgsdk.DisableThing(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -1575,6 +1654,7 @@ func TestShareThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -1584,9 +1664,10 @@ func TestShareThing(t *testing.T) { err errors.SDKError }{ { - desc: "share thing successfully", - token: validToken, - thingID: thing.ID, + desc: "share thing successfully", + domainID: domainID, + token: validToken, + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1595,9 +1676,10 @@ func TestShareThing(t *testing.T) { err: nil, }, { - desc: "share thing with an invalid token", - token: invalidToken, - thingID: thing.ID, + desc: "share thing with an invalid token", + domainID: domainID, + token: invalidToken, + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1606,9 +1688,10 @@ func TestShareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "share thing with empty token", - token: "", - thingID: thing.ID, + desc: "share thing with empty token", + domainID: domainID, + token: "", + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1617,9 +1700,10 @@ func TestShareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "share thing with an invalid thing id", - token: validToken, - thingID: wrongID, + desc: "share thing with an invalid thing id", + domainID: domainID, + token: validToken, + thingID: wrongID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1628,9 +1712,10 @@ func TestShareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity), }, { - desc: "share thing with empty thing id", - token: validToken, - thingID: "", + desc: "share thing with empty thing id", + domainID: domainID, + token: validToken, + thingID: "", shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1639,9 +1724,10 @@ func TestShareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), }, { - desc: "share thing with empty relation", - token: validToken, - thingID: thing.ID, + desc: "share thing with empty relation", + domainID: domainID, + token: validToken, + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: "", @@ -1653,11 +1739,11 @@ func TestShareThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("Share", mock.Anything, tc.session, tc.thingID, tc.shareReq.Relation, tc.shareReq.UserIDs[0]).Return(tc.svcErr) - err := mgsdk.ShareThing(tc.thingID, tc.shareReq, tc.token) + err := mgsdk.ShareThing(tc.thingID, tc.shareReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Share", mock.Anything, tc.session, tc.thingID, tc.shareReq.Relation, tc.shareReq.UserIDs[0]) @@ -1682,6 +1768,7 @@ func TestUnshareThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -1691,9 +1778,10 @@ func TestUnshareThing(t *testing.T) { err errors.SDKError }{ { - desc: "unshare thing successfully", - token: validToken, - thingID: thing.ID, + desc: "unshare thing successfully", + domainID: domainID, + token: validToken, + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1702,9 +1790,10 @@ func TestUnshareThing(t *testing.T) { err: nil, }, { - desc: "unshare thing with an invalid token", - token: invalidToken, - thingID: thing.ID, + desc: "unshare thing with an invalid token", + domainID: domainID, + token: invalidToken, + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1713,9 +1802,10 @@ func TestUnshareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "unshare thing with empty token", - token: "", - thingID: thing.ID, + desc: "unshare thing with empty token", + domainID: domainID, + token: "", + thingID: thing.ID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1723,9 +1813,10 @@ func TestUnshareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "unshare thing with an invalid thing id", - token: validToken, - thingID: wrongID, + desc: "unshare thing with an invalid thing id", + domainID: domainID, + token: validToken, + thingID: wrongID, shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1734,9 +1825,10 @@ func TestUnshareThing(t *testing.T) { err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity), }, { - desc: "unshare thing with empty thing id", - token: validToken, - thingID: "", + desc: "unshare thing with empty thing id", + domainID: domainID, + token: validToken, + thingID: "", shareReq: sdk.UsersRelationRequest{ UserIDs: []string{validID}, Relation: policies.EditorRelation, @@ -1748,11 +1840,11 @@ func TestUnshareThing(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("Unshare", mock.Anything, tc.session, tc.thingID, tc.shareReq.Relation, tc.shareReq.UserIDs[0]).Return(tc.svcErr) - err := mgsdk.UnshareThing(tc.thingID, tc.shareReq, tc.token) + err := mgsdk.UnshareThing(tc.thingID, tc.shareReq, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "Unshare", mock.Anything, tc.session, tc.thingID, tc.shareReq.Relation, tc.shareReq.UserIDs[0]) @@ -1777,6 +1869,7 @@ func TestDeleteThing(t *testing.T) { cases := []struct { desc string + domainID string token string session mgauthn.Session thingID string @@ -1785,49 +1878,54 @@ func TestDeleteThing(t *testing.T) { err errors.SDKError }{ { - desc: "delete thing successfully", - token: validToken, - thingID: thing.ID, - svcErr: nil, - err: nil, + desc: "delete thing successfully", + domainID: domainID, + token: validToken, + thingID: thing.ID, + svcErr: nil, + err: nil, }, { desc: "delete thing with an invalid token", + domainID: domainID, token: invalidToken, thingID: thing.ID, authenticateErr: svcerr.ErrAuthorization, err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), }, { - desc: "delete thing with empty token", - token: "", - thingID: thing.ID, - svcErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), + desc: "delete thing with empty token", + domainID: domainID, + token: "", + thingID: thing.ID, + svcErr: svcerr.ErrAuthentication, + err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "delete thing with an invalid thing id", - token: validToken, - thingID: wrongID, - svcErr: svcerr.ErrRemoveEntity, - err: errors.NewSDKErrorWithStatus(svcerr.ErrRemoveEntity, http.StatusUnprocessableEntity), + desc: "delete thing with an invalid thing id", + domainID: domainID, + token: validToken, + thingID: wrongID, + svcErr: svcerr.ErrRemoveEntity, + err: errors.NewSDKErrorWithStatus(svcerr.ErrRemoveEntity, http.StatusUnprocessableEntity), }, { - desc: "delete thing with empty thing id", - token: validToken, - thingID: "", - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), + desc: "delete thing with empty thing id", + domainID: domainID, + token: validToken, + thingID: "", + svcErr: nil, + err: errors.NewSDKError(apiutil.ErrMissingID), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("DeleteClient", mock.Anything, tc.session, tc.thingID).Return(tc.svcErr) - err := mgsdk.DeleteThing(tc.thingID, tc.token) + err := mgsdk.DeleteThing(tc.thingID, tc.domainID, tc.token) assert.Equal(t, tc.err, err) if tc.err == nil { ok := svcCall.Parent.AssertCalled(t, "DeleteClient", mock.Anything, tc.session, tc.thingID) @@ -1876,8 +1974,9 @@ func TestListUserThings(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -1907,8 +2006,9 @@ func TestListUserThings(t *testing.T) { token: invalidToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -1926,8 +2026,9 @@ func TestListUserThings(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 1000, + Offset: 0, + Limit: 1000, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.ClientsPage{}, @@ -1940,9 +2041,10 @@ func TestListUserThings(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Name: strings.Repeat("a", 1025), + Offset: 0, + Limit: 100, + Name: strings.Repeat("a", 1025), + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.ClientsPage{}, @@ -1955,9 +2057,10 @@ func TestListUserThings(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Status: mgclients.DisabledStatus.String(), + Offset: 0, + Limit: 100, + Status: mgclients.DisabledStatus.String(), + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -1989,9 +2092,10 @@ func TestListUserThings(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, - Tag: "tag1", + Offset: 0, + Limit: 100, + Tag: "tag1", + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -2028,6 +2132,7 @@ func TestListUserThings(t *testing.T) { Metadata: map[string]interface{}{ "test": make(chan int), }, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcRes: mgclients.ClientsPage{}, @@ -2039,8 +2144,9 @@ func TestListUserThings(t *testing.T) { desc: "list user things with response that can't be unmarshalled", token: validToken, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 100, + Offset: 0, + Limit: 100, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -2071,7 +2177,7 @@ func TestListUserThings(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr) svcCall := tsvc.On("ListClients", mock.Anything, tc.session, tc.userID, tc.svcReq).Return(tc.svcRes, tc.svcErr) diff --git a/pkg/sdk/go/users.go b/pkg/sdk/go/users.go index b3cdd8a585..b5f09cd8d7 100644 --- a/pkg/sdk/go/users.go +++ b/pkg/sdk/go/users.go @@ -80,7 +80,7 @@ func (sdk mgSDK) Users(pm PageMetadata, token string) (UsersPage, errors.SDKErro } func (sdk mgSDK) Members(groupID string, meta PageMetadata, token string) (UsersPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", groupsEndpoint, groupID, usersEndpoint), meta) + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", meta.DomainID, groupsEndpoint, groupID, usersEndpoint), meta) if err != nil { return UsersPage{}, errors.NewSDKError(err) } @@ -277,7 +277,7 @@ func (sdk mgSDK) UpdateUserRole(user User, token string) (User, errors.SDKError) } func (sdk mgSDK) ListUserChannels(userID string, pm PageMetadata, token string) (ChannelsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/%s/%s", usersEndpoint, userID, channelsEndpoint), pm) + url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, usersEndpoint, userID, channelsEndpoint), pm) if err != nil { return ChannelsPage{}, errors.NewSDKError(err) } @@ -295,7 +295,7 @@ func (sdk mgSDK) ListUserChannels(userID string, pm PageMetadata, token string) } func (sdk mgSDK) ListUserGroups(userID string, pm PageMetadata, token string) (GroupsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s", usersEndpoint, userID, groupsEndpoint), pm) + url, err := sdk.withQueryParams(sdk.usersURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, usersEndpoint, userID, groupsEndpoint), pm) if err != nil { return GroupsPage{}, errors.NewSDKError(err) } @@ -312,7 +312,7 @@ func (sdk mgSDK) ListUserGroups(userID string, pm PageMetadata, token string) (G } func (sdk mgSDK) ListUserThings(userID string, pm PageMetadata, token string) (ThingsPage, errors.SDKError) { - url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/%s/%s", usersEndpoint, userID, thingsEndpoint), pm) + url, err := sdk.withQueryParams(sdk.thingsURL, fmt.Sprintf("%s/%s/%s/%s", pm.DomainID, usersEndpoint, userID, thingsEndpoint), pm) if err != nil { return ThingsPage{}, errors.NewSDKError(err) } diff --git a/pkg/sdk/go/users_test.go b/pkg/sdk/go/users_test.go index 0bd61a7eaa..844f79a191 100644 --- a/pkg/sdk/go/users_test.go +++ b/pkg/sdk/go/users_test.go @@ -33,7 +33,10 @@ import ( "github.com/stretchr/testify/mock" ) -var id = generateUUID(&testing.T{}) +var ( + id = generateUUID(&testing.T{}) + domainID = "c717fa97-ffd9-40cb-8cf9-7c2859059395" +) func setupUsers() (*httptest.Server, *umocks.Service, *authnmocks.Authentication) { usvc := new(umocks.Service) @@ -291,7 +294,7 @@ func TestListUsers(t *testing.T) { }{ { desc: "list users successfully", - token: token, + token: validToken, pageMeta: sdk.PageMetadata{ Offset: offset, Limit: limit, @@ -352,7 +355,7 @@ func TestListUsers(t *testing.T) { }, { desc: "list users with zero limit", - token: token, + token: validToken, pageMeta: sdk.PageMetadata{ Offset: offset, Limit: 0, @@ -379,7 +382,7 @@ func TestListUsers(t *testing.T) { }, { desc: "list users with limit greater than max", - token: token, + token: validToken, pageMeta: sdk.PageMetadata{ Offset: offset, Limit: 101, @@ -536,7 +539,7 @@ func TestListUsers(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ListClients", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -667,7 +670,7 @@ func TestSearchClients(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, tc.authenticateErr) + authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, tc.authenticateErr) svcCall := svc.On("SearchUsers", mock.Anything, mock.Anything).Return(tc.searchreturn, tc.err) page, err := mgsdk.SearchUsers(tc.page, tc.token) assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %s, got %s", tc.desc, tc.err, err)) @@ -763,7 +766,7 @@ func TestViewUser(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ViewClient", mock.Anything, tc.session, tc.userID).Return(tc.svcRes, tc.svcErr) @@ -842,7 +845,7 @@ func TestUserProfile(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ViewProfile", mock.Anything, tc.session).Return(tc.svcRes, tc.svcErr) @@ -1006,7 +1009,7 @@ func TestUpdateUser(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("UpdateClient", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -1164,7 +1167,7 @@ func TestUpdateUserTags(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("UpdateClientTags", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -1312,7 +1315,7 @@ func TestUpdateUserIdentity(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("UpdateClientIdentity", mock.Anything, tc.session, tc.updateClientReq.ID, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -1417,7 +1420,7 @@ func TestResetPassword(t *testing.T) { { desc: "reset password successfully", token: validToken, - session: mgauthn.Session{UserID: validID, DomainID: validID}, + session: mgauthn.Session{UserID: validID, DomainID: domainID}, newPassword: newPassword, confPassword: newPassword, svcErr: nil, @@ -1442,7 +1445,7 @@ func TestResetPassword(t *testing.T) { { desc: "reset password with empty new password", token: validToken, - session: mgauthn.Session{UserID: validID, DomainID: validID}, + session: mgauthn.Session{UserID: validID, DomainID: domainID}, newPassword: "", confPassword: newPassword, svcErr: nil, @@ -1451,7 +1454,7 @@ func TestResetPassword(t *testing.T) { { desc: "reset password with empty confirm password", token: validToken, - session: mgauthn.Session{UserID: validID, DomainID: validID}, + session: mgauthn.Session{UserID: validID, DomainID: domainID}, newPassword: newPassword, confPassword: "", svcErr: nil, @@ -1460,7 +1463,7 @@ func TestResetPassword(t *testing.T) { { desc: "reset password with new password not matching confirm password", token: validToken, - session: mgauthn.Session{UserID: validID, DomainID: validID}, + session: mgauthn.Session{UserID: validID, DomainID: domainID}, newPassword: newPassword, confPassword: "wrongPassword", svcErr: nil, @@ -1469,7 +1472,7 @@ func TestResetPassword(t *testing.T) { { desc: "reset password with weak password", token: validToken, - session: mgauthn.Session{UserID: validID, DomainID: validID}, + session: mgauthn.Session{UserID: validID, DomainID: domainID}, newPassword: "weak", confPassword: "weak", svcErr: nil, @@ -1479,7 +1482,7 @@ func TestResetPassword(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ResetSecret", mock.Anything, tc.session, tc.newPassword).Return(tc.svcErr) @@ -1610,7 +1613,7 @@ func TestUpdatePassword(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("UpdateClientSecret", mock.Anything, tc.session, tc.oldPassword, tc.newPassword).Return(tc.svcRes, tc.svcErr) @@ -1767,7 +1770,7 @@ func TestUpdateUserRole(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("UpdateClientRole", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) @@ -1839,7 +1842,7 @@ func TestEnableUser(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("EnableClient", mock.Anything, tc.session, tc.userID).Return(tc.svcRes, tc.svcErr) @@ -1944,7 +1947,7 @@ func TestDisableUser(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("DisableClient", mock.Anything, tc.session, tc.userID).Return(tc.svcRes, tc.svcErr) @@ -1989,8 +1992,9 @@ func TestListMembers(t *testing.T) { token: validToken, groupID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -2016,8 +2020,9 @@ func TestListMembers(t *testing.T) { token: invalidToken, groupID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -2033,8 +2038,9 @@ func TestListMembers(t *testing.T) { token: "", groupID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcErr: nil, @@ -2046,8 +2052,9 @@ func TestListMembers(t *testing.T) { token: validToken, groupID: wrongID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -2063,8 +2070,9 @@ func TestListMembers(t *testing.T) { token: validToken, groupID: "", pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: mgclients.Page{}, svcErr: nil, @@ -2076,8 +2084,9 @@ func TestListMembers(t *testing.T) { token: validToken, groupID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, Metadata: map[string]interface{}{ "test": make(chan int), }, @@ -2093,8 +2102,9 @@ func TestListMembers(t *testing.T) { token: validToken, groupID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: mgclients.Page{ Offset: 0, @@ -2121,7 +2131,7 @@ func TestListMembers(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: 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) @@ -2195,7 +2205,7 @@ func TestDeleteUser(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("DeleteClient", mock.Anything, tc.session, tc.userID).Return(tc.svcErr) @@ -2239,8 +2249,9 @@ func TestListUserGroups(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2270,8 +2281,9 @@ func TestListUserGroups(t *testing.T) { token: invalidToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2296,8 +2308,9 @@ func TestListUserGroups(t *testing.T) { token: "", userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{}, svcErr: nil, @@ -2309,8 +2322,9 @@ func TestListUserGroups(t *testing.T) { token: validToken, userID: wrongID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2330,8 +2344,9 @@ func TestListUserGroups(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, Metadata: map[string]interface{}{ "test": make(chan int), }, @@ -2347,8 +2362,9 @@ func TestListUserGroups(t *testing.T) { token: validToken, userID: validID, pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, + Offset: 0, + Limit: 10, + DomainID: domainID, }, svcReq: groups.Page{ PageMeta: groups.PageMeta{ @@ -2378,7 +2394,7 @@ func TestListUserGroups(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID} + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ListGroups", mock.Anything, tc.session, "users", tc.userID, tc.svcReq).Return(tc.svcRes, tc.svcErr) diff --git a/pkg/sdk/mocks/sdk.go b/pkg/sdk/mocks/sdk.go index b3f6441a6f..9ac1b47e1e 100644 --- a/pkg/sdk/mocks/sdk.go +++ b/pkg/sdk/mocks/sdk.go @@ -36,9 +36,9 @@ func (_m *SDK) AcceptInvitation(domainID string, token string) error { return r0 } -// AddBootstrap provides a mock function with given fields: cfg, token -func (_m *SDK) AddBootstrap(cfg sdk.BootstrapConfig, token string) (string, errors.SDKError) { - ret := _m.Called(cfg, token) +// AddBootstrap provides a mock function with given fields: cfg, domainID, token +func (_m *SDK) AddBootstrap(cfg sdk.BootstrapConfig, domainID string, token string) (string, errors.SDKError) { + ret := _m.Called(cfg, domainID, token) if len(ret) == 0 { panic("no return value specified for AddBootstrap") @@ -46,17 +46,17 @@ func (_m *SDK) AddBootstrap(cfg sdk.BootstrapConfig, token string) (string, erro var r0 string var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string) (string, errors.SDKError)); ok { - return rf(cfg, token) + if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string, string) (string, errors.SDKError)); ok { + return rf(cfg, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string) string); ok { - r0 = rf(cfg, token) + if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string, string) string); ok { + r0 = rf(cfg, domainID, token) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(sdk.BootstrapConfig, string) errors.SDKError); ok { - r1 = rf(cfg, token) + if rf, ok := ret.Get(1).(func(sdk.BootstrapConfig, string, string) errors.SDKError); ok { + r1 = rf(cfg, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -66,17 +66,17 @@ func (_m *SDK) AddBootstrap(cfg sdk.BootstrapConfig, token string) (string, erro return r0, r1 } -// AddUserGroupToChannel provides a mock function with given fields: channelID, req, token -func (_m *SDK) AddUserGroupToChannel(channelID string, req sdk.UserGroupsRequest, token string) errors.SDKError { - ret := _m.Called(channelID, req, token) +// AddUserGroupToChannel provides a mock function with given fields: channelID, req, domainID, token +func (_m *SDK) AddUserGroupToChannel(channelID string, req sdk.UserGroupsRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(channelID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for AddUserGroupToChannel") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UserGroupsRequest, string) errors.SDKError); ok { - r0 = rf(channelID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UserGroupsRequest, string, string) errors.SDKError); ok { + r0 = rf(channelID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -86,17 +86,17 @@ func (_m *SDK) AddUserGroupToChannel(channelID string, req sdk.UserGroupsRequest return r0 } -// AddUserToChannel provides a mock function with given fields: channelID, req, token -func (_m *SDK) AddUserToChannel(channelID string, req sdk.UsersRelationRequest, token string) errors.SDKError { - ret := _m.Called(channelID, req, token) +// AddUserToChannel provides a mock function with given fields: channelID, req, domainID, token +func (_m *SDK) AddUserToChannel(channelID string, req sdk.UsersRelationRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(channelID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for AddUserToChannel") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string) errors.SDKError); ok { - r0 = rf(channelID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string, string) errors.SDKError); ok { + r0 = rf(channelID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -126,17 +126,17 @@ func (_m *SDK) AddUserToDomain(domainID string, req sdk.UsersRelationRequest, to return r0 } -// AddUserToGroup provides a mock function with given fields: groupID, req, token -func (_m *SDK) AddUserToGroup(groupID string, req sdk.UsersRelationRequest, token string) errors.SDKError { - ret := _m.Called(groupID, req, token) +// AddUserToGroup provides a mock function with given fields: groupID, req, domainID, token +func (_m *SDK) AddUserToGroup(groupID string, req sdk.UsersRelationRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(groupID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for AddUserToGroup") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string) errors.SDKError); ok { - r0 = rf(groupID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string, string) errors.SDKError); ok { + r0 = rf(groupID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -236,9 +236,9 @@ func (_m *SDK) Bootstraps(pm sdk.PageMetadata, token string) (sdk.BootstrapPage, return r0, r1 } -// Channel provides a mock function with given fields: id, token -func (_m *SDK) Channel(id string, token string) (sdk.Channel, errors.SDKError) { - ret := _m.Called(id, token) +// Channel provides a mock function with given fields: id, domainID, token +func (_m *SDK) Channel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for Channel") @@ -246,17 +246,17 @@ func (_m *SDK) Channel(id string, token string) (sdk.Channel, errors.SDKError) { var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Channel, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Channel); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Channel); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -266,9 +266,9 @@ func (_m *SDK) Channel(id string, token string) (sdk.Channel, errors.SDKError) { return r0, r1 } -// ChannelPermissions provides a mock function with given fields: id, token -func (_m *SDK) ChannelPermissions(id string, token string) (sdk.Channel, errors.SDKError) { - ret := _m.Called(id, token) +// ChannelPermissions provides a mock function with given fields: id, domainID, token +func (_m *SDK) ChannelPermissions(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for ChannelPermissions") @@ -276,17 +276,17 @@ func (_m *SDK) ChannelPermissions(id string, token string) (sdk.Channel, errors. var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Channel, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Channel); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Channel); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -326,9 +326,9 @@ func (_m *SDK) Channels(pm sdk.PageMetadata, token string) (sdk.ChannelsPage, er return r0, r1 } -// ChannelsByThing provides a mock function with given fields: thingID, pm, token -func (_m *SDK) ChannelsByThing(thingID string, pm sdk.PageMetadata, token string) (sdk.ChannelsPage, errors.SDKError) { - ret := _m.Called(thingID, pm, token) +// ChannelsByThing provides a mock function with given fields: thingID, pm, domainID, token +func (_m *SDK) ChannelsByThing(thingID string, pm sdk.PageMetadata, domainID string, token string) (sdk.ChannelsPage, errors.SDKError) { + ret := _m.Called(thingID, pm, domainID, token) if len(ret) == 0 { panic("no return value specified for ChannelsByThing") @@ -336,17 +336,17 @@ func (_m *SDK) ChannelsByThing(thingID string, pm sdk.PageMetadata, token string var r0 sdk.ChannelsPage var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string) (sdk.ChannelsPage, errors.SDKError)); ok { - return rf(thingID, pm, token) + if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string, string) (sdk.ChannelsPage, errors.SDKError)); ok { + return rf(thingID, pm, domainID, token) } - if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string) sdk.ChannelsPage); ok { - r0 = rf(thingID, pm, token) + if rf, ok := ret.Get(0).(func(string, sdk.PageMetadata, string, string) sdk.ChannelsPage); ok { + r0 = rf(thingID, pm, domainID, token) } else { r0 = ret.Get(0).(sdk.ChannelsPage) } - if rf, ok := ret.Get(1).(func(string, sdk.PageMetadata, string) errors.SDKError); ok { - r1 = rf(thingID, pm, token) + if rf, ok := ret.Get(1).(func(string, sdk.PageMetadata, string, string) errors.SDKError); ok { + r1 = rf(thingID, pm, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -386,17 +386,17 @@ func (_m *SDK) Children(id string, pm sdk.PageMetadata, token string) (sdk.Group return r0, r1 } -// Connect provides a mock function with given fields: conns, token -func (_m *SDK) Connect(conns sdk.Connection, token string) errors.SDKError { - ret := _m.Called(conns, token) +// Connect provides a mock function with given fields: conns, domainID, token +func (_m *SDK) Connect(conns sdk.Connection, domainID string, token string) errors.SDKError { + ret := _m.Called(conns, domainID, token) if len(ret) == 0 { panic("no return value specified for Connect") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Connection, string) errors.SDKError); ok { - r0 = rf(conns, token) + if rf, ok := ret.Get(0).(func(sdk.Connection, string, string) errors.SDKError); ok { + r0 = rf(conns, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -406,17 +406,17 @@ func (_m *SDK) Connect(conns sdk.Connection, token string) errors.SDKError { return r0 } -// ConnectThing provides a mock function with given fields: thingID, chanID, token -func (_m *SDK) ConnectThing(thingID string, chanID string, token string) errors.SDKError { - ret := _m.Called(thingID, chanID, token) +// ConnectThing provides a mock function with given fields: thingID, chanID, domainID, token +func (_m *SDK) ConnectThing(thingID string, chanID string, domainID string, token string) errors.SDKError { + ret := _m.Called(thingID, chanID, domainID, token) if len(ret) == 0 { panic("no return value specified for ConnectThing") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { - r0 = rf(thingID, chanID, token) + if rf, ok := ret.Get(0).(func(string, string, string, string) errors.SDKError); ok { + r0 = rf(thingID, chanID, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -426,9 +426,9 @@ func (_m *SDK) ConnectThing(thingID string, chanID string, token string) errors. return r0 } -// CreateChannel provides a mock function with given fields: channel, token -func (_m *SDK) CreateChannel(channel sdk.Channel, token string) (sdk.Channel, errors.SDKError) { - ret := _m.Called(channel, token) +// CreateChannel provides a mock function with given fields: channel, domainID, token +func (_m *SDK) CreateChannel(channel sdk.Channel, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(channel, domainID, token) if len(ret) == 0 { panic("no return value specified for CreateChannel") @@ -436,17 +436,17 @@ func (_m *SDK) CreateChannel(channel sdk.Channel, token string) (sdk.Channel, er var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Channel, string) (sdk.Channel, errors.SDKError)); ok { - return rf(channel, token) + if rf, ok := ret.Get(0).(func(sdk.Channel, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(channel, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Channel, string) sdk.Channel); ok { - r0 = rf(channel, token) + if rf, ok := ret.Get(0).(func(sdk.Channel, string, string) sdk.Channel); ok { + r0 = rf(channel, domainID, token) } else { r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(sdk.Channel, string) errors.SDKError); ok { - r1 = rf(channel, token) + if rf, ok := ret.Get(1).(func(sdk.Channel, string, string) errors.SDKError); ok { + r1 = rf(channel, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -486,9 +486,9 @@ func (_m *SDK) CreateDomain(d sdk.Domain, token string) (sdk.Domain, errors.SDKE return r0, r1 } -// CreateGroup provides a mock function with given fields: group, token -func (_m *SDK) CreateGroup(group sdk.Group, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(group, token) +// CreateGroup provides a mock function with given fields: group, domainID, token +func (_m *SDK) CreateGroup(group sdk.Group, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(group, domainID, token) if len(ret) == 0 { panic("no return value specified for CreateGroup") @@ -496,17 +496,17 @@ func (_m *SDK) CreateGroup(group sdk.Group, token string) (sdk.Group, errors.SDK var r0 sdk.Group var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Group, string) (sdk.Group, errors.SDKError)); ok { - return rf(group, token) + if rf, ok := ret.Get(0).(func(sdk.Group, string, string) (sdk.Group, errors.SDKError)); ok { + return rf(group, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Group, string) sdk.Group); ok { - r0 = rf(group, token) + if rf, ok := ret.Get(0).(func(sdk.Group, string, string) sdk.Group); ok { + r0 = rf(group, domainID, token) } else { r0 = ret.Get(0).(sdk.Group) } - if rf, ok := ret.Get(1).(func(sdk.Group, string) errors.SDKError); ok { - r1 = rf(group, token) + if rf, ok := ret.Get(1).(func(sdk.Group, string, string) errors.SDKError); ok { + r1 = rf(group, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -546,9 +546,9 @@ func (_m *SDK) CreateSubscription(topic string, contact string, token string) (s return r0, r1 } -// CreateThing provides a mock function with given fields: thing, token -func (_m *SDK) CreateThing(thing sdk.Thing, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(thing, token) +// CreateThing provides a mock function with given fields: thing, domainID, token +func (_m *SDK) CreateThing(thing sdk.Thing, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(thing, domainID, token) if len(ret) == 0 { panic("no return value specified for CreateThing") @@ -556,17 +556,17 @@ func (_m *SDK) CreateThing(thing sdk.Thing, token string) (sdk.Thing, errors.SDK var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Thing, string) (sdk.Thing, errors.SDKError)); ok { - return rf(thing, token) + if rf, ok := ret.Get(0).(func(sdk.Thing, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(thing, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Thing, string) sdk.Thing); ok { - r0 = rf(thing, token) + if rf, ok := ret.Get(0).(func(sdk.Thing, string, string) sdk.Thing); ok { + r0 = rf(thing, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(sdk.Thing, string) errors.SDKError); ok { - r1 = rf(thing, token) + if rf, ok := ret.Get(1).(func(sdk.Thing, string, string) errors.SDKError); ok { + r1 = rf(thing, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -576,9 +576,9 @@ func (_m *SDK) CreateThing(thing sdk.Thing, token string) (sdk.Thing, errors.SDK return r0, r1 } -// CreateThings provides a mock function with given fields: things, token -func (_m *SDK) CreateThings(things []sdk.Thing, token string) ([]sdk.Thing, errors.SDKError) { - ret := _m.Called(things, token) +// CreateThings provides a mock function with given fields: things, domainID, token +func (_m *SDK) CreateThings(things []sdk.Thing, domainID string, token string) ([]sdk.Thing, errors.SDKError) { + ret := _m.Called(things, domainID, token) if len(ret) == 0 { panic("no return value specified for CreateThings") @@ -586,19 +586,19 @@ func (_m *SDK) CreateThings(things []sdk.Thing, token string) ([]sdk.Thing, erro var r0 []sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func([]sdk.Thing, string) ([]sdk.Thing, errors.SDKError)); ok { - return rf(things, token) + if rf, ok := ret.Get(0).(func([]sdk.Thing, string, string) ([]sdk.Thing, errors.SDKError)); ok { + return rf(things, domainID, token) } - if rf, ok := ret.Get(0).(func([]sdk.Thing, string) []sdk.Thing); ok { - r0 = rf(things, token) + if rf, ok := ret.Get(0).(func([]sdk.Thing, string, string) []sdk.Thing); ok { + r0 = rf(things, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]sdk.Thing) } } - if rf, ok := ret.Get(1).(func([]sdk.Thing, string) errors.SDKError); ok { - r1 = rf(things, token) + if rf, ok := ret.Get(1).(func([]sdk.Thing, string, string) errors.SDKError); ok { + r1 = rf(things, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -668,17 +668,17 @@ func (_m *SDK) CreateUser(user sdk.User, token string) (sdk.User, errors.SDKErro return r0, r1 } -// DeleteChannel provides a mock function with given fields: id, token -func (_m *SDK) DeleteChannel(id string, token string) errors.SDKError { - ret := _m.Called(id, token) +// DeleteChannel provides a mock function with given fields: id, domainID, token +func (_m *SDK) DeleteChannel(id string, domainID string, token string) errors.SDKError { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for DeleteChannel") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) errors.SDKError); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { + r0 = rf(id, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -688,17 +688,17 @@ func (_m *SDK) DeleteChannel(id string, token string) errors.SDKError { return r0 } -// DeleteGroup provides a mock function with given fields: id, token -func (_m *SDK) DeleteGroup(id string, token string) errors.SDKError { - ret := _m.Called(id, token) +// DeleteGroup provides a mock function with given fields: id, domainID, token +func (_m *SDK) DeleteGroup(id string, domainID string, token string) errors.SDKError { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for DeleteGroup") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) errors.SDKError); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { + r0 = rf(id, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -746,17 +746,17 @@ func (_m *SDK) DeleteSubscription(id string, token string) errors.SDKError { return r0 } -// DeleteThing provides a mock function with given fields: id, token -func (_m *SDK) DeleteThing(id string, token string) errors.SDKError { - ret := _m.Called(id, token) +// DeleteThing provides a mock function with given fields: id, domainID, token +func (_m *SDK) DeleteThing(id string, domainID string, token string) errors.SDKError { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for DeleteThing") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) errors.SDKError); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { + r0 = rf(id, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -786,9 +786,9 @@ func (_m *SDK) DeleteUser(id string, token string) errors.SDKError { return r0 } -// DisableChannel provides a mock function with given fields: id, token -func (_m *SDK) DisableChannel(id string, token string) (sdk.Channel, errors.SDKError) { - ret := _m.Called(id, token) +// DisableChannel provides a mock function with given fields: id, domainID, token +func (_m *SDK) DisableChannel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for DisableChannel") @@ -796,17 +796,17 @@ func (_m *SDK) DisableChannel(id string, token string) (sdk.Channel, errors.SDKE var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Channel, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Channel); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Channel); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -836,9 +836,9 @@ func (_m *SDK) DisableDomain(domainID string, token string) errors.SDKError { return r0 } -// DisableGroup provides a mock function with given fields: id, token -func (_m *SDK) DisableGroup(id string, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(id, token) +// DisableGroup provides a mock function with given fields: id, domainID, token +func (_m *SDK) DisableGroup(id string, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for DisableGroup") @@ -846,17 +846,17 @@ func (_m *SDK) DisableGroup(id string, token string) (sdk.Group, errors.SDKError var r0 sdk.Group var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Group, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Group, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Group); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Group); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Group) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -866,9 +866,9 @@ func (_m *SDK) DisableGroup(id string, token string) (sdk.Group, errors.SDKError return r0, r1 } -// DisableThing provides a mock function with given fields: id, token -func (_m *SDK) DisableThing(id string, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(id, token) +// DisableThing provides a mock function with given fields: id, domainID, token +func (_m *SDK) DisableThing(id string, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for DisableThing") @@ -876,17 +876,17 @@ func (_m *SDK) DisableThing(id string, token string) (sdk.Thing, errors.SDKError var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Thing, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Thing); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Thing); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -926,17 +926,17 @@ func (_m *SDK) DisableUser(id string, token string) (sdk.User, errors.SDKError) return r0, r1 } -// Disconnect provides a mock function with given fields: connIDs, token -func (_m *SDK) Disconnect(connIDs sdk.Connection, token string) errors.SDKError { - ret := _m.Called(connIDs, token) +// Disconnect provides a mock function with given fields: connIDs, domainID, token +func (_m *SDK) Disconnect(connIDs sdk.Connection, domainID string, token string) errors.SDKError { + ret := _m.Called(connIDs, domainID, token) if len(ret) == 0 { panic("no return value specified for Disconnect") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Connection, string) errors.SDKError); ok { - r0 = rf(connIDs, token) + if rf, ok := ret.Get(0).(func(sdk.Connection, string, string) errors.SDKError); ok { + r0 = rf(connIDs, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -946,17 +946,17 @@ func (_m *SDK) Disconnect(connIDs sdk.Connection, token string) errors.SDKError return r0 } -// DisconnectThing provides a mock function with given fields: thingID, chanID, token -func (_m *SDK) DisconnectThing(thingID string, chanID string, token string) errors.SDKError { - ret := _m.Called(thingID, chanID, token) +// DisconnectThing provides a mock function with given fields: thingID, chanID, domainID, token +func (_m *SDK) DisconnectThing(thingID string, chanID string, domainID string, token string) errors.SDKError { + ret := _m.Called(thingID, chanID, domainID, token) if len(ret) == 0 { panic("no return value specified for DisconnectThing") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { - r0 = rf(thingID, chanID, token) + if rf, ok := ret.Get(0).(func(string, string, string, string) errors.SDKError); ok { + r0 = rf(thingID, chanID, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -1056,9 +1056,9 @@ func (_m *SDK) Domains(pm sdk.PageMetadata, token string) (sdk.DomainsPage, erro return r0, r1 } -// EnableChannel provides a mock function with given fields: id, token -func (_m *SDK) EnableChannel(id string, token string) (sdk.Channel, errors.SDKError) { - ret := _m.Called(id, token) +// EnableChannel provides a mock function with given fields: id, domainID, token +func (_m *SDK) EnableChannel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for EnableChannel") @@ -1066,17 +1066,17 @@ func (_m *SDK) EnableChannel(id string, token string) (sdk.Channel, errors.SDKEr var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Channel, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Channel); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Channel); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -1106,9 +1106,9 @@ func (_m *SDK) EnableDomain(domainID string, token string) errors.SDKError { return r0 } -// EnableGroup provides a mock function with given fields: id, token -func (_m *SDK) EnableGroup(id string, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(id, token) +// EnableGroup provides a mock function with given fields: id, domainID, token +func (_m *SDK) EnableGroup(id string, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for EnableGroup") @@ -1116,17 +1116,17 @@ func (_m *SDK) EnableGroup(id string, token string) (sdk.Group, errors.SDKError) var r0 sdk.Group var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Group, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Group, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Group); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Group); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Group) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -1136,9 +1136,9 @@ func (_m *SDK) EnableGroup(id string, token string) (sdk.Group, errors.SDKError) return r0, r1 } -// EnableThing provides a mock function with given fields: id, token -func (_m *SDK) EnableThing(id string, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(id, token) +// EnableThing provides a mock function with given fields: id, domainID, token +func (_m *SDK) EnableThing(id string, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for EnableThing") @@ -1146,17 +1146,17 @@ func (_m *SDK) EnableThing(id string, token string) (sdk.Thing, errors.SDKError) var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Thing, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Thing); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Thing); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -1196,9 +1196,9 @@ func (_m *SDK) EnableUser(id string, token string) (sdk.User, errors.SDKError) { return r0, r1 } -// Group provides a mock function with given fields: id, token -func (_m *SDK) Group(id string, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(id, token) +// Group provides a mock function with given fields: id, domainID, token +func (_m *SDK) Group(id string, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for Group") @@ -1206,17 +1206,17 @@ func (_m *SDK) Group(id string, token string) (sdk.Group, errors.SDKError) { var r0 sdk.Group var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Group, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Group, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Group); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Group); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Group) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -1226,9 +1226,9 @@ func (_m *SDK) Group(id string, token string) (sdk.Group, errors.SDKError) { return r0, r1 } -// GroupPermissions provides a mock function with given fields: id, token -func (_m *SDK) GroupPermissions(id string, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(id, token) +// GroupPermissions provides a mock function with given fields: id, domainID, token +func (_m *SDK) GroupPermissions(id string, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for GroupPermissions") @@ -1236,17 +1236,17 @@ func (_m *SDK) GroupPermissions(id string, token string) (sdk.Group, errors.SDKE var r0 sdk.Group var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Group, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Group, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Group); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Group); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Group) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -1372,9 +1372,9 @@ func (_m *SDK) Invitations(pm sdk.PageMetadata, token string) (sdk.InvitationPag return r0, r1 } -// IssueCert provides a mock function with given fields: thingID, validity, token -func (_m *SDK) IssueCert(thingID string, validity string, token string) (sdk.Cert, errors.SDKError) { - ret := _m.Called(thingID, validity, token) +// IssueCert provides a mock function with given fields: thingID, validity, domainID, token +func (_m *SDK) IssueCert(thingID string, validity string, domainID string, token string) (sdk.Cert, errors.SDKError) { + ret := _m.Called(thingID, validity, domainID, token) if len(ret) == 0 { panic("no return value specified for IssueCert") @@ -1382,17 +1382,17 @@ func (_m *SDK) IssueCert(thingID string, validity string, token string) (sdk.Cer var r0 sdk.Cert var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Cert, errors.SDKError)); ok { - return rf(thingID, validity, token) + if rf, ok := ret.Get(0).(func(string, string, string, string) (sdk.Cert, errors.SDKError)); ok { + return rf(thingID, validity, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string, string) sdk.Cert); ok { - r0 = rf(thingID, validity, token) + if rf, ok := ret.Get(0).(func(string, string, string, string) sdk.Cert); ok { + r0 = rf(thingID, validity, domainID, token) } else { r0 = ret.Get(0).(sdk.Cert) } - if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { - r1 = rf(thingID, validity, token) + if rf, ok := ret.Get(1).(func(string, string, string, string) errors.SDKError); ok { + r1 = rf(thingID, validity, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -1898,17 +1898,17 @@ func (_m *SDK) RejectInvitation(domainID string, token string) error { return r0 } -// RemoveBootstrap provides a mock function with given fields: id, token -func (_m *SDK) RemoveBootstrap(id string, token string) errors.SDKError { - ret := _m.Called(id, token) +// RemoveBootstrap provides a mock function with given fields: id, domainID, token +func (_m *SDK) RemoveBootstrap(id string, domainID string, token string) errors.SDKError { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for RemoveBootstrap") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) errors.SDKError); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { + r0 = rf(id, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -1918,17 +1918,17 @@ func (_m *SDK) RemoveBootstrap(id string, token string) errors.SDKError { return r0 } -// RemoveUserFromChannel provides a mock function with given fields: channelID, req, token -func (_m *SDK) RemoveUserFromChannel(channelID string, req sdk.UsersRelationRequest, token string) errors.SDKError { - ret := _m.Called(channelID, req, token) +// RemoveUserFromChannel provides a mock function with given fields: channelID, req, domainID, token +func (_m *SDK) RemoveUserFromChannel(channelID string, req sdk.UsersRelationRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(channelID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for RemoveUserFromChannel") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string) errors.SDKError); ok { - r0 = rf(channelID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string, string) errors.SDKError); ok { + r0 = rf(channelID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -1958,17 +1958,17 @@ func (_m *SDK) RemoveUserFromDomain(domainID string, userID string, token string return r0 } -// RemoveUserFromGroup provides a mock function with given fields: groupID, req, token -func (_m *SDK) RemoveUserFromGroup(groupID string, req sdk.UsersRelationRequest, token string) errors.SDKError { - ret := _m.Called(groupID, req, token) +// RemoveUserFromGroup provides a mock function with given fields: groupID, req, domainID, token +func (_m *SDK) RemoveUserFromGroup(groupID string, req sdk.UsersRelationRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(groupID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for RemoveUserFromGroup") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string) errors.SDKError); ok { - r0 = rf(groupID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string, string) errors.SDKError); ok { + r0 = rf(groupID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -1978,17 +1978,17 @@ func (_m *SDK) RemoveUserFromGroup(groupID string, req sdk.UsersRelationRequest, return r0 } -// RemoveUserGroupFromChannel provides a mock function with given fields: channelID, req, token -func (_m *SDK) RemoveUserGroupFromChannel(channelID string, req sdk.UserGroupsRequest, token string) errors.SDKError { - ret := _m.Called(channelID, req, token) +// RemoveUserGroupFromChannel provides a mock function with given fields: channelID, req, domainID, token +func (_m *SDK) RemoveUserGroupFromChannel(channelID string, req sdk.UserGroupsRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(channelID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for RemoveUserGroupFromChannel") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UserGroupsRequest, string) errors.SDKError); ok { - r0 = rf(channelID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UserGroupsRequest, string, string) errors.SDKError); ok { + r0 = rf(channelID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -2038,9 +2038,9 @@ func (_m *SDK) ResetPasswordRequest(email string) errors.SDKError { return r0 } -// RevokeCert provides a mock function with given fields: thingID, token -func (_m *SDK) RevokeCert(thingID string, token string) (time.Time, errors.SDKError) { - ret := _m.Called(thingID, token) +// RevokeCert provides a mock function with given fields: thingID, domainID, token +func (_m *SDK) RevokeCert(thingID string, domainID string, token string) (time.Time, errors.SDKError) { + ret := _m.Called(thingID, domainID, token) if len(ret) == 0 { panic("no return value specified for RevokeCert") @@ -2048,17 +2048,17 @@ func (_m *SDK) RevokeCert(thingID string, token string) (time.Time, errors.SDKEr var r0 time.Time var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (time.Time, errors.SDKError)); ok { - return rf(thingID, token) + if rf, ok := ret.Get(0).(func(string, string, string) (time.Time, errors.SDKError)); ok { + return rf(thingID, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) time.Time); ok { - r0 = rf(thingID, token) + if rf, ok := ret.Get(0).(func(string, string, string) time.Time); ok { + r0 = rf(thingID, domainID, token) } else { r0 = ret.Get(0).(time.Time) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(thingID, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(thingID, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2156,17 +2156,17 @@ func (_m *SDK) SetContentType(ct sdk.ContentType) errors.SDKError { return r0 } -// ShareThing provides a mock function with given fields: thingID, req, token -func (_m *SDK) ShareThing(thingID string, req sdk.UsersRelationRequest, token string) errors.SDKError { - ret := _m.Called(thingID, req, token) +// ShareThing provides a mock function with given fields: thingID, req, domainID, token +func (_m *SDK) ShareThing(thingID string, req sdk.UsersRelationRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(thingID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for ShareThing") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string) errors.SDKError); ok { - r0 = rf(thingID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string, string) errors.SDKError); ok { + r0 = rf(thingID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -2176,9 +2176,9 @@ func (_m *SDK) ShareThing(thingID string, req sdk.UsersRelationRequest, token st return r0 } -// Thing provides a mock function with given fields: id, token -func (_m *SDK) Thing(id string, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(id, token) +// Thing provides a mock function with given fields: id, domainID, token +func (_m *SDK) Thing(id string, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for Thing") @@ -2186,17 +2186,17 @@ func (_m *SDK) Thing(id string, token string) (sdk.Thing, errors.SDKError) { var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Thing, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Thing); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Thing); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2206,9 +2206,9 @@ func (_m *SDK) Thing(id string, token string) (sdk.Thing, errors.SDKError) { return r0, r1 } -// ThingPermissions provides a mock function with given fields: id, token -func (_m *SDK) ThingPermissions(id string, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(id, token) +// ThingPermissions provides a mock function with given fields: id, domainID, token +func (_m *SDK) ThingPermissions(id string, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for ThingPermissions") @@ -2216,17 +2216,17 @@ func (_m *SDK) ThingPermissions(id string, token string) (sdk.Thing, errors.SDKE var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Thing, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Thing); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Thing); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2296,17 +2296,17 @@ func (_m *SDK) ThingsByChannel(chanID string, pm sdk.PageMetadata, token string) return r0, r1 } -// UnshareThing provides a mock function with given fields: thingID, req, token -func (_m *SDK) UnshareThing(thingID string, req sdk.UsersRelationRequest, token string) errors.SDKError { - ret := _m.Called(thingID, req, token) +// UnshareThing provides a mock function with given fields: thingID, req, domainID, token +func (_m *SDK) UnshareThing(thingID string, req sdk.UsersRelationRequest, domainID string, token string) errors.SDKError { + ret := _m.Called(thingID, req, domainID, token) if len(ret) == 0 { panic("no return value specified for UnshareThing") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string) errors.SDKError); ok { - r0 = rf(thingID, req, token) + if rf, ok := ret.Get(0).(func(string, sdk.UsersRelationRequest, string, string) errors.SDKError); ok { + r0 = rf(thingID, req, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -2316,17 +2316,17 @@ func (_m *SDK) UnshareThing(thingID string, req sdk.UsersRelationRequest, token return r0 } -// UpdateBootstrap provides a mock function with given fields: cfg, token -func (_m *SDK) UpdateBootstrap(cfg sdk.BootstrapConfig, token string) errors.SDKError { - ret := _m.Called(cfg, token) +// UpdateBootstrap provides a mock function with given fields: cfg, domainID, token +func (_m *SDK) UpdateBootstrap(cfg sdk.BootstrapConfig, domainID string, token string) errors.SDKError { + ret := _m.Called(cfg, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateBootstrap") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string) errors.SDKError); ok { - r0 = rf(cfg, token) + if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string, string) errors.SDKError); ok { + r0 = rf(cfg, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -2336,9 +2336,9 @@ func (_m *SDK) UpdateBootstrap(cfg sdk.BootstrapConfig, token string) errors.SDK return r0 } -// UpdateBootstrapCerts provides a mock function with given fields: id, clientCert, clientKey, ca, token -func (_m *SDK) UpdateBootstrapCerts(id string, clientCert string, clientKey string, ca string, token string) (sdk.BootstrapConfig, errors.SDKError) { - ret := _m.Called(id, clientCert, clientKey, ca, token) +// UpdateBootstrapCerts provides a mock function with given fields: id, clientCert, clientKey, ca, domainID, token +func (_m *SDK) UpdateBootstrapCerts(id string, clientCert string, clientKey string, ca string, domainID string, token string) (sdk.BootstrapConfig, errors.SDKError) { + ret := _m.Called(id, clientCert, clientKey, ca, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateBootstrapCerts") @@ -2346,17 +2346,17 @@ func (_m *SDK) UpdateBootstrapCerts(id string, clientCert string, clientKey stri var r0 sdk.BootstrapConfig var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string, string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { - return rf(id, clientCert, clientKey, ca, token) + if rf, ok := ret.Get(0).(func(string, string, string, string, string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { + return rf(id, clientCert, clientKey, ca, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string, string, string, string) sdk.BootstrapConfig); ok { - r0 = rf(id, clientCert, clientKey, ca, token) + if rf, ok := ret.Get(0).(func(string, string, string, string, string, string) sdk.BootstrapConfig); ok { + r0 = rf(id, clientCert, clientKey, ca, domainID, token) } else { r0 = ret.Get(0).(sdk.BootstrapConfig) } - if rf, ok := ret.Get(1).(func(string, string, string, string, string) errors.SDKError); ok { - r1 = rf(id, clientCert, clientKey, ca, token) + if rf, ok := ret.Get(1).(func(string, string, string, string, string, string) errors.SDKError); ok { + r1 = rf(id, clientCert, clientKey, ca, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2366,17 +2366,17 @@ func (_m *SDK) UpdateBootstrapCerts(id string, clientCert string, clientKey stri return r0, r1 } -// UpdateBootstrapConnection provides a mock function with given fields: id, channels, token -func (_m *SDK) UpdateBootstrapConnection(id string, channels []string, token string) errors.SDKError { - ret := _m.Called(id, channels, token) +// UpdateBootstrapConnection provides a mock function with given fields: id, channels, domainID, token +func (_m *SDK) UpdateBootstrapConnection(id string, channels []string, domainID string, token string) errors.SDKError { + ret := _m.Called(id, channels, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateBootstrapConnection") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, []string, string) errors.SDKError); ok { - r0 = rf(id, channels, token) + if rf, ok := ret.Get(0).(func(string, []string, string, string) errors.SDKError); ok { + r0 = rf(id, channels, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) @@ -2386,9 +2386,9 @@ func (_m *SDK) UpdateBootstrapConnection(id string, channels []string, token str return r0 } -// UpdateChannel provides a mock function with given fields: channel, token -func (_m *SDK) UpdateChannel(channel sdk.Channel, token string) (sdk.Channel, errors.SDKError) { - ret := _m.Called(channel, token) +// UpdateChannel provides a mock function with given fields: channel, domainID, token +func (_m *SDK) UpdateChannel(channel sdk.Channel, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(channel, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateChannel") @@ -2396,17 +2396,17 @@ func (_m *SDK) UpdateChannel(channel sdk.Channel, token string) (sdk.Channel, er var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Channel, string) (sdk.Channel, errors.SDKError)); ok { - return rf(channel, token) + if rf, ok := ret.Get(0).(func(sdk.Channel, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(channel, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Channel, string) sdk.Channel); ok { - r0 = rf(channel, token) + if rf, ok := ret.Get(0).(func(sdk.Channel, string, string) sdk.Channel); ok { + r0 = rf(channel, domainID, token) } else { r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(sdk.Channel, string) errors.SDKError); ok { - r1 = rf(channel, token) + if rf, ok := ret.Get(1).(func(sdk.Channel, string, string) errors.SDKError); ok { + r1 = rf(channel, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2446,9 +2446,9 @@ func (_m *SDK) UpdateDomain(d sdk.Domain, token string) (sdk.Domain, errors.SDKE return r0, r1 } -// UpdateGroup provides a mock function with given fields: group, token -func (_m *SDK) UpdateGroup(group sdk.Group, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(group, token) +// UpdateGroup provides a mock function with given fields: group, domainID, token +func (_m *SDK) UpdateGroup(group sdk.Group, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(group, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateGroup") @@ -2456,17 +2456,17 @@ func (_m *SDK) UpdateGroup(group sdk.Group, token string) (sdk.Group, errors.SDK var r0 sdk.Group var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Group, string) (sdk.Group, errors.SDKError)); ok { - return rf(group, token) + if rf, ok := ret.Get(0).(func(sdk.Group, string, string) (sdk.Group, errors.SDKError)); ok { + return rf(group, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Group, string) sdk.Group); ok { - r0 = rf(group, token) + if rf, ok := ret.Get(0).(func(sdk.Group, string, string) sdk.Group); ok { + r0 = rf(group, domainID, token) } else { r0 = ret.Get(0).(sdk.Group) } - if rf, ok := ret.Get(1).(func(sdk.Group, string) errors.SDKError); ok { - r1 = rf(group, token) + if rf, ok := ret.Get(1).(func(sdk.Group, string, string) errors.SDKError); ok { + r1 = rf(group, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2506,9 +2506,9 @@ func (_m *SDK) UpdatePassword(oldPass string, newPass string, token string) (sdk return r0, r1 } -// UpdateThing provides a mock function with given fields: thing, token -func (_m *SDK) UpdateThing(thing sdk.Thing, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(thing, token) +// UpdateThing provides a mock function with given fields: thing, domainID, token +func (_m *SDK) UpdateThing(thing sdk.Thing, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(thing, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateThing") @@ -2516,17 +2516,17 @@ func (_m *SDK) UpdateThing(thing sdk.Thing, token string) (sdk.Thing, errors.SDK var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Thing, string) (sdk.Thing, errors.SDKError)); ok { - return rf(thing, token) + if rf, ok := ret.Get(0).(func(sdk.Thing, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(thing, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Thing, string) sdk.Thing); ok { - r0 = rf(thing, token) + if rf, ok := ret.Get(0).(func(sdk.Thing, string, string) sdk.Thing); ok { + r0 = rf(thing, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(sdk.Thing, string) errors.SDKError); ok { - r1 = rf(thing, token) + if rf, ok := ret.Get(1).(func(sdk.Thing, string, string) errors.SDKError); ok { + r1 = rf(thing, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2536,9 +2536,9 @@ func (_m *SDK) UpdateThing(thing sdk.Thing, token string) (sdk.Thing, errors.SDK return r0, r1 } -// UpdateThingSecret provides a mock function with given fields: id, secret, token -func (_m *SDK) UpdateThingSecret(id string, secret string, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(id, secret, token) +// UpdateThingSecret provides a mock function with given fields: id, secret, domainID, token +func (_m *SDK) UpdateThingSecret(id string, secret string, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(id, secret, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateThingSecret") @@ -2546,17 +2546,17 @@ func (_m *SDK) UpdateThingSecret(id string, secret string, token string) (sdk.Th var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Thing, errors.SDKError)); ok { - return rf(id, secret, token) + if rf, ok := ret.Get(0).(func(string, string, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(id, secret, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string, string) sdk.Thing); ok { - r0 = rf(id, secret, token) + if rf, ok := ret.Get(0).(func(string, string, string, string) sdk.Thing); ok { + r0 = rf(id, secret, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { - r1 = rf(id, secret, token) + if rf, ok := ret.Get(1).(func(string, string, string, string) errors.SDKError); ok { + r1 = rf(id, secret, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2566,9 +2566,9 @@ func (_m *SDK) UpdateThingSecret(id string, secret string, token string) (sdk.Th return r0, r1 } -// UpdateThingTags provides a mock function with given fields: thing, token -func (_m *SDK) UpdateThingTags(thing sdk.Thing, token string) (sdk.Thing, errors.SDKError) { - ret := _m.Called(thing, token) +// UpdateThingTags provides a mock function with given fields: thing, domainID, token +func (_m *SDK) UpdateThingTags(thing sdk.Thing, domainID string, token string) (sdk.Thing, errors.SDKError) { + ret := _m.Called(thing, domainID, token) if len(ret) == 0 { panic("no return value specified for UpdateThingTags") @@ -2576,17 +2576,17 @@ func (_m *SDK) UpdateThingTags(thing sdk.Thing, token string) (sdk.Thing, errors var r0 sdk.Thing var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.Thing, string) (sdk.Thing, errors.SDKError)); ok { - return rf(thing, token) + if rf, ok := ret.Get(0).(func(sdk.Thing, string, string) (sdk.Thing, errors.SDKError)); ok { + return rf(thing, domainID, token) } - if rf, ok := ret.Get(0).(func(sdk.Thing, string) sdk.Thing); ok { - r0 = rf(thing, token) + if rf, ok := ret.Get(0).(func(sdk.Thing, string, string) sdk.Thing); ok { + r0 = rf(thing, domainID, token) } else { r0 = ret.Get(0).(sdk.Thing) } - if rf, ok := ret.Get(1).(func(sdk.Thing, string) errors.SDKError); ok { - r1 = rf(thing, token) + if rf, ok := ret.Get(1).(func(sdk.Thing, string, string) errors.SDKError); ok { + r1 = rf(thing, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2806,9 +2806,9 @@ func (_m *SDK) Users(pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.S return r0, r1 } -// ViewBootstrap provides a mock function with given fields: id, token -func (_m *SDK) ViewBootstrap(id string, token string) (sdk.BootstrapConfig, errors.SDKError) { - ret := _m.Called(id, token) +// ViewBootstrap provides a mock function with given fields: id, domainID, token +func (_m *SDK) ViewBootstrap(id string, domainID string, token string) (sdk.BootstrapConfig, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { panic("no return value specified for ViewBootstrap") @@ -2816,17 +2816,17 @@ func (_m *SDK) ViewBootstrap(id string, token string) (sdk.BootstrapConfig, erro var r0 sdk.BootstrapConfig var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { - return rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.BootstrapConfig); ok { - r0 = rf(id, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.BootstrapConfig); ok { + r0 = rf(id, domainID, token) } else { r0 = ret.Get(0).(sdk.BootstrapConfig) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(id, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2836,9 +2836,9 @@ func (_m *SDK) ViewBootstrap(id string, token string) (sdk.BootstrapConfig, erro return r0, r1 } -// ViewCert provides a mock function with given fields: certID, token -func (_m *SDK) ViewCert(certID string, token string) (sdk.Cert, errors.SDKError) { - ret := _m.Called(certID, token) +// ViewCert provides a mock function with given fields: certID, domainID, token +func (_m *SDK) ViewCert(certID string, domainID string, token string) (sdk.Cert, errors.SDKError) { + ret := _m.Called(certID, domainID, token) if len(ret) == 0 { panic("no return value specified for ViewCert") @@ -2846,17 +2846,17 @@ func (_m *SDK) ViewCert(certID string, token string) (sdk.Cert, errors.SDKError) var r0 sdk.Cert var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.Cert, errors.SDKError)); ok { - return rf(certID, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Cert, errors.SDKError)); ok { + return rf(certID, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.Cert); ok { - r0 = rf(certID, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Cert); ok { + r0 = rf(certID, domainID, token) } else { r0 = ret.Get(0).(sdk.Cert) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(certID, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(certID, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2866,9 +2866,9 @@ func (_m *SDK) ViewCert(certID string, token string) (sdk.Cert, errors.SDKError) return r0, r1 } -// ViewCertByThing provides a mock function with given fields: thingID, token -func (_m *SDK) ViewCertByThing(thingID string, token string) (sdk.CertSerials, errors.SDKError) { - ret := _m.Called(thingID, token) +// ViewCertByThing provides a mock function with given fields: thingID, domainID, token +func (_m *SDK) ViewCertByThing(thingID string, domainID string, token string) (sdk.CertSerials, errors.SDKError) { + ret := _m.Called(thingID, domainID, token) if len(ret) == 0 { panic("no return value specified for ViewCertByThing") @@ -2876,17 +2876,17 @@ func (_m *SDK) ViewCertByThing(thingID string, token string) (sdk.CertSerials, e var r0 sdk.CertSerials var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.CertSerials, errors.SDKError)); ok { - return rf(thingID, token) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.CertSerials, errors.SDKError)); ok { + return rf(thingID, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.CertSerials); ok { - r0 = rf(thingID, token) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.CertSerials); ok { + r0 = rf(thingID, domainID, token) } else { r0 = ret.Get(0).(sdk.CertSerials) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(thingID, token) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(thingID, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -2926,17 +2926,17 @@ func (_m *SDK) ViewSubscription(id string, token string) (sdk.Subscription, erro return r0, r1 } -// Whitelist provides a mock function with given fields: thingID, state, token -func (_m *SDK) Whitelist(thingID string, state int, token string) errors.SDKError { - ret := _m.Called(thingID, state, token) +// Whitelist provides a mock function with given fields: thingID, state, domainID, token +func (_m *SDK) Whitelist(thingID string, state int, domainID string, token string) errors.SDKError { + ret := _m.Called(thingID, state, domainID, token) if len(ret) == 0 { panic("no return value specified for Whitelist") } var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, int, string) errors.SDKError); ok { - r0 = rf(thingID, state, token) + if rf, ok := ret.Get(0).(func(string, int, string, string) errors.SDKError); ok { + r0 = rf(thingID, state, domainID, token) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(errors.SDKError) diff --git a/provision/api/endpoint.go b/provision/api/endpoint.go index 5fc8773fd7..ec21527a5e 100644 --- a/provision/api/endpoint.go +++ b/provision/api/endpoint.go @@ -19,7 +19,7 @@ func doProvision(svc provision.Service) endpoint.Endpoint { return nil, errors.Wrap(apiutil.ErrValidation, err) } - res, err := svc.Provision(req.token, req.Name, req.ExternalID, req.ExternalKey) + res, err := svc.Provision(req.domainID, req.token, req.Name, req.ExternalID, req.ExternalKey) if err != nil { return nil, err } diff --git a/provision/api/endpoint_test.go b/provision/api/endpoint_test.go index 937e265946..369be0d9b5 100644 --- a/provision/api/endpoint_test.go +++ b/provision/api/endpoint_test.go @@ -67,6 +67,7 @@ func TestProvision(t *testing.T) { cases := []struct { desc string token string + domainID string data string contentType string status int @@ -75,6 +76,7 @@ func TestProvision(t *testing.T) { { desc: "valid request", token: validToken, + domainID: validID, data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), status: http.StatusCreated, contentType: validContenType, @@ -83,6 +85,7 @@ func TestProvision(t *testing.T) { { desc: "request with empty external id", token: validToken, + domainID: validID, data: fmt.Sprintf(`{"name": "test", "external_key": "%s"}`, validID), status: http.StatusBadRequest, contentType: validContenType, @@ -91,6 +94,7 @@ func TestProvision(t *testing.T) { { desc: "request with empty external key", token: validToken, + domainID: validID, data: fmt.Sprintf(`{"name": "test", "external_id": "%s"}`, validID), status: http.StatusBadRequest, contentType: validContenType, @@ -99,6 +103,7 @@ func TestProvision(t *testing.T) { { desc: "empty token", token: "", + domainID: validID, data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), status: http.StatusCreated, contentType: validContenType, @@ -107,6 +112,7 @@ func TestProvision(t *testing.T) { { desc: "invalid content type", token: validToken, + domainID: validID, data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), status: http.StatusUnsupportedMediaType, contentType: "text/plain", @@ -115,6 +121,7 @@ func TestProvision(t *testing.T) { { desc: "invalid request", token: validToken, + domainID: validID, data: `data`, status: http.StatusBadRequest, contentType: validContenType, @@ -123,6 +130,7 @@ func TestProvision(t *testing.T) { { desc: "service error", token: validToken, + domainID: validID, data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), status: http.StatusForbidden, contentType: validContenType, @@ -132,11 +140,11 @@ func TestProvision(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - repocall := svc.On("Provision", tc.token, "test", validID, validID).Return(provision.Result{}, tc.svcErr) + repocall := svc.On("Provision", validID, tc.token, "test", validID, validID).Return(provision.Result{}, tc.svcErr) req := testRequest{ client: is.Client(), method: http.MethodPost, - url: is.URL + "/mapping", + url: is.URL + fmt.Sprintf("/%s/mapping", tc.domainID), token: tc.token, contentType: tc.contentType, body: strings.NewReader(tc.data), @@ -156,6 +164,7 @@ func TestMapping(t *testing.T) { cases := []struct { desc string token string + domainID string contentType string status int svcErr error @@ -163,6 +172,7 @@ func TestMapping(t *testing.T) { { desc: "valid request", token: validToken, + domainID: validID, status: http.StatusOK, contentType: validContenType, svcErr: nil, @@ -170,6 +180,7 @@ func TestMapping(t *testing.T) { { desc: "empty token", token: "", + domainID: validID, status: http.StatusUnauthorized, contentType: validContenType, svcErr: nil, @@ -177,6 +188,7 @@ func TestMapping(t *testing.T) { { desc: "invalid content type", token: validToken, + domainID: validID, status: http.StatusUnsupportedMediaType, contentType: "text/plain", svcErr: nil, @@ -184,6 +196,7 @@ func TestMapping(t *testing.T) { { desc: "service error", token: validToken, + domainID: validID, status: http.StatusForbidden, contentType: validContenType, svcErr: svcerr.ErrAuthorization, @@ -196,7 +209,7 @@ func TestMapping(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodGet, - url: is.URL + "/mapping", + url: is.URL + fmt.Sprintf("/%s/mapping", tc.domainID), token: tc.token, contentType: tc.contentType, } diff --git a/provision/api/logging.go b/provision/api/logging.go index 4b2aca3d18..4d19af3c07 100644 --- a/provision/api/logging.go +++ b/provision/api/logging.go @@ -24,7 +24,7 @@ func NewLoggingMiddleware(svc provision.Service, logger *slog.Logger) provision. return &loggingMiddleware{logger, svc} } -func (lm *loggingMiddleware) Provision(token, name, externalID, externalKey string) (res provision.Result, err error) { +func (lm *loggingMiddleware) Provision(domainID, token, name, externalID, externalKey string) (res provision.Result, err error) { defer func(begin time.Time) { args := []any{ slog.String("duration", time.Since(begin).String()), @@ -39,10 +39,10 @@ func (lm *loggingMiddleware) Provision(token, name, externalID, externalKey stri lm.logger.Info("Provision completed successfully", args...) }(time.Now()) - return lm.svc.Provision(token, name, externalID, externalKey) + return lm.svc.Provision(domainID, token, name, externalID, externalKey) } -func (lm *loggingMiddleware) Cert(token, thingID, duration string) (cert, key string, err error) { +func (lm *loggingMiddleware) Cert(domainID, token, thingID, duration string) (cert, key string, err error) { defer func(begin time.Time) { args := []any{ slog.String("duration", time.Since(begin).String()), @@ -57,7 +57,7 @@ func (lm *loggingMiddleware) Cert(token, thingID, duration string) (cert, key st lm.logger.Info("Thing certificate created successfully", args...) }(time.Now()) - return lm.svc.Cert(token, thingID, duration) + return lm.svc.Cert(domainID, token, thingID, duration) } func (lm *loggingMiddleware) Mapping(token string) (res map[string]interface{}, err error) { diff --git a/provision/api/requests.go b/provision/api/requests.go index 323b98e8a3..847a235fce 100644 --- a/provision/api/requests.go +++ b/provision/api/requests.go @@ -7,6 +7,7 @@ import "github.com/absmach/magistrala/pkg/apiutil" type provisionReq struct { token string + domainID string Name string `json:"name"` ExternalID string `json:"external_id"` ExternalKey string `json:"external_key"` @@ -16,6 +17,9 @@ func (req provisionReq) validate() error { if req.ExternalID == "" { return apiutil.ErrMissingID } + if req.domainID == "" { + return apiutil.ErrMissingDomainID + } if req.ExternalKey == "" { return apiutil.ErrBearerKey @@ -29,12 +33,16 @@ func (req provisionReq) validate() error { } type mappingReq struct { - token string + token string + domainID string } func (req mappingReq) validate() error { if req.token == "" { return apiutil.ErrBearerToken } + if req.domainID == "" { + return apiutil.ErrMissingDomainID + } return nil } diff --git a/provision/api/requests_test.go b/provision/api/requests_test.go index 16bb13ff33..5cc5428af4 100644 --- a/provision/api/requests_test.go +++ b/provision/api/requests_test.go @@ -23,6 +23,7 @@ func TestProvisioReq(t *testing.T) { desc: "valid request", req: provisionReq{ token: "token", + domainID: testsutil.GenerateUUID(t), Name: "name", ExternalID: testsutil.GenerateUUID(t), ExternalKey: testsutil.GenerateUUID(t), @@ -33,16 +34,29 @@ func TestProvisioReq(t *testing.T) { desc: "empty external id", req: provisionReq{ token: "token", + domainID: testsutil.GenerateUUID(t), Name: "name", ExternalID: "", ExternalKey: testsutil.GenerateUUID(t), }, err: apiutil.ErrMissingID, }, + { + desc: "empty domain id", + req: provisionReq{ + token: "token", + domainID: "", + Name: "name", + ExternalID: testsutil.GenerateUUID(t), + ExternalKey: testsutil.GenerateUUID(t), + }, + err: apiutil.ErrMissingDomainID, + }, { desc: "empty external key", req: provisionReq{ token: "token", + domainID: testsutil.GenerateUUID(t), Name: "name", ExternalID: testsutil.GenerateUUID(t), ExternalKey: "", @@ -66,17 +80,27 @@ func TestMappingReq(t *testing.T) { { desc: "valid request", req: mappingReq{ - token: "token", + token: "token", + domainID: testsutil.GenerateUUID(t), }, err: nil, }, { desc: "empty token", req: mappingReq{ - token: "", + token: "", + domainID: testsutil.GenerateUUID(t), }, err: apiutil.ErrBearerToken, }, + { + desc: "empty domain id", + req: mappingReq{ + token: "token", + domainID: "", + }, + err: apiutil.ErrMissingDomainID, + }, } for _, tc := range cases { diff --git a/provision/api/transport.go b/provision/api/transport.go index 7c47719883..ae26a86b24 100644 --- a/provision/api/transport.go +++ b/provision/api/transport.go @@ -31,21 +31,22 @@ func MakeHandler(svc provision.Service, logger *slog.Logger, instanceID string) r := chi.NewRouter() - r.Route("/mapping", func(r chi.Router) { - r.Post("/", kithttp.NewServer( - doProvision(svc), - decodeProvisionRequest, - api.EncodeResponse, - opts..., - ).ServeHTTP) - r.Get("/", kithttp.NewServer( - getMapping(svc), - decodeMappingRequest, - api.EncodeResponse, - opts..., - ).ServeHTTP) + r.Route("/{domainID}", func(r chi.Router) { + r.Route("/mapping", func(r chi.Router) { + r.Post("/", kithttp.NewServer( + doProvision(svc), + decodeProvisionRequest, + api.EncodeResponse, + opts..., + ).ServeHTTP) + r.Get("/", kithttp.NewServer( + getMapping(svc), + decodeMappingRequest, + api.EncodeResponse, + opts..., + ).ServeHTTP) + }) }) - r.Handle("/metrics", promhttp.Handler()) r.Get("/health", magistrala.Health("provision", instanceID)) @@ -57,7 +58,10 @@ func decodeProvisionRequest(_ context.Context, r *http.Request) (interface{}, er return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) } - req := provisionReq{token: apiutil.ExtractBearerToken(r)} + req := provisionReq{ + token: apiutil.ExtractBearerToken(r), + domainID: chi.URLParam(r, "domainID"), + } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) } @@ -70,7 +74,10 @@ func decodeMappingRequest(_ context.Context, r *http.Request) (interface{}, erro return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) } - req := mappingReq{token: apiutil.ExtractBearerToken(r)} + req := mappingReq{ + token: apiutil.ExtractBearerToken(r), + domainID: chi.URLParam(r, "domainID"), + } return req, nil } diff --git a/provision/mocks/service.go b/provision/mocks/service.go index 725755bb13..ff45e5faca 100644 --- a/provision/mocks/service.go +++ b/provision/mocks/service.go @@ -14,9 +14,9 @@ type Service struct { mock.Mock } -// Cert provides a mock function with given fields: token, thingID, duration -func (_m *Service) Cert(token string, thingID string, duration string) (string, string, error) { - ret := _m.Called(token, thingID, duration) +// Cert provides a mock function with given fields: domainID, token, thingID, duration +func (_m *Service) Cert(domainID string, token string, thingID string, duration string) (string, string, error) { + ret := _m.Called(domainID, token, thingID, duration) if len(ret) == 0 { panic("no return value specified for Cert") @@ -25,23 +25,23 @@ func (_m *Service) Cert(token string, thingID string, duration string) (string, var r0 string var r1 string var r2 error - if rf, ok := ret.Get(0).(func(string, string, string) (string, string, error)); ok { - return rf(token, thingID, duration) + if rf, ok := ret.Get(0).(func(string, string, string, string) (string, string, error)); ok { + return rf(domainID, token, thingID, duration) } - if rf, ok := ret.Get(0).(func(string, string, string) string); ok { - r0 = rf(token, thingID, duration) + if rf, ok := ret.Get(0).(func(string, string, string, string) string); ok { + r0 = rf(domainID, token, thingID, duration) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(string, string, string) string); ok { - r1 = rf(token, thingID, duration) + if rf, ok := ret.Get(1).(func(string, string, string, string) string); ok { + r1 = rf(domainID, token, thingID, duration) } else { r1 = ret.Get(1).(string) } - if rf, ok := ret.Get(2).(func(string, string, string) error); ok { - r2 = rf(token, thingID, duration) + if rf, ok := ret.Get(2).(func(string, string, string, string) error); ok { + r2 = rf(domainID, token, thingID, duration) } else { r2 = ret.Error(2) } @@ -79,9 +79,9 @@ func (_m *Service) Mapping(token string) (map[string]interface{}, error) { return r0, r1 } -// Provision provides a mock function with given fields: token, name, externalID, externalKey -func (_m *Service) Provision(token string, name string, externalID string, externalKey string) (provision.Result, error) { - ret := _m.Called(token, name, externalID, externalKey) +// Provision provides a mock function with given fields: domainID, token, name, externalID, externalKey +func (_m *Service) Provision(domainID string, token string, name string, externalID string, externalKey string) (provision.Result, error) { + ret := _m.Called(domainID, token, name, externalID, externalKey) if len(ret) == 0 { panic("no return value specified for Provision") @@ -89,17 +89,17 @@ func (_m *Service) Provision(token string, name string, externalID string, exter var r0 provision.Result var r1 error - if rf, ok := ret.Get(0).(func(string, string, string, string) (provision.Result, error)); ok { - return rf(token, name, externalID, externalKey) + if rf, ok := ret.Get(0).(func(string, string, string, string, string) (provision.Result, error)); ok { + return rf(domainID, token, name, externalID, externalKey) } - if rf, ok := ret.Get(0).(func(string, string, string, string) provision.Result); ok { - r0 = rf(token, name, externalID, externalKey) + if rf, ok := ret.Get(0).(func(string, string, string, string, string) provision.Result); ok { + r0 = rf(domainID, token, name, externalID, externalKey) } else { r0 = ret.Get(0).(provision.Result) } - if rf, ok := ret.Get(1).(func(string, string, string, string) error); ok { - r1 = rf(token, name, externalID, externalKey) + if rf, ok := ret.Get(1).(func(string, string, string, string, string) error); ok { + r1 = rf(domainID, token, name, externalID, externalKey) } else { r1 = ret.Error(1) } diff --git a/provision/service.go b/provision/service.go index c86b7d6819..d247210d70 100644 --- a/provision/service.go +++ b/provision/service.go @@ -56,7 +56,7 @@ type Service interface { // - create multiple Channels // - create Bootstrap configuration // - whitelist Thing in Bootstrap configuration == connect Thing to Channels - Provision(token, name, externalID, externalKey string) (Result, error) + Provision(domainID, token, name, externalID, externalKey string) (Result, error) // Mapping returns current configuration used for provision // useful for using in ui to create configuration that matches @@ -67,7 +67,7 @@ type Service interface { // A duration string is a possibly signed sequence of decimal numbers, // each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - Cert(token, thingID, duration string) (string, string, error) + Cert(domainID, token, thingID, duration string) (string, string, error) } type provisionService struct { @@ -112,10 +112,10 @@ func (ps *provisionService) Mapping(token string) (map[string]interface{}, error // Provision is provision method for creating setup according to // provision layout specified in config.toml. -func (ps *provisionService) Provision(token, name, externalID, externalKey string) (res Result, err error) { +func (ps *provisionService) Provision(domainID, token, name, externalID, externalKey string) (res Result, err error) { var channels []sdk.Channel var things []sdk.Thing - defer ps.recover(&err, &things, &channels, &token) + defer ps.recover(&err, &things, &channels, &domainID, &token) token, err = ps.createTokenIfEmpty(token) if err != nil { @@ -142,14 +142,14 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin name = thing.Name } th.Name = name - th, err := ps.sdk.CreateThing(th, token) + th, err := ps.sdk.CreateThing(th, domainID, token) if err != nil { res.Error = err.Error() return res, errors.Wrap(ErrFailedThingCreation, err) } // Get newly created thing (in order to get the key). - th, err = ps.sdk.Thing(th.ID, token) + th, err = ps.sdk.Thing(th.ID, domainID, token) if err != nil { e := errors.Wrap(err, fmt.Errorf("thing id: %s", th.ID)) return res, errors.Wrap(ErrFailedThingRetrieval, e) @@ -162,11 +162,11 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin Name: name + "_" + channel.Name, Metadata: sdk.Metadata(channel.Metadata), } - ch, err := ps.sdk.CreateChannel(ch, token) + ch, err := ps.sdk.CreateChannel(ch, domainID, token) if err != nil { return res, errors.Wrap(ErrFailedChannelCreation, err) } - ch, err = ps.sdk.Channel(ch.ID, token) + ch, err = ps.sdk.Channel(ch.ID, domainID, token) if err != nil { e := errors.Wrap(err, fmt.Errorf("channel id: %s", ch.ID)) return res, errors.Wrap(ErrFailedChannelRetrieval, e) @@ -206,12 +206,12 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin ClientKey: cert.Key, Content: string(content), } - bsid, err := ps.sdk.AddBootstrap(bsReq, token) + bsid, err := ps.sdk.AddBootstrap(bsReq, domainID, token) if err != nil { return Result{}, errors.Wrap(ErrFailedBootstrap, err) } - bsConfig, err = ps.sdk.ViewBootstrap(bsid, token) + bsConfig, err = ps.sdk.ViewBootstrap(bsid, domainID, token) if err != nil { return Result{}, errors.Wrap(ErrFailedBootstrapValidate, err) } @@ -220,12 +220,12 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin if ps.conf.Bootstrap.X509Provision { var cert sdk.Cert - cert, err = ps.sdk.IssueCert(thing.ID, ps.conf.Cert.TTL, token) + cert, err = ps.sdk.IssueCert(thing.ID, ps.conf.Cert.TTL, domainID, token) if err != nil { e := errors.Wrap(err, fmt.Errorf("thing id: %s", thing.ID)) return res, errors.Wrap(ErrFailedCertCreation, e) } - cert, err := ps.sdk.ViewCert(cert.SerialNumber, token) + cert, err := ps.sdk.ViewCert(cert.SerialNumber, domainID, token) if err != nil { return res, errors.Wrap(ErrFailedCertView, err) } @@ -235,14 +235,14 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin res.CACert = "" if needsBootstrap(thing) { - if _, err = ps.sdk.UpdateBootstrapCerts(bsConfig.ThingID, cert.Certificate, cert.Key, "", token); err != nil { + if _, err = ps.sdk.UpdateBootstrapCerts(bsConfig.ThingID, cert.Certificate, cert.Key, "", domainID, token); err != nil { return Result{}, errors.Wrap(ErrFailedCertCreation, err) } } } if ps.conf.Bootstrap.AutoWhiteList { - if err := ps.sdk.Whitelist(thing.ID, Active, token); err != nil { + if err := ps.sdk.Whitelist(thing.ID, Active, domainID, token); err != nil { res.Error = err.Error() return res, ErrThingUpdate } @@ -250,27 +250,27 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin } } - if err = ps.updateGateway(token, bsConfig, channels); err != nil { + if err = ps.updateGateway(domainID, token, bsConfig, channels); err != nil { return res, err } return res, nil } -func (ps *provisionService) Cert(token, thingID, ttl string) (string, string, error) { +func (ps *provisionService) Cert(domainID, token, thingID, ttl string) (string, string, error) { token, err := ps.createTokenIfEmpty(token) if err != nil { return "", "", errors.Wrap(ErrFailedToCreateToken, err) } - th, err := ps.sdk.Thing(thingID, token) + th, err := ps.sdk.Thing(thingID, domainID, token) if err != nil { return "", "", errors.Wrap(ErrUnauthorized, err) } - cert, err := ps.sdk.IssueCert(th.ID, ps.conf.Cert.TTL, token) + cert, err := ps.sdk.IssueCert(th.ID, ps.conf.Cert.TTL, domainID, token) if err != nil { return "", "", errors.Wrap(ErrFailedCertCreation, err) } - cert, err = ps.sdk.ViewCert(cert.SerialNumber, token) + cert, err = ps.sdk.ViewCert(cert.SerialNumber, domainID, token) if err != nil { return "", "", errors.Wrap(ErrFailedCertView, err) } @@ -306,7 +306,7 @@ func (ps *provisionService) createTokenIfEmpty(token string) (string, error) { return tkn.AccessToken, nil } -func (ps *provisionService) updateGateway(token string, bs sdk.BootstrapConfig, channels []sdk.Channel) error { +func (ps *provisionService) updateGateway(domainID, token string, bs sdk.BootstrapConfig, channels []sdk.Channel) error { var gw Gateway for _, ch := range channels { switch ch.Metadata["type"] { @@ -323,7 +323,7 @@ func (ps *provisionService) updateGateway(token string, bs sdk.BootstrapConfig, gw.CfgID = bs.ThingID gw.Type = gateway - th, sdkerr := ps.sdk.Thing(bs.ThingID, token) + th, sdkerr := ps.sdk.Thing(bs.ThingID, domainID, token) if sdkerr != nil { return errors.Wrap(ErrGatewayUpdate, sdkerr) } @@ -334,7 +334,7 @@ func (ps *provisionService) updateGateway(token string, bs sdk.BootstrapConfig, if err := json.Unmarshal(b, &th.Metadata); err != nil { return errors.Wrap(ErrGatewayUpdate, err) } - if _, err := ps.sdk.UpdateThing(th, token); err != nil { + if _, err := ps.sdk.UpdateThing(th, domainID, token); err != nil { return errors.Wrap(ErrGatewayUpdate, err) } return nil @@ -346,68 +346,68 @@ func (ps *provisionService) errLog(err error) { } } -func clean(ps *provisionService, things []sdk.Thing, channels []sdk.Channel, token string) { +func clean(ps *provisionService, things []sdk.Thing, channels []sdk.Channel, domainID, token string) { for _, t := range things { - err := ps.sdk.DeleteThing(t.ID, token) + err := ps.sdk.DeleteThing(t.ID, domainID, token) ps.errLog(err) } for _, c := range channels { - err := ps.sdk.DeleteChannel(c.ID, token) + err := ps.sdk.DeleteChannel(c.ID, domainID, token) ps.errLog(err) } } -func (ps *provisionService) recover(e *error, ths *[]sdk.Thing, chs *[]sdk.Channel, tkn *string) { +func (ps *provisionService) recover(e *error, ths *[]sdk.Thing, chs *[]sdk.Channel, dm, tkn *string) { if e == nil { return } - things, channels, token, err := *ths, *chs, *tkn, *e + things, channels, domainID, token, err := *ths, *chs, *dm, *tkn, *e if errors.Contains(err, ErrFailedThingRetrieval) || errors.Contains(err, ErrFailedChannelCreation) { for _, th := range things { - err := ps.sdk.DeleteThing(th.ID, token) + err := ps.sdk.DeleteThing(th.ID, domainID, token) ps.errLog(err) } return } if errors.Contains(err, ErrFailedBootstrap) || errors.Contains(err, ErrFailedChannelRetrieval) { - clean(ps, things, channels, token) + clean(ps, things, channels, domainID, token) return } if errors.Contains(err, ErrFailedBootstrapValidate) || errors.Contains(err, ErrFailedCertCreation) { - clean(ps, things, channels, token) + clean(ps, things, channels, domainID, token) for _, th := range things { if needsBootstrap(th) { - ps.errLog(ps.sdk.RemoveBootstrap(th.ID, token)) + ps.errLog(ps.sdk.RemoveBootstrap(th.ID, domainID, token)) } } return } if errors.Contains(err, ErrFailedBootstrapValidate) || errors.Contains(err, ErrFailedCertCreation) { - clean(ps, things, channels, token) + clean(ps, things, channels, domainID, token) for _, th := range things { if needsBootstrap(th) { - bs, err := ps.sdk.ViewBootstrap(th.ID, token) + bs, err := ps.sdk.ViewBootstrap(th.ID, domainID, token) ps.errLog(errors.Wrap(ErrFailedBootstrapRetrieval, err)) - ps.errLog(ps.sdk.RemoveBootstrap(bs.ThingID, token)) + ps.errLog(ps.sdk.RemoveBootstrap(bs.ThingID, domainID, token)) } } } if errors.Contains(err, ErrThingUpdate) || errors.Contains(err, ErrGatewayUpdate) { - clean(ps, things, channels, token) + clean(ps, things, channels, domainID, token) for _, th := range things { if ps.conf.Bootstrap.X509Provision && needsBootstrap(th) { - _, err := ps.sdk.RevokeCert(th.ID, token) + _, err := ps.sdk.RevokeCert(th.ID, domainID, token) ps.errLog(err) } if needsBootstrap(th) { - bs, err := ps.sdk.ViewBootstrap(th.ID, token) + bs, err := ps.sdk.ViewBootstrap(th.ID, domainID, token) ps.errLog(errors.Wrap(ErrFailedBootstrapRetrieval, err)) - ps.errLog(ps.sdk.RemoveBootstrap(bs.ThingID, token)) + ps.errLog(ps.sdk.RemoveBootstrap(bs.ThingID, domainID, token)) } } return diff --git a/provision/service_test.go b/provision/service_test.go index 9959fbbca7..ef3268d016 100644 --- a/provision/service_test.go +++ b/provision/service_test.go @@ -64,6 +64,7 @@ func TestCert(t *testing.T) { cases := []struct { desc string config provision.Config + domainID string token string thingID string ttl string @@ -78,6 +79,7 @@ func TestCert(t *testing.T) { { desc: "valid", config: validConfig, + domainID: testsutil.GenerateUUID(t), token: validToken, thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -94,6 +96,7 @@ func TestCert(t *testing.T) { Server: provision.ServiceConf{MgAPIKey: "key"}, Cert: provision.Cert{TTL: "1h"}, }, + domainID: testsutil.GenerateUUID(t), token: "", thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -114,6 +117,7 @@ func TestCert(t *testing.T) { }, Cert: provision.Cert{TTL: "1h"}, }, + domainID: testsutil.GenerateUUID(t), token: "", thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -134,6 +138,7 @@ func TestCert(t *testing.T) { }, Cert: provision.Cert{TTL: "1h"}, }, + domainID: testsutil.GenerateUUID(t), token: "", thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -150,6 +155,7 @@ func TestCert(t *testing.T) { Server: provision.ServiceConf{}, Cert: provision.Cert{TTL: "1h"}, }, + domainID: testsutil.GenerateUUID(t), token: "", thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -163,6 +169,7 @@ func TestCert(t *testing.T) { { desc: "invalid thingID", config: validConfig, + domainID: testsutil.GenerateUUID(t), token: "invalid", thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -176,6 +183,7 @@ func TestCert(t *testing.T) { { desc: "invalid thingID", config: validConfig, + domainID: testsutil.GenerateUUID(t), token: validToken, thingID: "invalid", ttl: "1h", @@ -189,6 +197,7 @@ func TestCert(t *testing.T) { { desc: "failed to issue cert", config: validConfig, + domainID: testsutil.GenerateUUID(t), token: validToken, thingID: testsutil.GenerateUUID(t), ttl: "1h", @@ -206,16 +215,16 @@ func TestCert(t *testing.T) { mgsdk := new(sdkmocks.SDK) svc := provision.New(c.config, mgsdk, mglog.NewMock()) - mgsdk.On("Thing", c.thingID, mock.Anything).Return(sdk.Thing{ID: c.thingID}, c.sdkThingErr) - mgsdk.On("IssueCert", c.thingID, c.config.Cert.TTL, mock.Anything).Return(sdk.Cert{SerialNumber: c.serial}, c.sdkCertErr) - mgsdk.On("ViewCert", c.serial, mock.Anything).Return(sdk.Cert{Certificate: c.cert, Key: c.key}, c.sdkCertErr) + mgsdk.On("Thing", c.thingID, c.domainID, mock.Anything).Return(sdk.Thing{ID: c.thingID}, c.sdkThingErr) + mgsdk.On("IssueCert", c.thingID, c.config.Cert.TTL, c.domainID, mock.Anything).Return(sdk.Cert{SerialNumber: c.serial}, c.sdkCertErr) + mgsdk.On("ViewCert", c.serial, mock.Anything, mock.Anything).Return(sdk.Cert{Certificate: c.cert, Key: c.key}, c.sdkCertErr) login := sdk.Login{ Identity: c.config.Server.MgUser, Secret: c.config.Server.MgPass, DomainID: c.config.Server.MgDomainID, } mgsdk.On("CreateToken", login).Return(sdk.Token{AccessToken: validToken}, c.sdkTokenErr) - cert, key, err := svc.Cert(c.token, c.thingID, c.ttl) + cert, key, err := svc.Cert(c.domainID, c.token, c.thingID, c.ttl) assert.Equal(t, c.cert, cert) assert.Equal(t, c.key, key) assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected error %v, got %v", c.err, err)) diff --git a/readers/api/transport.go b/readers/api/transport.go index f92c103501..82a5d17fd5 100644 --- a/readers/api/transport.go +++ b/readers/api/transport.go @@ -6,7 +6,6 @@ package api import ( "context" "encoding/json" - "fmt" "net/http" "github.com/absmach/magistrala" @@ -258,7 +257,6 @@ func authorize(ctx context.Context, req listMessagesReq, authz mgauthz.Authoriza if ok && e.Code() == codes.PermissionDenied { return errors.Wrap(errUserAccess, err) } - fmt.Println("err", err) return err } return nil diff --git a/things/api/http/channels.go b/things/api/http/channels.go index a51e887d2e..4d4244892c 100644 --- a/things/api/http/channels.go +++ b/things/api/http/channels.go @@ -28,9 +28,9 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, } r.Group(func(r chi.Router) { - r.Use(api.AuthenticateMiddleware(authn)) + r.Use(api.AuthenticateMiddlewareDomain(authn)) - r.Route("/channels", func(r chi.Router) { + r.Route("/{domainID}/channels", func(r chi.Router) { r.Post("/", otelhttp.NewHandler(kithttp.NewServer( gapi.CreateGroupEndpoint(svc, policies.NewChannelKind), gapi.DecodeGroupCreate, @@ -143,7 +143,7 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, // SpiceDB provides list of channel ids to which thing id attached // and channel service can access spiceDB and get this channel ids list with given thing id. // Request to get list of channels to which thingID ({memberID}) belongs - r.Get("/things/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/things/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer( gapi.ListGroupsEndpoint(svc, "channels", "things"), gapi.DecodeListGroupsRequest, api.EncodeResponse, @@ -155,7 +155,7 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, // SpiceDB provides list of channel ids attached to given user id // and channel service can access spiceDB and get this user ids list with given thing id. // Request to get list of channels to which userID ({memberID}) have permission. - r.Get("/users/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/users/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer( gapi.ListGroupsEndpoint(svc, "channels", "users"), gapi.DecodeListGroupsRequest, api.EncodeResponse, @@ -166,7 +166,7 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, // SpiceDB provides list of channel ids attached to given user_group id // and channel service can access spiceDB and get this user ids list with given user_group id. // Request to get list of channels to which user_group_id ({memberID}) attached. - r.Get("/groups/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/groups/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer( gapi.ListGroupsEndpoint(svc, "channels", "groups"), gapi.DecodeListGroupsRequest, api.EncodeResponse, @@ -174,7 +174,7 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, ), "list_channel_by_user_group_id").ServeHTTP) // Connect channel and thing - r.Post("/connect", otelhttp.NewHandler(kithttp.NewServer( + r.Post("/{domainID}/connect", otelhttp.NewHandler(kithttp.NewServer( connectEndpoint(svc), decodeConnectRequest, api.EncodeResponse, @@ -182,7 +182,7 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, ), "connect").ServeHTTP) // Disconnect channel and thing - r.Post("/disconnect", otelhttp.NewHandler(kithttp.NewServer( + r.Post("/{domainID}/disconnect", otelhttp.NewHandler(kithttp.NewServer( disconnectEndpoint(svc), decodeDisconnectRequest, api.EncodeResponse, diff --git a/things/api/http/clients.go b/things/api/http/clients.go index caf0195a36..48f0ac5091 100644 --- a/things/api/http/clients.go +++ b/things/api/http/clients.go @@ -25,11 +25,10 @@ func clientsHandler(svc things.Service, r *chi.Mux, authn mgauthn.Authentication opts := []kithttp.ServerOption{ kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)), } - r.Group(func(r chi.Router) { - r.Use(api.AuthenticateMiddleware(authn)) + r.Use(api.AuthenticateMiddlewareDomain(authn)) - r.Route("/things", func(r chi.Router) { + r.Route("/{domainID}/things", func(r chi.Router) { r.Post("/", otelhttp.NewHandler(kithttp.NewServer( createClientEndpoint(svc), decodeCreateClientReq, @@ -127,21 +126,20 @@ func clientsHandler(svc things.Service, r *chi.Mux, authn mgauthn.Authentication // SpiceDB provides list of thing ids present in given channel id // and things service can access spiceDB and get the list of thing ids present in given channel id. // Request to get list of things present in channelID ({groupID}) . - r.Get("/channels/{groupID}/things", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/channels/{groupID}/things", otelhttp.NewHandler(kithttp.NewServer( listMembersEndpoint(svc), decodeListMembersRequest, api.EncodeResponse, opts..., ), "list_things_by_channel_id").ServeHTTP) - r.Get("/users/{userID}/things", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/users/{userID}/things", otelhttp.NewHandler(kithttp.NewServer( listClientsEndpoint(svc), decodeListClients, api.EncodeResponse, opts..., ), "list_user_things").ServeHTTP) }) - return r } diff --git a/things/api/http/endpoints_test.go b/things/api/http/endpoints_test.go index ad18397751..eb34ddd1d3 100644 --- a/things/api/http/endpoints_test.go +++ b/things/api/http/endpoints_test.go @@ -46,6 +46,7 @@ var ( inValidToken = "invalid" inValid = "invalid" validID = testsutil.GenerateUUID(&testing.T{}) + domainID = testsutil.GenerateUUID(&testing.T{}) namesgen = namegenerator.NewGenerator() ) @@ -106,6 +107,7 @@ func TestCreateThing(t *testing.T) { cases := []struct { desc string client mgclients.Client + domainID string token string contentType string status int @@ -116,8 +118,9 @@ func TestCreateThing(t *testing.T) { { desc: "register a new thing with a valid token", client: client, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusCreated, err: nil, @@ -125,8 +128,9 @@ func TestCreateThing(t *testing.T) { { desc: "register an existing thing", client: client, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusConflict, err: svcerr.ErrConflict, @@ -134,6 +138,7 @@ func TestCreateThing(t *testing.T) { { desc: "register a new thing with an empty token", client: client, + domainID: domainID, token: "", contentType: contentType, status: http.StatusUnauthorized, @@ -149,8 +154,9 @@ func TestCreateThing(t *testing.T) { Secret: "12345678", }, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -166,8 +172,9 @@ func TestCreateThing(t *testing.T) { "test": make(chan int), }, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: errors.ErrMalformedEntity, @@ -182,8 +189,9 @@ func TestCreateThing(t *testing.T) { }, Status: mgclients.AllStatus, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: svcerr.ErrInvalidStatus, @@ -197,8 +205,9 @@ func TestCreateThing(t *testing.T) { Secret: secret, }, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, @@ -206,30 +215,32 @@ func TestCreateThing(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/", ts.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("CreateThings", mock.Anything, tc.authnRes, tc.client).Return([]mgclients.Client{tc.client}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/", ts.URL, tc.domainID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("CreateThings", mock.Anything, tc.authnRes, tc.client).Return([]mgclients.Client{tc.client}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -256,6 +267,7 @@ func TestCreateThings(t *testing.T) { cases := []struct { desc string client []mgclients.Client + domainID string token string contentType string status int @@ -267,8 +279,9 @@ func TestCreateThings(t *testing.T) { { desc: "create things with valid token", client: items, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusOK, err: nil, @@ -296,8 +309,9 @@ func TestCreateThings(t *testing.T) { { desc: "create things with empty request", client: []mgclients.Client{}, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -316,8 +330,9 @@ func TestCreateThings(t *testing.T) { ID: validID, }, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -329,8 +344,9 @@ func TestCreateThings(t *testing.T) { ID: testsutil.GenerateUUID(t), }, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, @@ -350,8 +366,9 @@ func TestCreateThings(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: errors.ErrMalformedEntity, }, @@ -359,40 +376,43 @@ func TestCreateThings(t *testing.T) { desc: "create things with service error", client: items, contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusUnprocessableEntity, err: svcerr.ErrCreateEntity, }, } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/bulk", ts.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("CreateThings", mock.Anything, tc.authnRes, mock.Anything, mock.Anything, mock.Anything).Return(tc.client, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - var bodyRes respBody - err = json.NewDecoder(res.Body).Decode(&bodyRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if bodyRes.Err != "" || bodyRes.Message != "" { - err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) - } - 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.len, bodyRes.Total, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.len, bodyRes.Total)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/bulk", ts.URL, domainID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("CreateThings", mock.Anything, tc.authnRes, mock.Anything, mock.Anything, mock.Anything).Return(tc.client, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + var bodyRes respBody + err = json.NewDecoder(res.Body).Decode(&bodyRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if bodyRes.Err != "" || bodyRes.Message != "" { + err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) + } + 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.len, bodyRes.Total, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.len, bodyRes.Total)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -403,6 +423,7 @@ func TestListThings(t *testing.T) { cases := []struct { desc string query string + domainID string token string listThingsResponse mgclients.ClientsPage status int @@ -412,8 +433,9 @@ func TestListThings(t *testing.T) { }{ { desc: "list things as admin with valid token", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID, SuperAdmin: false}, status: http.StatusOK, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ @@ -425,8 +447,9 @@ func TestListThings(t *testing.T) { }, { desc: "list things as non admin with valid token", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, status: http.StatusOK, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ @@ -437,13 +460,15 @@ func TestListThings(t *testing.T) { err: nil, }, { - desc: "list things with empty token", - token: "", - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, + desc: "list things with empty token", + domainID: domainID, + token: "", + status: http.StatusUnauthorized, + err: apiutil.ErrBearerToken, }, { desc: "list things with invalid token", + domainID: domainID, token: inValidToken, status: http.StatusUnauthorized, authnErr: svcerr.ErrAuthentication, @@ -451,8 +476,9 @@ func TestListThings(t *testing.T) { }, { desc: "list things with offset", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Offset: 1, @@ -466,16 +492,18 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid offset", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "offset=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with limit", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Limit: 1, @@ -489,8 +517,9 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid limit", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "limit=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -498,15 +527,17 @@ func TestListThings(t *testing.T) { { desc: "list things with limit greater than max", token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + domainID: domainID, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with name", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, @@ -519,24 +550,27 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid name", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "name=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with duplicate name", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "name=1&name=2", status: http.StatusBadRequest, err: apiutil.ErrInvalidQueryParams, }, { desc: "list things with status", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, @@ -549,24 +583,27 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid status", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "status=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with duplicate status", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "status=enabled&status=disabled", status: http.StatusBadRequest, err: apiutil.ErrInvalidQueryParams, }, { desc: "list things with tags", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, @@ -579,24 +616,27 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid tags", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "tag=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with duplicate tags", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "tag=tag1&tag=tag2", status: http.StatusBadRequest, err: apiutil.ErrInvalidQueryParams, }, { desc: "list things with metadata", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, @@ -609,24 +649,27 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid metadata", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "metadata=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with duplicate metadata", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&metadata=%7B%22domain%22%3A%20%22example.com%22%7D", status: http.StatusBadRequest, err: apiutil.ErrInvalidQueryParams, }, { desc: "list things with permissions", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, @@ -639,24 +682,27 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid permissions", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "permission=invalid", status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { desc: "list things with duplicate permissions", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "permission=view&permission=view", status: http.StatusBadRequest, err: apiutil.ErrInvalidQueryParams, }, { desc: "list things with list perms", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, listThingsResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, @@ -670,8 +716,9 @@ func TestListThings(t *testing.T) { }, { desc: "list things with invalid list perms", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "list_perms=invalid", status: http.StatusBadRequest, @@ -679,8 +726,9 @@ func TestListThings(t *testing.T) { }, { desc: "list things with duplicate list perms", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID, SuperAdmin: false}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: false}, query: "list_perms=true&listPerms=true", status: http.StatusBadRequest, @@ -689,29 +737,31 @@ func TestListThings(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodGet, - url: ts.URL + "/things?" + tc.query, - contentType: contentType, - token: tc.token, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListClients", mock.Anything, tc.authnRes, "", mock.Anything).Return(tc.listThingsResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - var bodyRes respBody - err = json.NewDecoder(res.Body).Decode(&bodyRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if bodyRes.Err != "" || bodyRes.Message != "" { - err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodGet, + url: ts.URL + "/" + tc.domainID + "/things?" + tc.query, + contentType: contentType, + token: tc.token, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListClients", mock.Anything, tc.authnRes, "", mock.Anything).Return(tc.listThingsResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + var bodyRes respBody + err = json.NewDecoder(res.Body).Decode(&bodyRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if bodyRes.Err != "" || bodyRes.Message != "" { + err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -721,6 +771,7 @@ func TestViewThing(t *testing.T) { cases := []struct { desc string + domainID string token string id string status int @@ -730,8 +781,9 @@ func TestViewThing(t *testing.T) { }{ { desc: "view client with valid token", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, id: client.ID, status: http.StatusOK, @@ -739,6 +791,7 @@ func TestViewThing(t *testing.T) { }, { desc: "view client with invalid token", + domainID: domainID, token: inValidToken, id: client.ID, status: http.StatusUnauthorized, @@ -746,16 +799,18 @@ func TestViewThing(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "view client with empty token", - token: "", - id: client.ID, - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, + desc: "view client with empty token", + domainID: domainID, + token: "", + id: client.ID, + status: http.StatusUnauthorized, + err: apiutil.ErrBearerToken, }, { desc: "view client with invalid id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, id: inValid, status: http.StatusForbidden, @@ -764,27 +819,29 @@ func TestViewThing(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/things/%s", ts.URL, tc.id), - token: tc.token, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ViewClient", mock.Anything, tc.authnRes, tc.id).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/things/%s", ts.URL, tc.domainID, tc.id), + token: tc.token, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ViewClient", mock.Anything, tc.authnRes, tc.id).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -794,6 +851,7 @@ func TestViewThingPerms(t *testing.T) { cases := []struct { desc string + domainID string token string thingID string response []string @@ -804,8 +862,9 @@ func TestViewThingPerms(t *testing.T) { }{ { desc: "view thing permissions with valid token", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, thingID: client.ID, response: []string{"view", "delete", "membership"}, status: http.StatusOK, @@ -814,6 +873,7 @@ func TestViewThingPerms(t *testing.T) { }, { desc: "view thing permissions with invalid token", + domainID: domainID, token: inValidToken, thingID: client.ID, response: []string{}, @@ -823,6 +883,7 @@ func TestViewThingPerms(t *testing.T) { }, { desc: "view thing permissions with empty token", + domainID: domainID, token: "", thingID: client.ID, response: []string{}, @@ -831,8 +892,9 @@ func TestViewThingPerms(t *testing.T) { }, { desc: "view thing permissions with invalid id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, thingID: inValid, response: []string{}, status: http.StatusForbidden, @@ -841,8 +903,9 @@ func TestViewThingPerms(t *testing.T) { }, { desc: "view thing permissions with empty id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, thingID: "", response: []string{}, status: http.StatusBadRequest, @@ -852,28 +915,30 @@ func TestViewThingPerms(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/things/%s/permissions", ts.URL, tc.thingID), - token: tc.token, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ViewClientPerms", mock.Anything, tc.authnRes, tc.thingID).Return(tc.response, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - assert.Equal(t, len(tc.response), len(resBody.Permissions), fmt.Sprintf("%s: expected %d got %d", tc.desc, len(tc.response), len(resBody.Permissions))) - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/things/%s/permissions", ts.URL, tc.domainID, tc.thingID), + token: tc.token, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ViewClientPerms", mock.Anything, tc.authnRes, tc.thingID).Return(tc.response, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + assert.Equal(t, len(tc.response), len(resBody.Permissions), fmt.Sprintf("%s: expected %d got %d", tc.desc, len(tc.response), len(resBody.Permissions))) + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -890,6 +955,7 @@ func TestUpdateThing(t *testing.T) { id string data string clientResponse mgclients.Client + domainID string token string contentType string status int @@ -899,8 +965,9 @@ func TestUpdateThing(t *testing.T) { }{ { desc: "update thing with valid token", + domainID: domainID, id: client.ID, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, newName, newTag, toJSON(newMetadata)), token: validToken, contentType: contentType, @@ -918,6 +985,7 @@ func TestUpdateThing(t *testing.T) { desc: "update thing with invalid token", id: client.ID, data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, newName, newTag, toJSON(newMetadata)), + domainID: domainID, token: inValidToken, contentType: contentType, status: http.StatusUnauthorized, @@ -928,6 +996,7 @@ func TestUpdateThing(t *testing.T) { desc: "update thing with empty token", id: client.ID, data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, newName, newTag, toJSON(newMetadata)), + domainID: domainID, token: "", contentType: contentType, status: http.StatusUnauthorized, @@ -937,8 +1006,9 @@ func TestUpdateThing(t *testing.T) { desc: "update thing with invalid contentype", id: client.ID, data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, newName, newTag, toJSON(newMetadata)), + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, @@ -948,8 +1018,9 @@ func TestUpdateThing(t *testing.T) { desc: "update thing with malformed data", id: client.ID, data: fmt.Sprintf(`{"name":%s}`, "invalid"), + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -959,8 +1030,9 @@ func TestUpdateThing(t *testing.T) { desc: "update thing with empty id", id: " ", data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, newName, newTag, toJSON(newMetadata)), + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -969,8 +1041,9 @@ func TestUpdateThing(t *testing.T) { { desc: "update thing with name that is too long", id: client.ID, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, strings.Repeat("a", api.MaxNameSize+1), newTag, toJSON(newMetadata)), + domainID: domainID, token: validToken, contentType: contentType, clientResponse: mgclients.Client{}, @@ -980,34 +1053,36 @@ func TestUpdateThing(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/things/%s", ts.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClient", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - - if err == nil { - assert.Equal(t, tc.clientResponse.ID, resBody.ID, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.clientResponse, resBody.ID)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/%s/things/%s", ts.URL, tc.domainID, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClient", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + + if err == nil { + assert.Equal(t, tc.clientResponse.ID, resBody.ID, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.clientResponse, resBody.ID)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1023,6 +1098,7 @@ func TestUpdateThingsTags(t *testing.T) { data string contentType string clientResponse mgclients.Client + domainID string token string status int authnRes mgauthn.Session @@ -1038,8 +1114,9 @@ func TestUpdateThingsTags(t *testing.T) { ID: client.ID, Tags: []string{newTag}, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, @@ -1049,6 +1126,7 @@ func TestUpdateThingsTags(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: contentType, + domainID: domainID, token: "", status: http.StatusUnauthorized, err: apiutil.ErrBearerToken, @@ -1058,6 +1136,7 @@ func TestUpdateThingsTags(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: contentType, + domainID: domainID, token: inValidToken, status: http.StatusUnauthorized, authnErr: svcerr.ErrAuthentication, @@ -1068,8 +1147,9 @@ func TestUpdateThingsTags(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusForbidden, err: svcerr.ErrAuthorization, @@ -1079,8 +1159,9 @@ func TestUpdateThingsTags(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: "application/xml", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, }, @@ -1089,8 +1170,9 @@ func TestUpdateThingsTags(t *testing.T) { id: "", data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -1100,8 +1182,9 @@ func TestUpdateThingsTags(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"tags":[%s]}`, newTag), contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: errors.ErrMalformedEntity, @@ -1109,29 +1192,31 @@ func TestUpdateThingsTags(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/things/%s/tags", ts.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClientTags", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/%s/things/%s/tags", ts.URL, tc.domainID, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClientTags", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1144,6 +1229,7 @@ func TestUpdateClientSecret(t *testing.T) { data string client mgclients.Client contentType string + domainID string token string status int authnRes mgauthn.Session @@ -1161,11 +1247,11 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusOK, - - err: nil, + err: nil, }, { desc: "update thing secret with empty token", @@ -1178,6 +1264,7 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: "", status: http.StatusUnauthorized, err: apiutil.ErrBearerToken, @@ -1193,6 +1280,7 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: inValid, status: http.StatusUnauthorized, authnErr: svcerr.ErrAuthentication, @@ -1209,11 +1297,11 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, { desc: "update thing secret with empty secret", @@ -1226,8 +1314,9 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -1243,8 +1332,9 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: "application/xml", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, @@ -1260,8 +1350,9 @@ func TestUpdateClientSecret(t *testing.T) { }, }, contentType: contentType, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -1269,29 +1360,31 @@ func TestUpdateClientSecret(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/things/%s/secret", ts.URL, tc.client.ID), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClientSecret", mock.Anything, tc.authnRes, tc.client.ID, mock.Anything).Return(tc.client, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/%s/things/%s/secret", ts.URL, tc.domainID, tc.client.ID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClientSecret", mock.Anything, tc.authnRes, tc.client.ID, mock.Anything).Return(tc.client, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1303,6 +1396,7 @@ func TestEnableThing(t *testing.T) { desc string client mgclients.Client response mgclients.Client + domainID string token string status int authnRes mgauthn.Session @@ -1316,8 +1410,9 @@ func TestEnableThing(t *testing.T) { ID: client.ID, Status: mgclients.EnabledStatus, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, @@ -1325,6 +1420,7 @@ func TestEnableThing(t *testing.T) { { desc: "enable thing with invalid token", client: client, + domainID: domainID, token: inValidToken, status: http.StatusUnauthorized, authnErr: svcerr.ErrAuthentication, @@ -1335,8 +1431,9 @@ func TestEnableThing(t *testing.T) { client: mgclients.Client{ ID: "", }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -1344,33 +1441,35 @@ func TestEnableThing(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/%s/enable", ts.URL, tc.client.ID), - contentType: contentType, - token: tc.token, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("EnableClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - if err == nil { - assert.Equal(t, tc.response.Status, resBody.Status, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.response.Status, resBody.Status)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/%s/enable", ts.URL, tc.domainID, tc.client.ID), + contentType: contentType, + token: tc.token, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("EnableClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + if err == nil { + assert.Equal(t, tc.response.Status, resBody.Status, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.response.Status, resBody.Status)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1382,6 +1481,7 @@ func TestDisableThing(t *testing.T) { desc string client mgclients.Client response mgclients.Client + domainID string token string status int authnRes mgauthn.Session @@ -1395,8 +1495,9 @@ func TestDisableThing(t *testing.T) { ID: client.ID, Status: mgclients.DisabledStatus, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, @@ -1404,6 +1505,7 @@ func TestDisableThing(t *testing.T) { { desc: "disable thing with invalid token", client: client, + domainID: domainID, token: inValidToken, status: http.StatusUnauthorized, authnErr: svcerr.ErrAuthentication, @@ -1414,8 +1516,9 @@ func TestDisableThing(t *testing.T) { client: mgclients.Client{ ID: "", }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -1423,33 +1526,35 @@ func TestDisableThing(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/%s/disable", ts.URL, tc.client.ID), - contentType: contentType, - token: tc.token, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("DisableClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - if err == nil { - assert.Equal(t, tc.response.Status, resBody.Status, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.response.Status, resBody.Status)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/%s/disable", ts.URL, tc.domainID, tc.client.ID), + contentType: contentType, + token: tc.token, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("DisableClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + if err == nil { + assert.Equal(t, tc.response.Status, resBody.Status, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.response.Status, resBody.Status)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1461,6 +1566,7 @@ func TestShareThing(t *testing.T) { desc string data string thingID string + domainID string token string contentType string status int @@ -1472,8 +1578,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with valid token", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusCreated, @@ -1483,6 +1590,7 @@ func TestShareThing(t *testing.T) { desc: "share thing with invalid token", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: inValidToken, contentType: contentType, status: http.StatusUnauthorized, @@ -1493,6 +1601,7 @@ func TestShareThing(t *testing.T) { desc: "share thing with empty token", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: "", contentType: contentType, status: http.StatusUnauthorized, @@ -1502,8 +1611,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with empty id", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: " ", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1513,8 +1623,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with missing relation", data: fmt.Sprintf(`{"relation": "%s", user_ids" : ["%s", "%s"]}`, " ", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1524,8 +1635,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with malformed data", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : [%s, "%s"]}`, "editor", "invalid", validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1535,8 +1647,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with empty thing id", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: "", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1546,8 +1659,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with empty relation", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, " ", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1557,8 +1671,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with empty user ids", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : [" ", " "]}`, "editor"), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1568,8 +1683,9 @@ func TestShareThing(t *testing.T) { desc: "share thing with invalid content type", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, @@ -1578,22 +1694,24 @@ func TestShareThing(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/%s/share", ts.URL, tc.thingID), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("Share", mock.Anything, tc.authnRes, tc.thingID, mock.Anything, mock.Anything, mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/%s/share", ts.URL, tc.domainID, tc.thingID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("Share", mock.Anything, tc.authnRes, tc.thingID, mock.Anything, mock.Anything, mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1605,6 +1723,7 @@ func TestUnShareThing(t *testing.T) { desc string data string thingID string + domainID string token string contentType string status int @@ -1616,8 +1735,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with valid token", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusNoContent, @@ -1627,6 +1747,7 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with invalid token", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: inValidToken, contentType: contentType, status: http.StatusUnauthorized, @@ -1637,6 +1758,7 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with empty token", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: "", contentType: contentType, status: http.StatusUnauthorized, @@ -1646,8 +1768,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with empty id", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: " ", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1657,8 +1780,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with missing relation", data: fmt.Sprintf(`{"relation": "%s", user_ids" : ["%s", "%s"]}`, " ", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1668,8 +1792,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with malformed data", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : [%s, "%s"]}`, "editor", "invalid", validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1679,8 +1804,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with empty thing id", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: "", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1690,8 +1816,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with empty relation", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, " ", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1701,8 +1828,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with empty user ids", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : [" ", " "]}`, "editor"), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, @@ -1712,8 +1840,9 @@ func TestUnShareThing(t *testing.T) { desc: "unshare thing with invalid content type", data: fmt.Sprintf(`{"relation": "%s", "user_ids" : ["%s", "%s"]}`, "editor", validID, validID), thingID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, @@ -1722,22 +1851,24 @@ func TestUnShareThing(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/things/%s/unshare", ts.URL, tc.thingID), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("Unshare", mock.Anything, tc.authnRes, tc.thingID, mock.Anything, mock.Anything, mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/things/%s/unshare", ts.URL, tc.domainID, tc.thingID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("Unshare", mock.Anything, tc.authnRes, tc.thingID, mock.Anything, mock.Anything, mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1748,6 +1879,7 @@ func TestDeleteThing(t *testing.T) { cases := []struct { desc string id string + domainID string token string status int authnRes mgauthn.Session @@ -1757,8 +1889,9 @@ func TestDeleteThing(t *testing.T) { { desc: "delete thing with valid token", id: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusNoContent, err: nil, @@ -1766,6 +1899,7 @@ func TestDeleteThing(t *testing.T) { { desc: "delete thing with invalid token", id: client.ID, + domainID: domainID, token: inValidToken, authnRes: mgauthn.Session{}, status: http.StatusUnauthorized, @@ -1773,17 +1907,19 @@ func TestDeleteThing(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "delete thing with empty token", - id: client.ID, - token: "", - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, + desc: "delete thing with empty token", + id: client.ID, + domainID: domainID, + token: "", + status: http.StatusUnauthorized, + err: apiutil.ErrBearerToken, }, { desc: "delete thing with empty id", id: " ", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrMissingID, @@ -1791,20 +1927,22 @@ func TestDeleteThing(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodDelete, - url: fmt.Sprintf("%s/things/%s", ts.URL, tc.id), - token: tc.token, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("DeleteClient", mock.Anything, tc.authnRes, tc.id).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodDelete, + url: fmt.Sprintf("%s/%s/things/%s", ts.URL, tc.domainID, tc.id), + token: tc.token, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("DeleteClient", mock.Anything, tc.authnRes, tc.id).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -1816,6 +1954,7 @@ func TestListMembers(t *testing.T) { desc string query string groupID string + domainID string token string listMembersResponse mgclients.MembersPage status int @@ -1825,8 +1964,9 @@ func TestListMembers(t *testing.T) { }{ { desc: "list members with valid token", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, listMembersResponse: mgclients.MembersPage{ Page: mgclients.Page{ @@ -1839,14 +1979,16 @@ func TestListMembers(t *testing.T) { err: nil, }, { - desc: "list members with empty token", - token: "", - groupID: client.ID, - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, + desc: "list members with empty token", + domainID: domainID, + token: "", + groupID: client.ID, + status: http.StatusUnauthorized, + err: apiutil.ErrBearerToken, }, { desc: "list members with invalid token", + domainID: domainID, token: inValidToken, groupID: client.ID, status: http.StatusUnauthorized, @@ -1855,8 +1997,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with offset", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "offset=1", groupID: client.ID, listMembersResponse: mgclients.MembersPage{ @@ -1872,8 +2015,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with invalid offset", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "offset=invalid", groupID: client.ID, status: http.StatusBadRequest, @@ -1882,8 +2026,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with limit", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "limit=1", groupID: client.ID, listMembersResponse: mgclients.MembersPage{ @@ -1899,8 +2044,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with invalid limit", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "limit=invalid", groupID: client.ID, status: http.StatusBadRequest, @@ -1909,8 +2055,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with limit greater than 100", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), groupID: client.ID, status: http.StatusBadRequest, @@ -1919,8 +2066,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with channel_id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: fmt.Sprintf("channel_id=%s", validID), groupID: client.ID, listMembersResponse: mgclients.MembersPage{ @@ -1935,8 +2083,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with invalid channel_id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "channel_id=invalid", groupID: client.ID, status: http.StatusBadRequest, @@ -1945,8 +2094,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with duplicate channel_id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: fmt.Sprintf("channel_id=%s&channel_id=%s", validID, validID), groupID: client.ID, status: http.StatusBadRequest, @@ -1955,8 +2105,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with connected set", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "connected=true", groupID: client.ID, listMembersResponse: mgclients.MembersPage{ @@ -1971,8 +2122,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with invalid connected set", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "connected=invalid", groupID: client.ID, status: http.StatusBadRequest, @@ -1981,8 +2133,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with duplicate connected set", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "connected=true&connected=false", status: http.StatusBadRequest, @@ -1990,8 +2143,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with empty group id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, query: "", groupID: "", status: http.StatusBadRequest, @@ -2007,8 +2161,9 @@ func TestListMembers(t *testing.T) { }, Members: []mgclients.Client{client}, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusOK, @@ -2017,8 +2172,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with invalid status", query: "status=invalid", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusBadRequest, @@ -2027,8 +2183,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with duplicate status", query: fmt.Sprintf("status=%s&status=%s", mgclients.EnabledStatus, mgclients.DisabledStatus), + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusBadRequest, @@ -2036,8 +2193,9 @@ func TestListMembers(t *testing.T) { }, { desc: "list members with metadata", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, listMembersResponse: mgclients.MembersPage{ Page: mgclients.Page{ Total: 1, @@ -2054,8 +2212,9 @@ func TestListMembers(t *testing.T) { desc: "list members with invalid metadata", query: "metadata=invalid", groupID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -2064,8 +2223,9 @@ func TestListMembers(t *testing.T) { desc: "list members with duplicate metadata", query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&metadata=%7B%22domain%22%3A%20%22example.com%22%7D", groupID: client.ID, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrInvalidQueryParams, @@ -2079,8 +2239,9 @@ func TestListMembers(t *testing.T) { }, Members: []mgclients.Client{client}, }, + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusOK, @@ -2089,8 +2250,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with duplicate permission", query: fmt.Sprintf("permission=%s&permission=%s", "view", "edit"), + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusBadRequest, @@ -2099,8 +2261,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with list permission", query: "list_perms=true", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, listMembersResponse: mgclients.MembersPage{ Page: mgclients.Page{ Total: 1, @@ -2115,8 +2278,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with invalid list permission", query: "list_perms=invalid", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusBadRequest, @@ -2125,8 +2289,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with duplicate list permission", query: "list_perms=true&list_perms=false", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, status: http.StatusBadRequest, @@ -2135,8 +2300,9 @@ func TestListMembers(t *testing.T) { { desc: "list members with all query params", query: fmt.Sprintf("offset=1&limit=1&channel_id=%s&connected=true&status=%s&metadata=%s&permission=%s&list_perms=true", validID, mgclients.EnabledStatus, "%7B%22domain%22%3A%20%22example.com%22%7D", "view"), + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: client.ID, listMembersResponse: mgclients.MembersPage{ Page: mgclients.Page{ @@ -2153,29 +2319,31 @@ func TestListMembers(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodGet, - url: ts.URL + fmt.Sprintf("/channels/%s/things?", tc.groupID) + tc.query, - contentType: contentType, - token: tc.token, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListClientsByGroup", mock.Anything, tc.authnRes, mock.Anything, mock.Anything).Return(tc.listMembersResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - var bodyRes respBody - err = json.NewDecoder(res.Body).Decode(&bodyRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if bodyRes.Err != "" || bodyRes.Message != "" { - err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodGet, + url: ts.URL + fmt.Sprintf("/%s/channels/%s/things?", tc.domainID, tc.groupID) + tc.query, + contentType: contentType, + token: tc.token, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListClientsByGroup", mock.Anything, tc.authnRes, mock.Anything, mock.Anything).Return(tc.listMembersResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + + var bodyRes respBody + err = json.NewDecoder(res.Body).Decode(&bodyRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if bodyRes.Err != "" || bodyRes.Message != "" { + err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2185,6 +2353,7 @@ func TestAssignUsers(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -2196,8 +2365,9 @@ func TestAssignUsers(t *testing.T) { }{ { desc: "assign users to a group successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -2210,6 +2380,7 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with invalid token", + domainID: domainID, token: inValidToken, authnRes: mgauthn.Session{}, groupID: validID, @@ -2223,9 +2394,10 @@ func TestAssignUsers(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "assign users to a group with empty token", - token: "", - groupID: validID, + desc: "assign users to a group with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2237,7 +2409,7 @@ func TestAssignUsers(t *testing.T) { { desc: "assign users to a group with empty group id", token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: "", reqBody: groupReqBody{ Relation: "member", @@ -2250,8 +2422,9 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with empty relation", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "", @@ -2264,8 +2437,9 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with empty user ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -2278,8 +2452,9 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with invalid request body", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: map[string]interface{}{ "relation": make(chan int), @@ -2291,8 +2466,9 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with invalid content type", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -2306,23 +2482,25 @@ func TestAssignUsers(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/channels/%s/users/assign", ts.URL, tc.groupID), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/channels/%s/users/assign", ts.URL, tc.domainID, tc.groupID), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2332,6 +2510,7 @@ func TestUnassignUsers(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -2343,8 +2522,9 @@ func TestUnassignUsers(t *testing.T) { }{ { desc: "unassign users from a group successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -2356,9 +2536,10 @@ func TestUnassignUsers(t *testing.T) { err: nil, }, { - desc: "unassign users from a group with invalid token", - token: inValidToken, - groupID: validID, + desc: "unassign users from a group with invalid token", + domainID: domainID, + token: inValidToken, + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2369,9 +2550,10 @@ func TestUnassignUsers(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "unassign users from a group with empty token", - token: "", - groupID: validID, + desc: "unassign users from a group with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2382,8 +2564,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with empty group id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: "", reqBody: groupReqBody{ Relation: "member", @@ -2396,8 +2579,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with empty relation", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "", @@ -2410,8 +2594,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with empty user ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -2424,8 +2609,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with invalid request body", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: map[string]interface{}{ "relation": make(chan int), @@ -2437,8 +2623,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with invalid content type", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -2452,23 +2639,25 @@ func TestUnassignUsers(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/channels/%s/users/unassign", ts.URL, tc.groupID), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/channels/%s/users/unassign", ts.URL, tc.domainID, tc.groupID), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2478,6 +2667,7 @@ func TestAssignGroupsToChannel(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -2489,8 +2679,9 @@ func TestAssignGroupsToChannel(t *testing.T) { }{ { desc: "assign groups to a channel successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2501,9 +2692,10 @@ func TestAssignGroupsToChannel(t *testing.T) { err: nil, }, { - desc: "assign groups to a channel with invalid token", - token: inValidToken, - groupID: validID, + desc: "assign groups to a channel with invalid token", + domainID: domainID, + token: inValidToken, + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -2513,9 +2705,10 @@ func TestAssignGroupsToChannel(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "assign groups to a channel with empty token", - token: "", - groupID: validID, + desc: "assign groups to a channel with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -2525,8 +2718,9 @@ func TestAssignGroupsToChannel(t *testing.T) { }, { desc: "assign groups to a channel with empty group id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: "", reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2538,8 +2732,9 @@ func TestAssignGroupsToChannel(t *testing.T) { }, { desc: "assign groups to a channel with empty group ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{}, @@ -2551,8 +2746,9 @@ func TestAssignGroupsToChannel(t *testing.T) { }, { desc: "assign groups to a channel with invalid request body", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: map[string]interface{}{ "group_ids": make(chan int), @@ -2564,8 +2760,9 @@ func TestAssignGroupsToChannel(t *testing.T) { }, { desc: "assign groups to a channel with invalid content type", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2578,23 +2775,25 @@ func TestAssignGroupsToChannel(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/channels/%s/groups/assign", ts.URL, tc.groupID), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "channels", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/channels/%s/groups/assign", ts.URL, tc.domainID, tc.groupID), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "channels", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2604,6 +2803,7 @@ func TestUnassignGroupsFromChannel(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -2615,8 +2815,9 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }{ { desc: "unassign groups from a channel successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2628,6 +2829,7 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }, { desc: "unassign groups from a channel with invalid token", + domainID: domainID, token: inValidToken, authnRes: mgauthn.Session{}, groupID: validID, @@ -2640,9 +2842,10 @@ func TestUnassignGroupsFromChannel(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "unassign groups from a channel with empty token", - token: "", - groupID: validID, + desc: "unassign groups from a channel with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -2652,8 +2855,9 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }, { desc: "unassign groups from a channel with empty group id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: "", reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2665,8 +2869,9 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }, { desc: "unassign groups from a channel with empty group ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{}, @@ -2678,8 +2883,9 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }, { desc: "unassign groups from a channel with invalid request body", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: map[string]interface{}{ "group_ids": make(chan int), @@ -2691,8 +2897,9 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }, { desc: "unassign groups from a channel with invalid content type", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -2704,23 +2911,25 @@ func TestUnassignGroupsFromChannel(t *testing.T) { }, } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/channels/%s/groups/unassign", ts.URL, tc.groupID), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "channels", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/channels/%s/groups/unassign", ts.URL, tc.domainID, tc.groupID), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "channels", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2730,6 +2939,7 @@ func TestConnectThingToChannel(t *testing.T) { cases := []struct { desc string + domainID string token string channelID string thingID string @@ -2741,17 +2951,18 @@ func TestConnectThingToChannel(t *testing.T) { }{ { desc: "connect thing to a channel successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, channelID: validID, thingID: validID, contentType: contentType, status: http.StatusCreated, - - err: nil, + err: nil, }, { desc: "connect thing to a channel with invalid token", + domainID: domainID, token: inValidToken, channelID: validID, thingID: validID, @@ -2762,7 +2973,9 @@ func TestConnectThingToChannel(t *testing.T) { }, { desc: "connect thing to a channel with empty channel id", + domainID: domainID, token: validToken, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, channelID: "", thingID: validID, contentType: contentType, @@ -2771,32 +2984,34 @@ func TestConnectThingToChannel(t *testing.T) { }, { desc: "connect thing to a channel with empty thing id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, channelID: validID, thingID: "", contentType: contentType, status: http.StatusBadRequest, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/channels/%s/things/%s/connect", ts.URL, tc.channelID, tc.thingID), - token: tc.token, - contentType: tc.contentType, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.channelID, "group", "things", []string{tc.thingID}).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/channels/%s/things/%s/connect", ts.URL, tc.domainID, tc.channelID, tc.thingID), + token: tc.token, + contentType: tc.contentType, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.channelID, "group", "things", []string{tc.thingID}).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2806,6 +3021,7 @@ func TestDisconnectThingFromChannel(t *testing.T) { cases := []struct { desc string + domainID string token string channelID string thingID string @@ -2817,8 +3033,9 @@ func TestDisconnectThingFromChannel(t *testing.T) { }{ { desc: "disconnect thing from a channel successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, channelID: validID, thingID: validID, contentType: contentType, @@ -2828,6 +3045,7 @@ func TestDisconnectThingFromChannel(t *testing.T) { }, { desc: "disconnect thing from a channel with invalid token", + domainID: domainID, token: inValidToken, channelID: validID, thingID: validID, @@ -2838,8 +3056,9 @@ func TestDisconnectThingFromChannel(t *testing.T) { }, { desc: "disconnect thing from a channel with empty channel id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, channelID: "", thingID: validID, contentType: contentType, @@ -2849,33 +3068,35 @@ func TestDisconnectThingFromChannel(t *testing.T) { }, { desc: "disconnect thing from a channel with empty thing id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, channelID: validID, thingID: "", contentType: contentType, status: http.StatusBadRequest, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, } for _, tc := range cases { - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/channels/%s/things/%s/disconnect", ts.URL, tc.channelID, tc.thingID), - token: tc.token, - contentType: tc.contentType, - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.channelID, "group", "things", []string{tc.thingID}).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/channels/%s/things/%s/disconnect", ts.URL, tc.domainID, tc.channelID, tc.thingID), + token: tc.token, + contentType: tc.contentType, + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.channelID, "group", "things", []string{tc.thingID}).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2885,6 +3106,7 @@ func TestConnect(t *testing.T) { cases := []struct { desc string + domainID string token string reqBody interface{} contentType string @@ -2895,8 +3117,9 @@ func TestConnect(t *testing.T) { }{ { desc: "connect thing to a channel successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: validID, ThingID: validID, @@ -2907,8 +3130,9 @@ func TestConnect(t *testing.T) { err: nil, }, { - desc: "connect thing to a channel with invalid token", - token: inValidToken, + desc: "connect thing to a channel with invalid token", + domainID: domainID, + token: inValidToken, reqBody: groupReqBody{ ChannelID: validID, ThingID: validID, @@ -2920,8 +3144,9 @@ func TestConnect(t *testing.T) { }, { desc: "connect thing to a channel with empty channel id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: "", ThingID: validID, @@ -2933,8 +3158,9 @@ func TestConnect(t *testing.T) { }, { desc: "connect thing to a channel with empty thing id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: validID, ThingID: "", @@ -2946,8 +3172,9 @@ func TestConnect(t *testing.T) { }, { desc: "connect thing to a channel with invalid request body", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: map[string]interface{}{ "channel_id": make(chan int), }, @@ -2958,37 +3185,39 @@ func TestConnect(t *testing.T) { }, { desc: "connect thing to a channel with invalid content type", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: validID, ThingID: validID, }, contentType: "application/xml", status: http.StatusUnsupportedMediaType, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/connect", ts.URL), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, mock.Anything, "group", "things", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/connect", ts.URL, tc.domainID), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, mock.Anything, "group", "things", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } @@ -2998,6 +3227,7 @@ func TestDisconnect(t *testing.T) { cases := []struct { desc string + domainID string token string reqBody interface{} contentType string @@ -3008,8 +3238,9 @@ func TestDisconnect(t *testing.T) { }{ { desc: "Disconnect thing from a channel successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: validID, ThingID: validID, @@ -3021,6 +3252,7 @@ func TestDisconnect(t *testing.T) { }, { desc: "Disconnect thing from a channel with invalid token", + domainID: domainID, token: inValidToken, authnRes: mgauthn.Session{}, reqBody: groupReqBody{ @@ -3034,8 +3266,9 @@ func TestDisconnect(t *testing.T) { }, { desc: "Disconnect thing from a channel with empty channel id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: "", ThingID: validID, @@ -3047,61 +3280,63 @@ func TestDisconnect(t *testing.T) { }, { desc: "Disconnect thing from a channel with empty thing id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: validID, ThingID: "", }, contentType: contentType, status: http.StatusBadRequest, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, { desc: "Disconnect thing from a channel with invalid request body", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: map[string]interface{}{ "channel_id": make(chan int), }, contentType: contentType, status: http.StatusBadRequest, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, { desc: "Disconnect thing from a channel with invalid content type", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, reqBody: groupReqBody{ ChannelID: validID, ThingID: validID, }, contentType: "application/xml", status: http.StatusUnsupportedMediaType, - - err: apiutil.ErrValidation, + err: apiutil.ErrValidation, }, } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: ts.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/disconnect", ts.URL), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(data), - } - - authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, mock.Anything, "group", "things", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: ts.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/disconnect", ts.URL, tc.domainID), + token: tc.token, + contentType: tc.contentType, + body: strings.NewReader(data), + } + + authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, mock.Anything, "group", "things", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authCall.Unset() + }) } } diff --git a/things/api/http/requests.go b/things/api/http/requests.go index 26fefe96cf..4d13f6e092 100644 --- a/things/api/http/requests.go +++ b/things/api/http/requests.go @@ -54,6 +54,7 @@ func (req viewClientReq) validate() error { if req.id == "" { return apiutil.ErrMissingID } + return nil } @@ -65,6 +66,7 @@ func (req viewClientPermsReq) validate() error { if req.id == "" { return apiutil.ErrMissingID } + return nil } @@ -123,6 +125,7 @@ func (req updateClientReq) validate() error { if req.id == "" { return apiutil.ErrMissingID } + if len(req.Name) > api.MaxNameSize { return apiutil.ErrNameSize } @@ -152,6 +155,7 @@ func (req updateClientCredentialsReq) validate() error { if req.id == "" { return apiutil.ErrMissingID } + if req.Secret == "" { return apiutil.ErrMissingSecret } @@ -246,5 +250,6 @@ func (req deleteClientReq) validate() error { if req.id == "" { return apiutil.ErrMissingID } + return nil } diff --git a/things/api/http/requests_test.go b/things/api/http/requests_test.go index 4b3f1fceec..9f216794db 100644 --- a/things/api/http/requests_test.go +++ b/things/api/http/requests_test.go @@ -60,8 +60,10 @@ func TestCreateThingReqValidate(t *testing.T) { }, } for _, tc := range cases { - err := tc.req.validate() - assert.Equal(t, tc.err, err) + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err) + }) } } @@ -115,9 +117,11 @@ func TestCreateThingsReqValidate(t *testing.T) { err: apiutil.ErrInvalidIDFormat, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -142,9 +146,11 @@ func TestViewClientReqValidate(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -169,9 +175,11 @@ func TestViewClientPermsReq(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -219,9 +227,11 @@ func TestListClientsReqValidate(t *testing.T) { err: apiutil.ErrNameSize, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -246,9 +256,11 @@ func TestListMembersReqValidate(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -283,9 +295,11 @@ func TestUpdateClientReqValidate(t *testing.T) { err: apiutil.ErrNameSize, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -312,9 +326,11 @@ func TestUpdateClientTagsReqValidate(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -349,9 +365,11 @@ func TestUpdateClientCredentialsReqValidate(t *testing.T) { err: apiutil.ErrMissingSecret, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -376,9 +394,11 @@ func TestChangeClientStatusReqValidate(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -425,9 +445,11 @@ func TestAssignUsersRequestValidate(t *testing.T) { 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -462,9 +484,11 @@ func TestAssignUserGroupsRequestValidate(t *testing.T) { err: apiutil.ErrEmptyList, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -499,9 +523,11 @@ func TestConnectChannelThingRequestValidate(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -548,9 +574,11 @@ func TestThingShareRequestValidate(t *testing.T) { err: apiutil.ErrMalformedPolicy, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } @@ -575,8 +603,10 @@ func TestDeleteClientReqValidate(t *testing.T) { err: apiutil.ErrMissingID, }, } - 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) + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := tc.req.validate() + assert.Equal(t, tc.err, err, "%s: expected %s got %s\n", tc.desc, tc.err, err) + }) } } diff --git a/tools/e2e/e2e.go b/tools/e2e/e2e.go index e72c1259f9..e40238cf04 100644 --- a/tools/e2e/e2e.go +++ b/tools/e2e/e2e.go @@ -77,7 +77,7 @@ func Test(conf Config) { magenta := color.FgLightMagenta.Render - token, err := createUser(s, conf) + domainID, token, err := createUser(s, conf) if err != nil { errExit(fmt.Errorf("unable to create user: %w", err)) } @@ -89,38 +89,38 @@ func Test(conf Config) { } color.Success.Printf("created users of ids:\n%s\n", magenta(getIDS(users))) - groups, err := createGroups(s, conf, token) + groups, err := createGroups(s, conf, domainID, token) if err != nil { errExit(fmt.Errorf("unable to create groups: %w", err)) } color.Success.Printf("created groups of ids:\n%s\n", magenta(getIDS(groups))) - things, err := createThings(s, conf, token) + things, err := createThings(s, conf, domainID, token) if err != nil { errExit(fmt.Errorf("unable to create things: %w", err)) } color.Success.Printf("created things of ids:\n%s\n", magenta(getIDS(things))) - channels, err := createChannels(s, conf, token) + channels, err := createChannels(s, conf, domainID, token) if err != nil { errExit(fmt.Errorf("unable to create channels: %w", err)) } color.Success.Printf("created channels of ids:\n%s\n", magenta(getIDS(channels))) // List users, groups, things and channels - if err := read(s, conf, token, users, groups, things, channels); err != nil { + if err := read(s, conf, domainID, token, users, groups, things, channels); err != nil { errExit(fmt.Errorf("unable to read users, groups, things and channels: %w", err)) } color.Success.Println("viewed users, groups, things and channels") // Update users, groups, things and channels - if err := update(s, token, users, groups, things, channels); err != nil { + if err := update(s, domainID, token, users, groups, things, channels); err != nil { errExit(fmt.Errorf("unable to update users, groups, things and channels: %w", err)) } color.Success.Println("updated users, groups, things and channels") // Send messages to channels - if err := messaging(s, conf, token, things, channels); err != nil { + if err := messaging(s, conf, domainID, token, things, channels); err != nil { errExit(fmt.Errorf("unable to send messages to channels: %w", err)) } color.Success.Println("sent messages to channels") @@ -131,7 +131,7 @@ func errExit(err error) { os.Exit(1) } -func createUser(s sdk.SDK, conf Config) (string, error) { +func createUser(s sdk.SDK, conf Config) (string, string, error) { user := sdk.User{ Name: fmt.Sprintf("%s%s", conf.Prefix, namesgenerator.Generate()), Credentials: sdk.Credentials{ @@ -143,7 +143,7 @@ func createUser(s sdk.SDK, conf Config) (string, error) { } if _, err := s.CreateUser(user, ""); err != nil { - return "", fmt.Errorf("unable to create user: %w", err) + return "", "", fmt.Errorf("unable to create user: %w", err) } login := sdk.Login{ @@ -152,7 +152,7 @@ func createUser(s sdk.SDK, conf Config) (string, error) { } token, err := s.CreateToken(login) if err != nil { - return "", fmt.Errorf("unable to login user: %w", err) + return "", "", fmt.Errorf("unable to login user: %w", err) } dname := fmt.Sprintf("%s%s", conf.Prefix, namesgenerator.Generate()) @@ -164,7 +164,7 @@ func createUser(s sdk.SDK, conf Config) (string, error) { domain, err = s.CreateDomain(domain, token.AccessToken) if err != nil { - return "", fmt.Errorf("unable to create domain: %w", err) + return "", "", fmt.Errorf("unable to create domain: %w", err) } login = sdk.Login{ @@ -174,10 +174,10 @@ func createUser(s sdk.SDK, conf Config) (string, error) { } token, err = s.CreateToken(login) if err != nil { - return "", fmt.Errorf("unable to login user: %w", err) + return "", "", fmt.Errorf("unable to login user: %w", err) } - return token.AccessToken, nil + return domain.ID, token.AccessToken, nil } func createUsers(s sdk.SDK, conf Config, token string) ([]sdk.User, error) { @@ -204,7 +204,7 @@ func createUsers(s sdk.SDK, conf Config, token string) ([]sdk.User, error) { return users, nil } -func createGroups(s sdk.SDK, conf Config, token string) ([]sdk.Group, error) { +func createGroups(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Group, error) { var err error groups := []sdk.Group{} @@ -214,7 +214,7 @@ func createGroups(s sdk.SDK, conf Config, token string) ([]sdk.Group, error) { Status: sdk.EnabledStatus, } - group, err = s.CreateGroup(group, token) + group, err = s.CreateGroup(group, domainID, token) if err != nil { return []sdk.Group{}, fmt.Errorf("failed to create the group: %w", err) } @@ -224,7 +224,7 @@ func createGroups(s sdk.SDK, conf Config, token string) ([]sdk.Group, error) { return groups, nil } -func createThingsInBatch(s sdk.SDK, conf Config, token string, num uint64) ([]sdk.Thing, error) { +func createThingsInBatch(s sdk.SDK, conf Config, domainID, token string, num uint64) ([]sdk.Thing, error) { var err error things := make([]sdk.Thing, num) @@ -234,7 +234,7 @@ func createThingsInBatch(s sdk.SDK, conf Config, token string, num uint64) ([]sd } } - things, err = s.CreateThings(things, token) + things, err = s.CreateThings(things, domainID, token) if err != nil { return []sdk.Thing{}, fmt.Errorf("failed to create the things: %w", err) } @@ -242,25 +242,25 @@ func createThingsInBatch(s sdk.SDK, conf Config, token string, num uint64) ([]sd return things, nil } -func createThings(s sdk.SDK, conf Config, token string) ([]sdk.Thing, error) { +func createThings(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Thing, error) { things := []sdk.Thing{} if conf.Num > batchSize { batches := int(conf.Num) / batchSize for i := 0; i < batches; i++ { - ths, err := createThingsInBatch(s, conf, token, batchSize) + ths, err := createThingsInBatch(s, conf, domainID, token, batchSize) if err != nil { return []sdk.Thing{}, fmt.Errorf("Failed to create the things: %w", err) } things = append(things, ths...) } - ths, err := createThingsInBatch(s, conf, token, conf.Num%uint64(batchSize)) + ths, err := createThingsInBatch(s, conf, domainID, token, conf.Num%uint64(batchSize)) if err != nil { return []sdk.Thing{}, fmt.Errorf("Failed to create the things: %w", err) } things = append(things, ths...) } else { - ths, err := createThingsInBatch(s, conf, token, conf.Num) + ths, err := createThingsInBatch(s, conf, domainID, token, conf.Num) if err != nil { return []sdk.Thing{}, fmt.Errorf("Failed to create the things: %w", err) } @@ -270,7 +270,7 @@ func createThings(s sdk.SDK, conf Config, token string) ([]sdk.Thing, error) { return things, nil } -func createChannelsInBatch(s sdk.SDK, conf Config, token string, num uint64) ([]sdk.Channel, error) { +func createChannelsInBatch(s sdk.SDK, conf Config, domainID, token string, num uint64) ([]sdk.Channel, error) { var err error channels := make([]sdk.Channel, num) @@ -278,7 +278,7 @@ func createChannelsInBatch(s sdk.SDK, conf Config, token string, num uint64) ([] channels[i] = sdk.Channel{ Name: fmt.Sprintf("%s%s", conf.Prefix, namesgenerator.Generate()), } - channels[i], err = s.CreateChannel(channels[i], token) + channels[i], err = s.CreateChannel(channels[i], domainID, token) if err != nil { return []sdk.Channel{}, fmt.Errorf("failed to create the channels: %w", err) } @@ -287,25 +287,25 @@ func createChannelsInBatch(s sdk.SDK, conf Config, token string, num uint64) ([] return channels, nil } -func createChannels(s sdk.SDK, conf Config, token string) ([]sdk.Channel, error) { +func createChannels(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Channel, error) { channels := []sdk.Channel{} if conf.Num > batchSize { batches := int(conf.Num) / batchSize for i := 0; i < batches; i++ { - chs, err := createChannelsInBatch(s, conf, token, batchSize) + chs, err := createChannelsInBatch(s, conf, token, domainID, batchSize) if err != nil { return []sdk.Channel{}, fmt.Errorf("Failed to create the channels: %w", err) } channels = append(channels, chs...) } - chs, err := createChannelsInBatch(s, conf, token, conf.Num%uint64(batchSize)) + chs, err := createChannelsInBatch(s, conf, domainID, token, conf.Num%uint64(batchSize)) if err != nil { return []sdk.Channel{}, fmt.Errorf("Failed to create the channels: %w", err) } channels = append(channels, chs...) } else { - chs, err := createChannelsInBatch(s, conf, token, conf.Num) + chs, err := createChannelsInBatch(s, conf, domainID, token, conf.Num) if err != nil { return []sdk.Channel{}, fmt.Errorf("Failed to create the channels: %w", err) } @@ -315,7 +315,7 @@ func createChannels(s sdk.SDK, conf Config, token string) ([]sdk.Channel, error) return channels, nil } -func read(s sdk.SDK, conf Config, token string, users []sdk.User, groups []sdk.Group, things []sdk.Thing, channels []sdk.Channel) error { +func read(s sdk.SDK, conf Config, domainID, token string, users []sdk.User, groups []sdk.Group, things []sdk.Thing, channels []sdk.Channel) error { for _, user := range users { if _, err := s.User(user.ID, token); err != nil { return fmt.Errorf("failed to get user %w", err) @@ -329,7 +329,7 @@ func read(s sdk.SDK, conf Config, token string, users []sdk.User, groups []sdk.G return fmt.Errorf("returned users %d less than created users %d", up.Total, conf.Num) } for _, group := range groups { - if _, err := s.Group(group.ID, token); err != nil { + if _, err := s.Group(group.ID, domainID, token); err != nil { return fmt.Errorf("failed to get group %w", err) } } @@ -341,7 +341,7 @@ func read(s sdk.SDK, conf Config, token string, users []sdk.User, groups []sdk.G return fmt.Errorf("returned groups %d less than created groups %d", gp.Total, conf.Num) } for _, thing := range things { - if _, err := s.Thing(thing.ID, token); err != nil { + if _, err := s.Thing(thing.ID, domainID, token); err != nil { return fmt.Errorf("failed to get thing %w", err) } } @@ -353,11 +353,13 @@ func read(s sdk.SDK, conf Config, token string, users []sdk.User, groups []sdk.G return fmt.Errorf("returned things %d less than created things %d", tp.Total, conf.Num) } for _, channel := range channels { - if _, err := s.Channel(channel.ID, token); err != nil { + if _, err := s.Channel(channel.ID, domainID, token); err != nil { return fmt.Errorf("failed to get channel %w", err) } } - cp, err := s.Channels(sdk.PageMetadata{}, token) + cp, err := s.Channels(sdk.PageMetadata{ + DomainID: domainID, + }, token) if err != nil { return fmt.Errorf("failed to get channels %w", err) } @@ -368,7 +370,7 @@ func read(s sdk.SDK, conf Config, token string, users []sdk.User, groups []sdk.G return nil } -func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, things []sdk.Thing, channels []sdk.Channel) error { +func update(s sdk.SDK, domainID, token string, users []sdk.User, groups []sdk.Group, things []sdk.Thing, channels []sdk.Channel) error { for _, user := range users { user.Name = namesgenerator.Generate() user.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()} @@ -420,7 +422,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing for _, group := range groups { group.Name = namesgenerator.Generate() group.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()} - rGroup, err := s.UpdateGroup(group, token) + rGroup, err := s.UpdateGroup(group, domainID, token) if err != nil { return fmt.Errorf("failed to update group %w", err) } @@ -431,7 +433,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to update group metadata before %s after %s", group.Metadata["Update"], rGroup.Metadata["Update"]) } group = rGroup - rGroup, err = s.DisableGroup(group.ID, token) + rGroup, err = s.DisableGroup(group.ID, domainID, token) if err != nil { return fmt.Errorf("failed to disable group %w", err) } @@ -439,7 +441,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to disable group before %s after %s", group.Status, rGroup.Status) } group = rGroup - rGroup, err = s.EnableGroup(group.ID, token) + rGroup, err = s.EnableGroup(group.ID, domainID, token) if err != nil { return fmt.Errorf("failed to enable group %w", err) } @@ -450,7 +452,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing for _, thing := range things { thing.Name = namesgenerator.Generate() thing.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()} - rThing, err := s.UpdateThing(thing, token) + rThing, err := s.UpdateThing(thing, domainID, token) if err != nil { return fmt.Errorf("failed to update thing %w", err) } @@ -461,13 +463,13 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to update thing metadata before %s after %s", thing.Metadata["Update"], rThing.Metadata["Update"]) } thing = rThing - rThing, err = s.UpdateThingSecret(thing.ID, thing.Credentials.Secret, token) + rThing, err = s.UpdateThingSecret(thing.ID, thing.Credentials.Secret, domainID, token) if err != nil { return fmt.Errorf("failed to update thing secret %w", err) } thing = rThing thing.Tags = []string{namesgenerator.Generate()} - rThing, err = s.UpdateThingTags(thing, token) + rThing, err = s.UpdateThingTags(thing, domainID, token) if err != nil { return fmt.Errorf("failed to update thing tags %w", err) } @@ -475,7 +477,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to update thing tags before %s after %s", thing.Tags[0], rThing.Tags[0]) } thing = rThing - rThing, err = s.DisableThing(thing.ID, token) + rThing, err = s.DisableThing(thing.ID, domainID, token) if err != nil { return fmt.Errorf("failed to disable thing %w", err) } @@ -483,7 +485,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to disable thing before %s after %s", thing.Status, rThing.Status) } thing = rThing - rThing, err = s.EnableThing(thing.ID, token) + rThing, err = s.EnableThing(thing.ID, domainID, token) if err != nil { return fmt.Errorf("failed to enable thing %w", err) } @@ -494,7 +496,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing for _, channel := range channels { channel.Name = namesgenerator.Generate() channel.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()} - rChannel, err := s.UpdateChannel(channel, token) + rChannel, err := s.UpdateChannel(channel, domainID, token) if err != nil { return fmt.Errorf("failed to update channel %w", err) } @@ -505,7 +507,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to update channel metadata before %s after %s", channel.Metadata["Update"], rChannel.Metadata["Update"]) } channel = rChannel - rChannel, err = s.DisableChannel(channel.ID, token) + rChannel, err = s.DisableChannel(channel.ID, domainID, token) if err != nil { return fmt.Errorf("failed to disable channel %w", err) } @@ -513,7 +515,7 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return fmt.Errorf("failed to disable channel before %s after %s", channel.Status, rChannel.Status) } channel = rChannel - rChannel, err = s.EnableChannel(channel.ID, token) + rChannel, err = s.EnableChannel(channel.ID, domainID, token) if err != nil { return fmt.Errorf("failed to enable channel %w", err) } @@ -525,14 +527,14 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing return nil } -func messaging(s sdk.SDK, conf Config, token string, things []sdk.Thing, channels []sdk.Channel) error { +func messaging(s sdk.SDK, conf Config, domainID, token string, things []sdk.Thing, channels []sdk.Channel) error { for _, thing := range things { for _, channel := range channels { conn := sdk.Connection{ ThingID: thing.ID, ChannelID: channel.ID, } - if err := s.Connect(conn, token); err != nil { + if err := s.Connect(conn, domainID, token); err != nil { return fmt.Errorf("failed to connect thing %s to channel %s", thing.ID, channel.ID) } } diff --git a/tools/provision/provision.go b/tools/provision/provision.go index c4dbe454f0..dcddda660b 100644 --- a/tools/provision/provision.go +++ b/tools/provision/provision.go @@ -17,6 +17,7 @@ import ( "log" "math/big" "os" + "strings" "time" "github.com/0x6flab/namegenerator" @@ -97,6 +98,28 @@ func Provision(conf Config) error { return fmt.Errorf("unable to login user: %s", err.Error()) } + // Create new domain + dname := fmt.Sprintf("%s%s", conf.Prefix, namesgenerator.Generate()) + domain := sdk.Domain{ + Name: dname, + Alias: strings.ToLower(dname), + Permission: "admin", + } + + domain, err = s.CreateDomain(domain, token.AccessToken) + if err != nil { + return fmt.Errorf("unable to create domain: %w", err) + } + // Login to domain + token, err = s.CreateToken(sdk.Login{ + Identity: user.Credentials.Identity, + Secret: user.Credentials.Secret, + DomainID: domain.ID, + }) + if err != nil { + return fmt.Errorf("unable to login user: %w", err) + } + var tlsCert tls.Certificate var caCert *x509.Certificate @@ -135,14 +158,14 @@ func Provision(conf Config) error { channels[i] = sdk.Channel{Name: fmt.Sprintf("%s-channel-%d", conf.Prefix, i)} } - things, err = s.CreateThings(things, token.AccessToken) + things, err = s.CreateThings(things, domain.ID, token.AccessToken) if err != nil { return fmt.Errorf("failed to create the things: %s", err.Error()) } var chs []sdk.Channel for _, c := range channels { - c, err = s.CreateChannel(c, token.AccessToken) + c, err = s.CreateChannel(c, domain.ID, token.AccessToken) if err != nil { return fmt.Errorf("failed to create the chennels: %s", err.Error()) } @@ -237,7 +260,7 @@ func Provision(conf Config) error { ThingID: tID, ChannelID: cID, } - if err := s.Connect(conIDs, token.AccessToken); err != nil { + if err := s.Connect(conIDs, domain.ID, token.AccessToken); err != nil { log.Fatalf("Failed to connect things %s to channels %s: %s", tID, cID, err) } } diff --git a/users/api/clients.go b/users/api/clients.go index 6dd8aaca2f..9701ece634 100644 --- a/users/api/clients.go +++ b/users/api/clients.go @@ -120,6 +120,13 @@ func clientsHandler(svc users.Service, authn mgauthn.Authentication, tokenClient opts..., ), "update_client_role").ServeHTTP) + r.Patch("/{id}/role", otelhttp.NewHandler(kithttp.NewServer( + updateClientRoleEndpoint(svc), + decodeUpdateClientRole, + api.EncodeResponse, + opts..., + ), "update_client_role").ServeHTTP) + r.Post("/{id}/enable", otelhttp.NewHandler(kithttp.NewServer( enableClientEndpoint(svc), decodeChangeClientStatus, @@ -164,7 +171,7 @@ func clientsHandler(svc users.Service, authn mgauthn.Authentication, tokenClient // 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("/groups/{groupID}/users", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/groups/{groupID}/users", otelhttp.NewHandler(kithttp.NewServer( listMembersByGroupEndpoint(svc), decodeListMembersByGroup, api.EncodeResponse, @@ -176,21 +183,21 @@ func clientsHandler(svc users.Service, authn mgauthn.Authentication, tokenClient // 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("/channels/{channelID}/users", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/channels/{channelID}/users", otelhttp.NewHandler(kithttp.NewServer( listMembersByChannelEndpoint(svc), decodeListMembersByChannel, api.EncodeResponse, opts..., ), "list_users_by_channel_id").ServeHTTP) - r.Get("/things/{thingID}/users", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/things/{thingID}/users", otelhttp.NewHandler(kithttp.NewServer( listMembersByThingEndpoint(svc), decodeListMembersByThing, api.EncodeResponse, opts..., ), "list_users_by_thing_id").ServeHTTP) - r.Get("/domains/{domainID}/users", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/users", otelhttp.NewHandler(kithttp.NewServer( listMembersByDomainEndpoint(svc), decodeListMembersByDomain, api.EncodeResponse, diff --git a/users/api/endpoint_test.go b/users/api/endpoint_test.go index 461fc8da22..d7095f2bd9 100644 --- a/users/api/endpoint_test.go +++ b/users/api/endpoint_test.go @@ -50,6 +50,7 @@ var ( validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" passRegex = regexp.MustCompile("^.{8,}$") testReferer = "http://localhost" + domainID = testsutil.GenerateUUID(&testing.T{}) ) const contentType = "application/json" @@ -219,28 +220,30 @@ func TestRegisterClient(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/users/", us.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(data), - } - - svcCall := svc.On("RegisterClient", mock.Anything, mgauthn.Session{}, tc.client, true).Return(tc.client, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/users/", us.URL), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(data), + } + + svcCall := svc.On("RegisterClient", mock.Anything, mgauthn.Session{}, tc.client, true).Return(tc.client, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + }) } } @@ -262,7 +265,7 @@ func TestViewClient(t *testing.T) { token: validToken, id: client.ID, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -288,33 +291,35 @@ func TestViewClient(t *testing.T) { token: validToken, id: client.ID, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/users/%s", us.URL, tc.id), - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ViewClient", mock.Anything, tc.authnRes, tc.id).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/users/%s", us.URL, tc.id), + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ViewClient", mock.Anything, tc.authnRes, tc.id).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -336,7 +341,7 @@ func TestViewProfile(t *testing.T) { token: validToken, id: client.ID, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -360,27 +365,29 @@ func TestViewProfile(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/users/profile", us.URL), - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ViewProfile", mock.Anything, tc.authnRes).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var errRes respBody - err = json.NewDecoder(res.Body).Decode(&errRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if errRes.Err != "" || errRes.Message != "" { - err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/users/profile", us.URL), + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ViewProfile", mock.Anything, tc.authnRes).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var errRes respBody + err = json.NewDecoder(res.Body).Decode(&errRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if errRes.Err != "" || errRes.Message != "" { + err = errors.Wrap(errors.New(errRes.Err), errors.New(errRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -408,7 +415,7 @@ func TestListClients(t *testing.T) { }, Clients: []mgclients.Client{client}, }, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -439,7 +446,7 @@ func TestListClients(t *testing.T) { }, query: "offset=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -447,7 +454,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "offset=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -462,7 +469,7 @@ func TestListClients(t *testing.T) { }, query: "limit=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -470,7 +477,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "limit=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -478,7 +485,7 @@ func TestListClients(t *testing.T) { token: validToken, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -492,7 +499,7 @@ func TestListClients(t *testing.T) { }, query: "name=clientname", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -500,7 +507,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "name=1&name=2", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -514,7 +521,7 @@ func TestListClients(t *testing.T) { }, query: "status=enabled", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -522,7 +529,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "status=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -530,7 +537,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "status=enabled&status=disabled", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -544,7 +551,7 @@ func TestListClients(t *testing.T) { }, query: "tag=tag1,tag2", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -552,7 +559,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "tag=tag1&tag=tag2", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -566,7 +573,7 @@ func TestListClients(t *testing.T) { }, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -574,7 +581,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "metadata=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -582,7 +589,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&metadata=%7B%22domain%22%3A%20%22example.com%22%7D", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -596,7 +603,7 @@ func TestListClients(t *testing.T) { }, query: "permission=view", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -604,7 +611,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "permission=view&permission=view", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -618,7 +625,7 @@ func TestListClients(t *testing.T) { }, query: "list_perms=true", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -626,7 +633,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "list_perms=true&list_perms=true", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -642,7 +649,7 @@ func TestListClients(t *testing.T) { }, }, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -650,7 +657,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "identity=1&identity=2", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -666,7 +673,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "order=name", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -674,7 +681,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "order=name&order=name", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -682,7 +689,7 @@ func TestListClients(t *testing.T) { token: validToken, query: "dir=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -690,34 +697,36 @@ func TestListClients(t *testing.T) { token: validToken, query: "dir=asc&dir=asc", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: us.URL + "/users?" + tc.query, - contentType: contentType, - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListClients", mock.Anything, tc.authnRes, mock.Anything).Return(tc.listUsersResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var bodyRes respBody - err = json.NewDecoder(res.Body).Decode(&bodyRes) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if bodyRes.Err != "" || bodyRes.Message != "" { - err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: us.URL + "/users?" + tc.query, + contentType: contentType, + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListClients", mock.Anything, tc.authnRes, mock.Anything).Return(tc.listUsersResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var bodyRes respBody + err = json.NewDecoder(res.Body).Decode(&bodyRes) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if bodyRes.Err != "" || bodyRes.Message != "" { + err = errors.Wrap(errors.New(bodyRes.Err), errors.New(bodyRes.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -823,25 +832,27 @@ func TestSearchUsers(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/users/search?", us.URL) + tc.query, - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(mgauthn.Session{UserID: validID, DomainID: validID}, tc.authnErr) - svcCall := svc.On("SearchUsers", mock.Anything, mock.Anything).Return( - mgclients.ClientsPage{ - Page: tc.listUsersResponse.Page, - Clients: tc.listUsersResponse.Clients, - }, - tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/users/search?", us.URL) + tc.query, + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(mgauthn.Session{UserID: validID, DomainID: domainID}, tc.authnErr) + svcCall := svc.On("SearchUsers", mock.Anything, mock.Anything).Return( + mgclients.ClientsPage{ + Page: tc.listUsersResponse.Page, + Clients: tc.listUsersResponse.Clients, + }, + tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -869,7 +880,7 @@ func TestUpdateClient(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"name":"%s","metadata":%s}`, newName, toJSON(newMetadata)), token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, clientResponse: mgclients.Client{ ID: client.ID, @@ -884,7 +895,7 @@ func TestUpdateClient(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"name":"%s","metadata":%s}`, newName, toJSON(newMetadata)), token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, clientResponse: mgclients.Client{ ID: client.ID, @@ -919,7 +930,7 @@ func TestUpdateClient(t *testing.T) { id: inValid, data: fmt.Sprintf(`{"name":"%s","metadata":%s}`, newName, toJSON(newMetadata)), token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusForbidden, err: svcerr.ErrAuthorization, @@ -929,7 +940,7 @@ func TestUpdateClient(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"name":"%s","metadata":%s}`, newName, toJSON(newMetadata)), token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, @@ -939,7 +950,7 @@ func TestUpdateClient(t *testing.T) { id: client.ID, data: fmt.Sprintf(`{"name":%s}`, "invalid"), token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -949,7 +960,7 @@ func TestUpdateClient(t *testing.T) { id: " ", data: fmt.Sprintf(`{"name":"%s","metadata":%s}`, newName, toJSON(newMetadata)), token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -957,28 +968,30 @@ func TestUpdateClient(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/users/%s", us.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClient", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/users/%s", us.URL, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClient", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1011,7 +1024,7 @@ func TestUpdateClientTags(t *testing.T) { Tags: []string{newTag}, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -1025,7 +1038,7 @@ func TestUpdateClientTags(t *testing.T) { Tags: []string{newTag}, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -1055,7 +1068,7 @@ func TestUpdateClientTags(t *testing.T) { data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusForbidden, err: svcerr.ErrAuthorization, }, @@ -1065,7 +1078,7 @@ func TestUpdateClientTags(t *testing.T) { data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: "application/xml", token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, }, @@ -1075,7 +1088,7 @@ func TestUpdateClientTags(t *testing.T) { data: fmt.Sprintf(`{"tags":["%s"]}`, newTag), contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, }, @@ -1085,39 +1098,41 @@ func TestUpdateClientTags(t *testing.T) { data: fmt.Sprintf(`{"tags":%s}`, newTag), contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, }, } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/users/%s/tags", us.URL, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClientTags", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - if err == nil { - assert.Equal(t, tc.clientResponse.Tags, resBody.Tags, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.clientResponse.Tags, resBody.Tags)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/users/%s/tags", us.URL, tc.id), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClientTags", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + if err == nil { + assert.Equal(t, tc.clientResponse.Tags, resBody.Tags, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.clientResponse.Tags, resBody.Tags)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1148,7 +1163,7 @@ func TestUpdateClientIdentity(t *testing.T) { }, contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -1164,7 +1179,7 @@ func TestUpdateClientIdentity(t *testing.T) { }, contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -1212,7 +1227,7 @@ func TestUpdateClientIdentity(t *testing.T) { }, contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrMissingID, }, @@ -1228,7 +1243,7 @@ func TestUpdateClientIdentity(t *testing.T) { }, contentType: "application/xml", token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, }, @@ -1244,36 +1259,38 @@ func TestUpdateClientIdentity(t *testing.T) { }, contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, }, } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/users/%s/identity", us.URL, tc.client.ID), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClientIdentity", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/users/%s/identity", us.URL, tc.client.ID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClientIdentity", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1355,21 +1372,23 @@ func TestPasswordResetRequest(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/password/reset-request", us.URL), - contentType: tc.contentType, - referer: tc.referer, - body: strings.NewReader(tc.data), - } - svcCall := svc.On("GenerateResetToken", mock.Anything, mock.Anything, mock.Anything).Return(tc.generateErr) - svcCall1 := svc.On("SendPasswordReset", mock.Anything, mock.Anything, mock.Anything, mock.Anything, validToken).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - svcCall1.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/password/reset-request", us.URL), + contentType: tc.contentType, + referer: tc.referer, + body: strings.NewReader(tc.data), + } + svcCall := svc.On("GenerateResetToken", mock.Anything, mock.Anything, mock.Anything).Return(tc.generateErr) + svcCall1 := svc.On("SendPasswordReset", mock.Anything, mock.Anything, mock.Anything, mock.Anything, validToken).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + svcCall1.Unset() + }) } } @@ -1449,22 +1468,24 @@ func TestPasswordReset(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPut, - url: fmt.Sprintf("%s/password/reset", us.URL), - contentType: tc.contentType, - referer: testReferer, - token: tc.token, - body: strings.NewReader(tc.data), - } - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ResetSecret", mock.Anything, tc.authnRes, mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPut, + url: fmt.Sprintf("%s/password/reset", us.URL), + contentType: tc.contentType, + referer: testReferer, + token: tc.token, + body: strings.NewReader(tc.data), + } + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ResetSecret", mock.Anything, tc.authnRes, mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1488,7 +1509,7 @@ func TestUpdateClientRole(t *testing.T) { data: fmt.Sprintf(`{"role": "%s"}`, "admin"), clientID: client.ID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusOK, err: nil, @@ -1498,7 +1519,7 @@ func TestUpdateClientRole(t *testing.T) { data: fmt.Sprintf(`{"role": "%s"}`, "admin"), clientID: client.ID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusOK, err: nil, @@ -1528,7 +1549,7 @@ func TestUpdateClientRole(t *testing.T) { data: fmt.Sprintf(`{"role": "%s"}`, "invalid"), clientID: client.ID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: svcerr.ErrInvalidRole, @@ -1538,7 +1559,7 @@ func TestUpdateClientRole(t *testing.T) { data: fmt.Sprintf(`{"role": "%s"}`, "admin"), clientID: client.ID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: "application/xml", status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, @@ -1548,7 +1569,7 @@ func TestUpdateClientRole(t *testing.T) { data: fmt.Sprintf(`{"role": %s}`, "admin"), clientID: client.ID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, contentType: contentType, status: http.StatusBadRequest, err: apiutil.ErrValidation, @@ -1556,29 +1577,31 @@ func TestUpdateClientRole(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/users/%s/role", us.URL, tc.clientID), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClientRole", mock.Anything, tc.authnRes, mock.Anything).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/users/%s/role", us.URL, tc.clientID), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClientRole", mock.Anything, tc.authnRes, mock.Anything).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1693,29 +1716,31 @@ func TestUpdateClientSecret(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPatch, - url: fmt.Sprintf("%s/users/secret", us.URL), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("UpdateClientSecret", mock.Anything, tc.authnRes, mock.Anything, mock.Anything).Return(tc.client, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) - } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPatch, + url: fmt.Sprintf("%s/users/secret", us.URL), + contentType: tc.contentType, + token: tc.token, + body: strings.NewReader(tc.data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("UpdateClientSecret", mock.Anything, tc.authnRes, mock.Anything, mock.Anything).Return(tc.client, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1784,28 +1809,30 @@ func TestIssueToken(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/users/tokens/issue", us.URL), - contentType: tc.contentType, - body: strings.NewReader(tc.data), - } - - svcCall := svc.On("IssueToken", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&magistrala.Token{AccessToken: validToken}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - if tc.err != nil { - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/users/tokens/issue", us.URL), + contentType: tc.contentType, + body: strings.NewReader(tc.data), } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() + + svcCall := svc.On("IssueToken", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&magistrala.Token{AccessToken: validToken}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + if tc.err != nil { + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + }) } } @@ -1829,7 +1856,7 @@ func TestRefreshToken(t *testing.T) { data: fmt.Sprintf(`{"refresh_token": "%s", "domain_id": "%s"}`, validToken, validID), contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusCreated, err: nil, }, @@ -1855,7 +1882,7 @@ func TestRefreshToken(t *testing.T) { data: fmt.Sprintf(`{"refresh_token": "%s", "domain_id": "%s"}`, validToken, "invalid"), contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusUnauthorized, err: svcerr.ErrAuthentication, }, @@ -1864,7 +1891,7 @@ func TestRefreshToken(t *testing.T) { data: fmt.Sprintf(`{"refresh_token": %s, "domain_id": %s}`, validToken, validID), contentType: contentType, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrValidation, }, @@ -1873,37 +1900,39 @@ func TestRefreshToken(t *testing.T) { data: fmt.Sprintf(`{"refresh_token": "%s", "domain_id": "%s"}`, validToken, validID), contentType: "application/xml", token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusUnsupportedMediaType, err: apiutil.ErrValidation, }, } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/users/tokens/refresh", us.URL), - contentType: tc.contentType, - body: strings.NewReader(tc.data), - token: tc.token, - } - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("RefreshToken", mock.Anything, tc.authnRes, tc.token, mock.Anything).Return(&magistrala.Token{AccessToken: validToken}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - if tc.err != nil { - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/users/tokens/refresh", us.URL), + contentType: tc.contentType, + body: strings.NewReader(tc.data), + token: tc.token, } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("RefreshToken", mock.Anything, tc.authnRes, tc.token, mock.Anything).Return(&magistrala.Token{AccessToken: validToken}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + if tc.err != nil { + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -1928,7 +1957,7 @@ func TestEnableClient(t *testing.T) { Status: mgclients.EnabledStatus, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -1940,7 +1969,7 @@ func TestEnableClient(t *testing.T) { Status: mgclients.EnabledStatus, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -1958,39 +1987,41 @@ func TestEnableClient(t *testing.T) { ID: "", }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrMissingID, }, } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/users/%s/enable", us.URL, tc.client.ID), - contentType: contentType, - token: tc.token, - body: strings.NewReader(data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("EnableClient", mock.Anything, tc.authnRes, mock.Anything).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - if tc.err != nil { - var resBody respBody - err = json.NewDecoder(res.Body).Decode(&resBody) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - if resBody.Err != "" || resBody.Message != "" { - err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/users/%s/enable", us.URL, tc.client.ID), + contentType: contentType, + token: tc.token, + body: strings.NewReader(data), } - 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("EnableClient", mock.Anything, tc.authnRes, mock.Anything).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + if tc.err != nil { + var resBody respBody + err = json.NewDecoder(res.Body).Decode(&resBody) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + if resBody.Err != "" || resBody.Message != "" { + err = errors.Wrap(errors.New(resBody.Err), errors.New(resBody.Message)) + } + 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.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -2016,7 +2047,7 @@ func TestDisableClient(t *testing.T) { Status: mgclients.DisabledStatus, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, SuperAdmin: true}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, SuperAdmin: true}, status: http.StatusOK, err: nil, }, @@ -2028,7 +2059,7 @@ func TestDisableClient(t *testing.T) { Status: mgclients.DisabledStatus, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusOK, err: nil, }, @@ -2046,30 +2077,32 @@ func TestDisableClient(t *testing.T) { ID: "", }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusBadRequest, err: apiutil.ErrMissingID, }, } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/users/%s/disable", us.URL, tc.client.ID), - contentType: contentType, - token: tc.token, - body: strings.NewReader(data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("DisableClient", mock.Anything, mock.Anything, mock.Anything).Return(mgclients.Client{}, tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/users/%s/disable", us.URL, tc.client.ID), + contentType: contentType, + token: tc.token, + body: strings.NewReader(data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("DisableClient", mock.Anything, mock.Anything, mock.Anything).Return(mgclients.Client{}, tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -2094,7 +2127,7 @@ func TestDeleteClient(t *testing.T) { ID: client.ID, }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusNoContent, err: nil, }, @@ -2112,29 +2145,31 @@ func TestDeleteClient(t *testing.T) { ID: "", }, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, status: http.StatusMethodNotAllowed, err: apiutil.ErrMissingID, }, } for _, tc := range cases { - data := toJSON(tc.client) - req := testRequest{ - client: us.Client(), - method: http.MethodDelete, - url: fmt.Sprintf("%s/users/%s", us.URL, tc.client.ID), - contentType: contentType, - token: tc.token, - body: strings.NewReader(data), - } - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - repoCall := svc.On("DeleteClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - repoCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.client) + req := testRequest{ + client: us.Client(), + method: http.MethodDelete, + url: fmt.Sprintf("%s/users/%s", us.URL, tc.client.ID), + contentType: contentType, + token: tc.token, + body: strings.NewReader(data), + } + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + repoCall := svc.On("DeleteClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + repoCall.Unset() + authnCall.Unset() + }) } } @@ -2146,6 +2181,7 @@ func TestListUsersByUserGroupId(t *testing.T) { desc string token string groupID string + domainID string page mgclients.Page status int query string @@ -2155,17 +2191,18 @@ func TestListUsersByUserGroupId(t *testing.T) { err error }{ { - desc: "list users with valid token", - token: validToken, - groupID: validID, - status: http.StatusOK, + desc: "list users with valid token", + token: validToken, + groupID: validID, + domainID: validID, + status: http.StatusOK, listUsersResponse: mgclients.ClientsPage{ Page: mgclients.Page{ Total: 1, }, Clients: []mgclients.Client{client}, }, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2173,7 +2210,7 @@ func TestListUsersByUserGroupId(t *testing.T) { token: validToken, groupID: "", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrMissingID, }, { @@ -2205,7 +2242,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "offset=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2229,7 +2266,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "limit=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2238,7 +2275,7 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: "limit=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2247,7 +2284,7 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2262,7 +2299,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "name=clientname", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2271,7 +2308,7 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: "name=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2294,7 +2331,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "status=enabled", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2325,7 +2362,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "tag=tag1,tag2", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2334,7 +2371,7 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: "tag=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2343,7 +2380,7 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: "tag=tag1&tag=tag2", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -2358,7 +2395,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2389,7 +2426,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, query: "permission=view", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2399,7 +2436,7 @@ func TestListUsersByUserGroupId(t *testing.T) { query: "permission=view&permission=view", status: http.StatusBadRequest, listUsersResponse: mgclients.ClientsPage{}, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -2416,7 +2453,7 @@ func TestListUsersByUserGroupId(t *testing.T) { }, }, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2425,7 +2462,7 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: "identity=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2434,30 +2471,32 @@ func TestListUsersByUserGroupId(t *testing.T) { groupID: validID, query: "identity=1&identity=2", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/groups/%s/users?", us.URL, tc.groupID) + tc.query, - token: tc.token, - } - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: validID}, mock.Anything, mock.Anything, mock.Anything).Return( - mgclients.MembersPage{ - Page: tc.listUsersResponse.Page, - Members: tc.listUsersResponse.Clients, - }, - tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/groups/%s/users?", us.URL, validID, tc.groupID) + tc.query, + token: tc.token, + } + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: domainID}, mock.Anything, mock.Anything, mock.Anything).Return( + mgclients.MembersPage{ + Page: tc.listUsersResponse.Page, + Members: tc.listUsersResponse.Clients, + }, + tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -2488,7 +2527,7 @@ func TestListUsersByChannelID(t *testing.T) { }, Clients: []mgclients.Client{client}, }, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2520,7 +2559,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "offset=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2544,7 +2583,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "limit=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2553,7 +2592,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "limit=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2562,7 +2601,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2577,7 +2616,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "name=clientname", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2586,7 +2625,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "name=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2608,7 +2647,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "status=enabled", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2617,7 +2656,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "status=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2639,7 +2678,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "tag=tag1,tag2", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2648,7 +2687,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "tag=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2671,7 +2710,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2680,7 +2719,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "metadata=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2702,7 +2741,7 @@ func TestListUsersByChannelID(t *testing.T) { }, query: "permission=view", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2727,7 +2766,7 @@ func TestListUsersByChannelID(t *testing.T) { }, }, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2736,7 +2775,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "identity=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2753,7 +2792,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "list_perms=true", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2762,7 +2801,7 @@ func TestListUsersByChannelID(t *testing.T) { channelID: validID, query: "list_perms=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2775,25 +2814,27 @@ func TestListUsersByChannelID(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/channels/%s/users?", us.URL, validID) + tc.query, - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: validID}, mock.Anything, mock.Anything, mock.Anything).Return( - mgclients.MembersPage{ - Page: tc.listUsersResponse.Page, - Members: tc.listUsersResponse.Clients, - }, - tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/channels/%s/users?", us.URL, validID, validID) + tc.query, + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: domainID}, mock.Anything, mock.Anything, mock.Anything).Return( + mgclients.MembersPage{ + Page: tc.listUsersResponse.Page, + Members: tc.listUsersResponse.Clients, + }, + tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -2824,7 +2865,7 @@ func TestListUsersByDomainID(t *testing.T) { }, Clients: []mgclients.Client{client}, }, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2854,7 +2895,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "offset=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2863,7 +2904,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "offset=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2879,7 +2920,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "limit=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2888,7 +2929,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "limit=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2897,7 +2938,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2912,7 +2953,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "name=clientname", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2921,7 +2962,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "name=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2944,7 +2985,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "status=enabled", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2953,7 +2994,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "status=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -2975,7 +3016,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "tag=tag1,tag2", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -2984,7 +3025,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "tag=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3006,7 +3047,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3015,7 +3056,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "metadata=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3037,7 +3078,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "permission=membership", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3062,7 +3103,7 @@ func TestListUsersByDomainID(t *testing.T) { }, }, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3071,7 +3112,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "identity=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3095,7 +3136,7 @@ func TestListUsersByDomainID(t *testing.T) { }, query: "list_perms=true", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3104,7 +3145,7 @@ func TestListUsersByDomainID(t *testing.T) { domainID: validID, query: "list_perms=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3117,25 +3158,27 @@ func TestListUsersByDomainID(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/domains/%s/users?", us.URL, validID) + tc.query, - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: validID}, mock.Anything, mock.Anything, mock.Anything).Return( - mgclients.MembersPage{ - Page: tc.listUsersResponse.Page, - Members: tc.listUsersResponse.Clients, - }, - tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/users?", us.URL, validID) + tc.query, + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: domainID}, mock.Anything, mock.Anything, mock.Anything).Return( + mgclients.MembersPage{ + Page: tc.listUsersResponse.Page, + Members: tc.listUsersResponse.Clients, + }, + tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -3166,7 +3209,7 @@ func TestListUsersByThingID(t *testing.T) { }, Clients: []mgclients.Client{client}, }, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3198,7 +3241,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "offset=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3207,7 +3250,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "offset=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3223,7 +3266,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "limit=1", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3232,7 +3275,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "limit=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3241,7 +3284,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: fmt.Sprintf("limit=%d", api.MaxLimitSize+1), status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3256,7 +3299,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "name=clientname", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3265,7 +3308,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "name=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3288,7 +3331,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "status=enabled", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3297,7 +3340,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "status=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3319,7 +3362,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "tag=tag1,tag2", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3328,7 +3371,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "tag=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3350,7 +3393,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3359,7 +3402,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "metadata=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3368,7 +3411,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&metadata=%7B%22domain%22%3A%20%22example.com%22%7D", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrInvalidQueryParams, }, { @@ -3383,7 +3426,7 @@ func TestListUsersByThingID(t *testing.T) { }, query: "permission=view", status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3407,7 +3450,7 @@ func TestListUsersByThingID(t *testing.T) { }, }, status: http.StatusOK, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: nil, }, { @@ -3416,7 +3459,7 @@ func TestListUsersByThingID(t *testing.T) { thingID: validID, query: "identity=invalid", status: http.StatusBadRequest, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID}, err: apiutil.ErrValidation, }, { @@ -3429,25 +3472,27 @@ func TestListUsersByThingID(t *testing.T) { } for _, tc := range cases { - req := testRequest{ - client: us.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/things/%s/users?", us.URL, validID) + tc.query, - token: tc.token, - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: validID}, mock.Anything, mock.Anything, mock.Anything).Return( - mgclients.MembersPage{ - Page: tc.listUsersResponse.Page, - Members: tc.listUsersResponse.Clients, - }, - tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + req := testRequest{ + client: us.Client(), + method: http.MethodGet, + url: fmt.Sprintf("%s/%s/things/%s/users?", us.URL, validID, validID) + tc.query, + token: tc.token, + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := svc.On("ListMembers", mock.Anything, mgauthn.Session{UserID: validID, DomainID: domainID}, mock.Anything, mock.Anything, mock.Anything).Return( + mgclients.MembersPage{ + Page: tc.listUsersResponse.Page, + Members: tc.listUsersResponse.Clients, + }, + tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -3457,6 +3502,7 @@ func TestAssignUsers(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -3467,8 +3513,9 @@ func TestAssignUsers(t *testing.T) { }{ { desc: "assign users to a group successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -3478,9 +3525,10 @@ func TestAssignUsers(t *testing.T) { err: nil, }, { - desc: "assign users to a group with invalid token", - token: inValidToken, - groupID: validID, + desc: "assign users to a group with invalid token", + domainID: domainID, + token: inValidToken, + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3490,9 +3538,10 @@ func TestAssignUsers(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "assign users to a group with empty token", - token: "", - groupID: validID, + desc: "assign users to a group with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3502,8 +3551,9 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with empty relation", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "", @@ -3514,8 +3564,9 @@ func TestAssignUsers(t *testing.T) { }, { desc: "assign users to a group with empty user ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -3525,9 +3576,11 @@ func TestAssignUsers(t *testing.T) { err: apiutil.ErrValidation, }, { - desc: "assign users to a group with invalid request body", - token: validToken, - groupID: validID, + desc: "assign users to a group with invalid request body", + domainID: domainID, + token: validToken, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, + groupID: validID, reqBody: map[string]interface{}{ "relation": make(chan int), }, @@ -3537,21 +3590,23 @@ func TestAssignUsers(t *testing.T) { } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/groups/%s/users/assign", us.URL, tc.groupID), - token: tc.token, - body: strings.NewReader(data), - } - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/groups/%s/users/assign", us.URL, tc.domainID, tc.groupID), + token: tc.token, + body: strings.NewReader(data), + } + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -3561,6 +3616,7 @@ func TestUnassignUsers(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -3571,8 +3627,9 @@ func TestUnassignUsers(t *testing.T) { }{ { desc: "unassign users from a group successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -3582,9 +3639,10 @@ func TestUnassignUsers(t *testing.T) { err: nil, }, { - desc: "unassign users from a group with invalid token", - token: inValidToken, - groupID: validID, + desc: "unassign users from a group with invalid token", + domainID: domainID, + token: inValidToken, + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3594,9 +3652,10 @@ func TestUnassignUsers(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "unassign users from a group with empty token", - token: "", - groupID: validID, + desc: "unassign users from a group with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ Relation: "member", UserIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3606,8 +3665,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with empty relation", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, groupID: validID, reqBody: groupReqBody{ Relation: "", @@ -3618,8 +3678,9 @@ func TestUnassignUsers(t *testing.T) { }, { desc: "unassign users from a group with empty user ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ Relation: "member", @@ -3629,9 +3690,11 @@ func TestUnassignUsers(t *testing.T) { err: apiutil.ErrValidation, }, { - desc: "unassign users from a group with invalid request body", - token: validToken, - groupID: validID, + desc: "unassign users from a group with invalid request body", + domainID: domainID, + token: validToken, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, + groupID: validID, reqBody: map[string]interface{}{ "relation": make(chan int), }, @@ -3640,22 +3703,24 @@ func TestUnassignUsers(t *testing.T) { }, } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/groups/%s/users/unassign", us.URL, tc.groupID), - token: tc.token, - body: strings.NewReader(data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/groups/%s/users/unassign", us.URL, tc.domainID, tc.groupID), + token: tc.token, + body: strings.NewReader(data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Unassign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "users", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -3665,6 +3730,7 @@ func TestAssignGroups(t *testing.T) { cases := []struct { desc string + domainID string token string groupID string reqBody interface{} @@ -3675,8 +3741,9 @@ func TestAssignGroups(t *testing.T) { }{ { desc: "assign groups to a parent group successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3685,9 +3752,10 @@ func TestAssignGroups(t *testing.T) { err: nil, }, { - desc: "assign groups to a parent group with invalid token", - token: inValidToken, - groupID: validID, + desc: "assign groups to a parent group with invalid token", + domainID: domainID, + token: inValidToken, + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -3696,9 +3764,10 @@ func TestAssignGroups(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "assign groups to a parent group with empty token", - token: "", - groupID: validID, + desc: "assign groups to a parent group with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -3707,8 +3776,9 @@ func TestAssignGroups(t *testing.T) { }, { desc: "assign groups to a parent group with empty parent group id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: "", reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3718,8 +3788,9 @@ func TestAssignGroups(t *testing.T) { }, { desc: "assign groups to a parent group with empty group ids", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{}, @@ -3728,9 +3799,11 @@ func TestAssignGroups(t *testing.T) { err: apiutil.ErrValidation, }, { - desc: "assign groups to a parent group with invalid request body", - token: validToken, - groupID: validID, + desc: "assign groups to a parent group with invalid request body", + domainID: domainID, + token: validToken, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, + groupID: validID, reqBody: map[string]interface{}{ "group_ids": make(chan int), }, @@ -3739,22 +3812,24 @@ func TestAssignGroups(t *testing.T) { }, } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/groups/%s/groups/assign", us.URL, tc.groupID), - token: tc.token, - body: strings.NewReader(data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "groups", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/groups/%s/groups/assign", us.URL, tc.domainID, tc.groupID), + token: tc.token, + body: strings.NewReader(data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Assign", mock.Anything, tc.authnRes, tc.groupID, mock.Anything, "groups", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } @@ -3765,6 +3840,7 @@ func TestUnassignGroups(t *testing.T) { cases := []struct { desc string token string + domainID string groupID string reqBody interface{} authnRes mgauthn.Session @@ -3774,8 +3850,9 @@ func TestUnassignGroups(t *testing.T) { }{ { desc: "unassign groups from a parent group successfully", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3784,9 +3861,10 @@ func TestUnassignGroups(t *testing.T) { err: nil, }, { - desc: "unassign groups from a parent group with invalid token", - token: inValidToken, - groupID: validID, + desc: "unassign groups from a parent group with invalid token", + domainID: domainID, + token: inValidToken, + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -3795,9 +3873,10 @@ func TestUnassignGroups(t *testing.T) { err: svcerr.ErrAuthentication, }, { - desc: "unassign groups from a parent group with empty token", - token: "", - groupID: validID, + desc: "unassign groups from a parent group with empty token", + domainID: domainID, + token: "", + groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, }, @@ -3806,8 +3885,9 @@ func TestUnassignGroups(t *testing.T) { }, { desc: "unassign groups from a parent group with empty group id", + domainID: domainID, token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID}, groupID: "", reqBody: groupReqBody{ GroupIDs: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}, @@ -3818,7 +3898,7 @@ func TestUnassignGroups(t *testing.T) { { desc: "unassign groups from a parent group with empty group ids", token: validToken, - authnRes: mgauthn.Session{UserID: validID, DomainID: validID, DomainUserID: validID}, + authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, groupID: validID, reqBody: groupReqBody{ GroupIDs: []string{}, @@ -3838,22 +3918,24 @@ func TestUnassignGroups(t *testing.T) { }, } for _, tc := range cases { - data := toJSON(tc.reqBody) - req := testRequest{ - client: us.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/groups/%s/groups/unassign", us.URL, tc.groupID), - token: tc.token, - body: strings.NewReader(data), - } - - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) - svcCall := gsvc.On("Unassign", mock.Anything, mock.Anything, tc.groupID, mock.Anything, "groups", mock.Anything).Return(tc.err) - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authnCall.Unset() + t.Run(tc.desc, func(t *testing.T) { + data := toJSON(tc.reqBody) + req := testRequest{ + client: us.Client(), + method: http.MethodPost, + url: fmt.Sprintf("%s/%s/groups/%s/groups/unassign", us.URL, tc.domainID, tc.groupID), + token: tc.token, + body: strings.NewReader(data), + } + + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr) + svcCall := gsvc.On("Unassign", mock.Anything, mock.Anything, tc.groupID, mock.Anything, "groups", mock.Anything).Return(tc.err) + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) + svcCall.Unset() + authnCall.Unset() + }) } } diff --git a/users/api/groups.go b/users/api/groups.go index c5ec38020e..50bcd2af05 100644 --- a/users/api/groups.go +++ b/users/api/groups.go @@ -31,9 +31,9 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, } r.Group(func(r chi.Router) { - r.Use(api.AuthenticateMiddleware(authn)) + r.Use(api.AuthenticateMiddlewareDomain(authn)) - r.Route("/groups", func(r chi.Router) { + r.Route("/{domainID}/groups", func(r chi.Router) { r.Post("/", otelhttp.NewHandler(kithttp.NewServer( gapi.CreateGroupEndpoint(svc, policies.NewGroupKind), gapi.DecodeGroupCreate, @@ -135,14 +135,14 @@ func groupsHandler(svc groups.Service, authn mgauthn.Authentication, r *chi.Mux, // The ideal placeholder name should be {channelID}, but gapi.DecodeListGroupsRequest uses {memberID} as a placeholder for the ID. // So here, we are using {memberID} as the placeholder. - r.Get("/channels/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/channels/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer( gapi.ListGroupsEndpoint(svc, "groups", "channels"), gapi.DecodeListGroupsRequest, api.EncodeResponse, opts..., ), "list_groups_by_channel_id").ServeHTTP) - r.Get("/users/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer( + r.Get("/{domainID}/users/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer( gapi.ListGroupsEndpoint(svc, "groups", "users"), gapi.DecodeListGroupsRequest, api.EncodeResponse, @@ -212,7 +212,8 @@ func unassignUsersEndpoint(svc groups.Service) endpoint.Endpoint { func decodeAssignGroupsRequest(_ context.Context, r *http.Request) (interface{}, error) { req := assignGroupsReq{ - groupID: chi.URLParam(r, "groupID"), + groupID: chi.URLParam(r, "groupID"), + domainID: chi.URLParam(r, "domainID"), } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) @@ -222,7 +223,8 @@ func decodeAssignGroupsRequest(_ context.Context, r *http.Request) (interface{}, func decodeUnassignGroupsRequest(_ context.Context, r *http.Request) (interface{}, error) { req := unassignGroupsReq{ - groupID: chi.URLParam(r, "groupID"), + groupID: chi.URLParam(r, "groupID"), + domainID: chi.URLParam(r, "domainID"), } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) diff --git a/users/api/requests.go b/users/api/requests.go index fbb2538654..865a9fabf4 100644 --- a/users/api/requests.go +++ b/users/api/requests.go @@ -298,10 +298,15 @@ func (req unassignUsersReq) validate() error { 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 } @@ -315,10 +320,15 @@ func (req assignGroupsReq) validate() error { 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 } diff --git a/users/api/requests_test.go b/users/api/requests_test.go index 554d2c55f4..148b7776be 100644 --- a/users/api/requests_test.go +++ b/users/api/requests_test.go @@ -21,7 +21,10 @@ const ( name = "client" ) -var validID = testsutil.GenerateUUID(&testing.T{}) +var ( + validID = testsutil.GenerateUUID(&testing.T{}) + domain = testsutil.GenerateUUID(&testing.T{}) +) func TestCreateClientReqValidate(t *testing.T) { cases := []struct { @@ -685,6 +688,7 @@ func TestAssignGroupsRequestValidate(t *testing.T) { { desc: "valid request", req: assignGroupsReq{ + domainID: domain, groupID: validID, GroupIDs: []string{validID}, }, @@ -693,6 +697,7 @@ func TestAssignGroupsRequestValidate(t *testing.T) { { desc: "empty group id", req: assignGroupsReq{ + domainID: domain, groupID: "", GroupIDs: []string{validID}, }, @@ -701,11 +706,21 @@ func TestAssignGroupsRequestValidate(t *testing.T) { { 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() @@ -722,6 +737,7 @@ func TestUnassignGroupsRequestValidate(t *testing.T) { { desc: "valid request", req: unassignGroupsReq{ + domainID: domain, groupID: validID, GroupIDs: []string{validID}, }, @@ -730,6 +746,7 @@ func TestUnassignGroupsRequestValidate(t *testing.T) { { desc: "empty group id", req: unassignGroupsReq{ + domainID: domain, groupID: "", GroupIDs: []string{validID}, }, @@ -738,11 +755,21 @@ func TestUnassignGroupsRequestValidate(t *testing.T) { { 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()