From a5059a79462251437c1cd7f0a7a190bce1a31784 Mon Sep 17 00:00:00 2001 From: Steve Munene Date: Fri, 8 Nov 2024 20:31:00 +0300 Subject: [PATCH] NOISSUE - Remove domain prefix for invitation (#2513) Signed-off-by: nyagamunene --- api/openapi/invitations.yml | 83 ++++++++++----- cli/invitations.go | 2 +- cli/invitations_test.go | 4 +- invitations/api/endpoint.go | 21 ++-- invitations/api/endpoint_test.go | 117 ++++++++------------- invitations/api/requests.go | 14 ++- invitations/api/requests_test.go | 45 +++++--- invitations/api/transport.go | 24 +++-- invitations/middleware/authorization.go | 5 +- pkg/sdk/go/invitations.go | 41 +++++--- pkg/sdk/go/invitations_test.go | 132 ++++++++++++------------ pkg/sdk/go/sdk.go | 4 +- pkg/sdk/mocks/sdk.go | 18 ++-- 13 files changed, 284 insertions(+), 226 deletions(-) diff --git a/api/openapi/invitations.yml b/api/openapi/invitations.yml index e6e50bab58..541e368595 100644 --- a/api/openapi/invitations.yml +++ b/api/openapi/invitations.yml @@ -27,7 +27,7 @@ tags: url: https://docs.magistrala.abstractmachines.fr/ paths: - /{domainID}/invitations: + /invitations: post: operationId: sendInvitation tags: @@ -35,8 +35,6 @@ 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: @@ -49,7 +47,7 @@ paths: "401": description: Missing or invalid access token provided. "403": - description: Unauthorized access to the domain ID. + description: Failed to perform authorization over the entity. "404": description: A non-existent entity request. "409": @@ -74,7 +72,7 @@ paths: - $ref: "#/components/parameters/Offset" - $ref: "#/components/parameters/UserID" - $ref: "#/components/parameters/InvitedBy" - - $ref: "auth.yml#/components/parameters/DomainID" + - $ref: "#/components/parameters/DomainID" - $ref: "#/components/parameters/Relation" - $ref: "#/components/parameters/State" security: @@ -89,7 +87,7 @@ paths: Missing or invalid access token provided. This endpoint is available only for administrators. "403": - description: Unauthorized access to the domain ID. + description: Failed to perform authorization over the entity. "404": description: A non-existent entity request. "422": @@ -97,7 +95,7 @@ paths: "500": $ref: "#/components/responses/ServiceError" - /{domainID}/invitations/accept: + /invitations/accept: post: operationId: acceptInvitation summary: Accept invitation @@ -107,8 +105,8 @@ paths: - Invitations security: - bearerAuth: [] - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" + requestBody: + $ref: "#/components/requestBodies/AcceptInvitationReq" responses: "204": description: Invitation accepted. @@ -118,12 +116,10 @@ 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" - /{domainID}/invitations/reject: + /invitations/reject: post: operationId: rejectInvitation summary: Reject invitation @@ -133,8 +129,8 @@ paths: - Invitations security: - bearerAuth: [] - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" + requestBody: + $ref: "#/components/requestBodies/AcceptInvitationReq" responses: "204": description: Invitation rejected. @@ -144,12 +140,10 @@ 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" - /{domainID}/invitations/users/{user_id}: + /invitations/{user_id}/{domain_id}: get: operationId: getInvitation summary: Retrieves a specific invitation @@ -159,7 +153,7 @@ paths: - Invitations parameters: - $ref: "#/components/parameters/user_id" - - $ref: "auth.yml#/components/parameters/DomainID" + - $ref: "#/components/parameters/domain_id" security: - bearerAuth: [] responses: @@ -170,11 +164,9 @@ paths: "401": description: Missing or invalid access token provided. "403": - description: Unauthorized access to the domain ID. + description: Failed to perform authorization over the entity. "404": description: A non-existent entity request. - "415": - description: Missing or invalid content type. "422": description: Database can't process request. "500": @@ -189,7 +181,7 @@ paths: - Invitations parameters: - $ref: "#/components/parameters/user_id" - - $ref: "auth.yml#/components/parameters/DomainID" + - $ref: "#/components/parameters/domain_id" security: - bearerAuth: [] responses: @@ -198,13 +190,11 @@ paths: "400": description: Failed due to malformed JSON. "403": - description: Unauthorized access to the domain ID. + description: Failed to perform authorization over the entity. "404": 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" @@ -230,6 +220,11 @@ 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: @@ -251,6 +246,7 @@ components: description: Resend invitation. required: - user_id + - domain_id - relation Invitation: @@ -406,6 +402,26 @@ 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. @@ -458,6 +474,22 @@ 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. @@ -470,6 +502,7 @@ components: operationId: deleteInvitation parameters: user_id: $response.body#/user_id + domain_id: $response.body#/domain_id InvitationPageRes: description: Data retrieved. diff --git a/cli/invitations.go b/cli/invitations.go index 0971deac31..379187c8bf 100644 --- a/cli/invitations.go +++ b/cli/invitations.go @@ -53,7 +53,7 @@ var cmdInvitations = []cobra.Command{ Limit: Limit, } if args[0] == all { - l, err := sdk.Invitations(pageMetadata, args[1], args[2]) + l, err := sdk.Invitations(pageMetadata, args[1]) if err != nil { logErrorCmd(*cmd, err) return diff --git a/cli/invitations_test.go b/cli/invitations_test.go index 55d1df5e22..43b9bb86ab 100644 --- a/cli/invitations_test.go +++ b/cli/invitations_test.go @@ -113,7 +113,6 @@ func TestGetInvitationCmd(t *testing.T) { desc: "get all invitations successfully", args: []string{ all, - domain.ID, token, }, page: mgsdk.InvitationPage{ @@ -148,7 +147,6 @@ func TestGetInvitationCmd(t *testing.T) { desc: "get all invitations with invalid token", args: []string{ all, - domain.ID, invalidToken, }, logType: errLog, @@ -171,7 +169,7 @@ func TestGetInvitationCmd(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { sdkCall := sdkMock.On("Invitation", tc.args[0], tc.args[1], mock.Anything).Return(tc.inv, tc.sdkErr) - sdkCall1 := sdkMock.On("Invitations", mock.Anything, tc.args[1], tc.args[2]).Return(tc.page, tc.sdkErr) + sdkCall1 := sdkMock.On("Invitations", mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) diff --git a/invitations/api/endpoint.go b/invitations/api/endpoint.go index cb10ac7630..08adfc43d7 100644 --- a/invitations/api/endpoint.go +++ b/invitations/api/endpoint.go @@ -24,15 +24,14 @@ func sendInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { if err := req.validate(); err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) } - session, ok := ctx.Value(api.SessionKey).(authn.Session) if !ok { return nil, svcerr.ErrAuthorization } - + session.DomainID = req.DomainID invitation := invitations.Invitation{ UserID: req.UserID, - DomainID: session.DomainID, + DomainID: req.DomainID, Relation: req.Relation, Resend: req.Resend, } @@ -57,8 +56,7 @@ func viewInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { if !ok { return nil, svcerr.ErrAuthorization } - req.domainID = session.DomainID - + session.DomainID = req.domainID invitation, err := svc.ViewInvitation(ctx, session, req.userID, req.domainID) if err != nil { return nil, err @@ -81,8 +79,8 @@ func listInvitationsEndpoint(svc invitations.Service) endpoint.Endpoint { if !ok { return nil, svcerr.ErrAuthorization } + session.DomainID = req.DomainID - req.Page.DomainID = session.DomainID page, err := svc.ListInvitations(ctx, session, req.Page) if err != nil { return nil, err @@ -105,8 +103,8 @@ func acceptInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { if !ok { return nil, svcerr.ErrAuthorization } - req.domainID = session.DomainID - if err := svc.AcceptInvitation(ctx, session, req.domainID); err != nil { + + if err := svc.AcceptInvitation(ctx, session, req.DomainID); err != nil { return nil, err } @@ -125,8 +123,8 @@ func rejectInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { if !ok { return nil, svcerr.ErrAuthorization } - req.domainID = session.DomainID - if err := svc.RejectInvitation(ctx, session, req.domainID); err != nil { + + if err := svc.RejectInvitation(ctx, session, req.DomainID); err != nil { return nil, err } @@ -145,7 +143,8 @@ func deleteInvitationEndpoint(svc invitations.Service) endpoint.Endpoint { if !ok { return nil, svcerr.ErrAuthorization } - req.domainID = session.DomainID + session.DomainID = req.domainID + if err := svc.DeleteInvitation(ctx, session, req.userID, req.domainID); err != nil { return nil, err } diff --git a/invitations/api/endpoint_test.go b/invitations/api/endpoint_test.go index 41f34c058e..c81e5ee0c6 100644 --- a/invitations/api/endpoint_test.go +++ b/invitations/api/endpoint_test.go @@ -70,7 +70,6 @@ func TestSendInvitation(t *testing.T) { cases := []struct { desc string - domainID string token string data string contentType string @@ -81,9 +80,8 @@ func TestSendInvitation(t *testing.T) { }{ { desc: "valid request", - domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s","domain_id": "%s", "relation": "%s"}`, validID, domainID, "domain"), authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, status: http.StatusCreated, contentType: validContenType, @@ -91,27 +89,24 @@ func TestSendInvitation(t *testing.T) { }, { desc: "invalid token", - domainID: domainID, token: "", - data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s","domain_id": "%s", "relation": "%s"}`, validID, 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"), + data: fmt.Sprintf(`{"user_id": "%s","domain_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", "relation": "%s"}`, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s","domain_id": "%s", "relation": "%s"}`, validID, validID, "domain"), authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, status: http.StatusUnsupportedMediaType, contentType: "text/plain", @@ -119,7 +114,6 @@ func TestSendInvitation(t *testing.T) { }, { desc: "invalid data", - domainID: domainID, token: validToken, data: `data`, authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, @@ -129,9 +123,8 @@ func TestSendInvitation(t *testing.T) { }, { desc: "with service error", - domainID: domainID, token: validToken, - data: fmt.Sprintf(`{"user_id": "%s", "relation": "%s"}`, validID, "domain"), + data: fmt.Sprintf(`{"user_id": "%s", "domain_id": "%s", "relation": "%s"}`, validID, domainID, "domain"), authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, status: http.StatusForbidden, contentType: validContenType, @@ -146,7 +139,7 @@ func TestSendInvitation(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodPost, - url: is.URL + "/" + tc.domainID + "/invitations", + url: is.URL + "/invitations", token: tc.token, contentType: tc.contentType, body: strings.NewReader(tc.data), @@ -166,7 +159,6 @@ func TestListInvitation(t *testing.T) { cases := []struct { desc string - domainID string token string query string contentType string @@ -177,8 +169,7 @@ func TestListInvitation(t *testing.T) { }{ { desc: "valid request", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, status: http.StatusOK, contentType: validContenType, @@ -186,7 +177,6 @@ func TestListInvitation(t *testing.T) { }, { desc: "invalid token", - domainID: domainID, token: "", status: http.StatusUnauthorized, contentType: validContenType, @@ -194,8 +184,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with offset", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: "offset=1", status: http.StatusOK, @@ -204,7 +193,6 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invalid offset", - domainID: domainID, token: validToken, query: "offset=invalid", status: http.StatusBadRequest, @@ -213,8 +201,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with limit", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: "limit=1", status: http.StatusOK, @@ -223,7 +210,6 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invalid limit", - domainID: domainID, token: validToken, query: "limit=invalid", status: http.StatusBadRequest, @@ -232,8 +218,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with user_id", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: fmt.Sprintf("user_id=%s", validID), status: http.StatusOK, @@ -242,8 +227,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate user_id", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: "user_id=1&user_id=2", status: http.StatusBadRequest, @@ -252,8 +236,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invited_by", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: fmt.Sprintf("invited_by=%s", validID), status: http.StatusOK, @@ -262,8 +245,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate invited_by", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: "invited_by=1&invited_by=2", status: http.StatusBadRequest, @@ -272,8 +254,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with relation", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: fmt.Sprintf("relation=%s", "relation"), status: http.StatusOK, @@ -282,26 +263,16 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate relation", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: "relation=1&relation=2", status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, }, - { - desc: "with empty domain_id", - domainID: "", - token: validToken, - status: http.StatusBadRequest, - contentType: validContenType, - svcErr: nil, - }, { desc: "with state", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, query: "state=pending", status: http.StatusOK, @@ -310,7 +281,6 @@ func TestListInvitation(t *testing.T) { }, { desc: "with invalid state", - domainID: domainID, token: validToken, query: "state=invalid", status: http.StatusBadRequest, @@ -319,7 +289,6 @@ func TestListInvitation(t *testing.T) { }, { desc: "with duplicate state", - domainID: domainID, token: validToken, query: "state=all&state=all", status: http.StatusBadRequest, @@ -328,8 +297,7 @@ func TestListInvitation(t *testing.T) { }, { desc: "with service error", - domainID: domainID, - authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + authnRes: mgauthn.Session{UserID: validID, DomainUserID: domainID + "_" + validID}, token: validToken, status: http.StatusForbidden, contentType: validContenType, @@ -344,7 +312,7 @@ func TestListInvitation(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodGet, - url: is.URL + "/" + tc.domainID + "/invitations?" + tc.query, + url: is.URL + "/invitations?" + tc.query, token: tc.token, contentType: tc.contentType, } @@ -405,7 +373,7 @@ func TestViewInvitation(t *testing.T) { token: validToken, userID: "", domainID: domainID, - status: http.StatusNotFound, + status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, }, @@ -414,7 +382,7 @@ func TestViewInvitation(t *testing.T) { token: validToken, userID: validID, domainID: "", - status: http.StatusBadRequest, + status: http.StatusNotFound, contentType: validContenType, svcErr: nil, }, @@ -423,7 +391,7 @@ func TestViewInvitation(t *testing.T) { token: validToken, userID: "", domainID: "", - status: http.StatusBadRequest, + status: http.StatusNotFound, contentType: validContenType, svcErr: nil, }, @@ -436,7 +404,7 @@ func TestViewInvitation(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodGet, - url: is.URL + "/" + tc.domainID + "/invitations/users/" + tc.userID, + url: is.URL + "/invitations/" + tc.userID + "/" + tc.domainID, token: tc.token, contentType: tc.contentType, } @@ -499,7 +467,7 @@ func TestDeleteInvitation(t *testing.T) { token: validToken, userID: "", domainID: domainID, - status: http.StatusNotFound, + status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, }, @@ -508,7 +476,7 @@ func TestDeleteInvitation(t *testing.T) { token: validToken, userID: validID, domainID: "", - status: http.StatusBadRequest, + status: http.StatusNotFound, contentType: validContenType, svcErr: nil, }, @@ -517,7 +485,7 @@ func TestDeleteInvitation(t *testing.T) { token: validToken, userID: "", domainID: "", - status: http.StatusBadRequest, + status: http.StatusNotFound, contentType: validContenType, svcErr: nil, }, @@ -530,7 +498,7 @@ func TestDeleteInvitation(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodDelete, - url: is.URL + "/" + tc.domainID + "/invitations/users/" + tc.userID, + url: is.URL + "/invitations/" + tc.userID + "/" + tc.domainID, token: tc.token, contentType: tc.contentType, } @@ -549,7 +517,6 @@ func TestAcceptInvitation(t *testing.T) { _ = authn cases := []struct { desc string - domainID string token string data string contentType string @@ -560,8 +527,8 @@ func TestAcceptInvitation(t *testing.T) { }{ { desc: "valid request", - domainID: domainID, authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, + data: fmt.Sprintf(`{"domain_id": "%s"}`, validID), token: validToken, status: http.StatusNoContent, contentType: validContenType, @@ -569,33 +536,33 @@ func TestAcceptInvitation(t *testing.T) { }, { 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, authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, 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: "empty domain", - domainID: "", + desc: "invalid data", token: validToken, + data: `data`, status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, @@ -609,9 +576,10 @@ func TestAcceptInvitation(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodPost, - url: is.URL + "/" + tc.domainID + "/invitations/accept", + url: is.URL + "/invitations/accept", token: tc.token, contentType: tc.contentType, + body: strings.NewReader(tc.data), } res, err := req.make() @@ -629,8 +597,8 @@ func TestRejectInvitation(t *testing.T) { cases := []struct { desc string - domainID string token string + data string contentType string status int svcErr error @@ -639,42 +607,42 @@ func TestRejectInvitation(t *testing.T) { }{ { desc: "valid request", - domainID: domainID, authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, 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, authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID}, 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: "empty domain", - domainID: "", + desc: "invalid data", token: validToken, + data: `data`, status: http.StatusBadRequest, contentType: validContenType, svcErr: nil, @@ -688,9 +656,10 @@ func TestRejectInvitation(t *testing.T) { req := testRequest{ client: is.Client(), method: http.MethodPost, - url: is.URL + "/" + tc.domainID + "/invitations/reject", + url: is.URL + "/invitations/reject", token: tc.token, contentType: tc.contentType, + body: strings.NewReader(tc.data), } res, err := req.make() diff --git a/invitations/api/requests.go b/invitations/api/requests.go index 7a44dc11d8..74c42acaa1 100644 --- a/invitations/api/requests.go +++ b/invitations/api/requests.go @@ -11,8 +11,8 @@ import ( const maxLimitSize = 100 type sendInvitationReq struct { - domainID string UserID string `json:"user_id,omitempty"` + DomainID string `json:"domain_id,omitempty"` Relation string `json:"relation,omitempty"` Resend bool `json:"resend,omitempty"` } @@ -21,6 +21,9 @@ func (req *sendInvitationReq) validate() error { if req.UserID == "" { return apiutil.ErrMissingID } + if req.DomainID == "" { + return apiutil.ErrMissingDomainID + } if err := invitations.CheckRelation(req.Relation); err != nil { return err } @@ -41,10 +44,14 @@ func (req *listInvitationsReq) validate() error { } type acceptInvitationReq struct { - domainID string + DomainID string `json:"domain_id,omitempty"` } func (req *acceptInvitationReq) validate() error { + if req.DomainID == "" { + return apiutil.ErrMissingDomainID + } + return nil } @@ -57,6 +64,9 @@ func (req *invitationReq) validate() error { if req.userID == "" { return apiutil.ErrMissingID } + if req.domainID == "" { + return apiutil.ErrMissingDomainID + } return nil } diff --git a/invitations/api/requests_test.go b/invitations/api/requests_test.go index c1809e840f..17d731d792 100644 --- a/invitations/api/requests_test.go +++ b/invitations/api/requests_test.go @@ -25,7 +25,7 @@ func TestSendInvitationReqValidation(t *testing.T) { desc: "valid request", req: sendInvitationReq{ UserID: valid, - domainID: valid, + DomainID: valid, Relation: policies.DomainRelation, Resend: true, }, @@ -35,17 +35,27 @@ func TestSendInvitationReqValidation(t *testing.T) { desc: "empty user ID", req: sendInvitationReq{ UserID: "", - domainID: valid, + DomainID: valid, Relation: policies.DomainRelation, Resend: true, }, err: apiutil.ErrMissingID, }, + { + desc: "empty domain_id", + req: sendInvitationReq{ + UserID: valid, + DomainID: "", + Relation: policies.DomainRelation, + Resend: true, + }, + err: apiutil.ErrMissingDomainID, + }, { desc: "missing relation", req: sendInvitationReq{ UserID: valid, - domainID: valid, + DomainID: valid, Relation: "", Resend: true, }, @@ -55,7 +65,7 @@ func TestSendInvitationReqValidation(t *testing.T) { desc: "invalid relation", req: sendInvitationReq{ UserID: valid, - domainID: valid, + DomainID: valid, Relation: "invalid", Resend: true, }, @@ -80,20 +90,14 @@ func TestListInvitationsReq(t *testing.T) { { desc: "valid request", req: listInvitationsReq{ - Page: invitations.Page{ - Limit: 1, - DomainID: valid, - }, + Page: invitations.Page{Limit: 1}, }, err: nil, }, { desc: "invalid limit", req: listInvitationsReq{ - Page: invitations.Page{ - Limit: 1000, - DomainID: valid, - }, + Page: invitations.Page{Limit: 1000}, }, err: apiutil.ErrLimitSize, }, @@ -116,10 +120,17 @@ func TestAcceptInvitationReq(t *testing.T) { { desc: "valid request", req: acceptInvitationReq{ - domainID: valid, + DomainID: valid, }, err: nil, }, + { + desc: "empty domain_id", + req: acceptInvitationReq{ + DomainID: "", + }, + err: apiutil.ErrMissingDomainID, + }, } for _, tc := range cases { @@ -152,6 +163,14 @@ func TestInvitationReqValidation(t *testing.T) { }, err: apiutil.ErrMissingID, }, + { + desc: "empty domain", + req: invitationReq{ + userID: valid, + domainID: "", + }, + err: apiutil.ErrMissingDomainID, + }, } for _, tc := range cases { diff --git a/invitations/api/transport.go b/invitations/api/transport.go index 5f36b5e6a1..b8d6b69214 100644 --- a/invitations/api/transport.go +++ b/invitations/api/transport.go @@ -38,9 +38,9 @@ func MakeHandler(svc invitations.Service, logger *slog.Logger, authn mgauthn.Aut mux := chi.NewRouter() mux.Group(func(r chi.Router) { - r.Use(api.AuthenticateMiddleware(authn, true)) + r.Use(api.AuthenticateMiddleware(authn, false)) - r.Route("/{domainID}/invitations", func(r chi.Router) { + r.Route("/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("/users/{user_id}", func(r chi.Router) { + r.Route("/{user_id}/{domain_id}", func(r chi.Router) { r.Get("/", otelhttp.NewHandler(kithttp.NewServer( viewInvitationEndpoint(svc), decodeInvitationReq, @@ -122,6 +122,10 @@ 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) @@ -130,7 +134,6 @@ func decodeListInvitationsReq(_ context.Context, r *http.Request) (interface{}, if err != nil { return nil, errors.Wrap(apiutil.ErrValidation, err) } - req := listInvitationsReq{ Page: invitations.Page{ Offset: offset, @@ -138,6 +141,7 @@ func decodeListInvitationsReq(_ context.Context, r *http.Request) (interface{}, InvitedBy: invitedBy, UserID: userID, Relation: relation, + DomainID: domainID, State: state, }, } @@ -150,14 +154,18 @@ func decodeAcceptInvitationReq(_ context.Context, r *http.Request) (interface{}, return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) } - return acceptInvitationReq{ - domainID: chi.URLParam(r, "domainID"), - }, nil + var req acceptInvitationReq + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) + } + + return req, nil } func decodeInvitationReq(_ context.Context, r *http.Request) (interface{}, error) { req := invitationReq{ - userID: chi.URLParam(r, "user_id"), + userID: chi.URLParam(r, "user_id"), + domainID: chi.URLParam(r, "domain_id"), } return req, nil diff --git a/invitations/middleware/authorization.go b/invitations/middleware/authorization.go index 73ecf3e1f4..1f89b1fef2 100644 --- a/invitations/middleware/authorization.go +++ b/invitations/middleware/authorization.go @@ -33,7 +33,7 @@ func (am *authorizationMiddleware) SendInvitation(ctx context.Context, session a if err := am.checkAdmin(ctx, session.UserID, session.DomainID); err != nil { return err } - + session.DomainUserID = auth.EncodeDomainUserID(session.DomainID, session.UserID) domainUserId := auth.EncodeDomainUserID(invitation.DomainID, invitation.UserID) if err := am.authorize(ctx, domainUserId, policies.MembershipPermission, policies.DomainType, invitation.DomainID); err == nil { // return error if the user is already a member of the domain @@ -48,6 +48,7 @@ func (am *authorizationMiddleware) SendInvitation(ctx context.Context, session a } func (am *authorizationMiddleware) ViewInvitation(ctx context.Context, session authn.Session, userID, domain string) (invitation invitations.Invitation, err error) { + session.DomainUserID = auth.EncodeDomainUserID(session.DomainID, session.UserID) if session.UserID != userID { if err := am.checkAdmin(ctx, session.DomainUserID, domain); err != nil { return invitations.Invitation{}, err @@ -58,6 +59,7 @@ func (am *authorizationMiddleware) ViewInvitation(ctx context.Context, session a } func (am *authorizationMiddleware) ListInvitations(ctx context.Context, session authn.Session, page invitations.Page) (invs invitations.InvitationPage, err error) { + session.DomainUserID = auth.EncodeDomainUserID(session.DomainID, session.UserID) if err := am.authorize(ctx, session.DomainUserID, policies.AdminPermission, policies.PlatformType, policies.MagistralaObject); err == nil { session.SuperAdmin = true } @@ -85,6 +87,7 @@ func (am *authorizationMiddleware) RejectInvitation(ctx context.Context, session } func (am *authorizationMiddleware) DeleteInvitation(ctx context.Context, session authn.Session, userID, domainID string) (err error) { + session.DomainUserID = auth.EncodeDomainUserID(session.DomainID, session.UserID) if err := am.checkAdmin(ctx, session.DomainUserID, domainID); err != nil { return err } diff --git a/pkg/sdk/go/invitations.go b/pkg/sdk/go/invitations.go index 78433d0fc5..97c42255f9 100644 --- a/pkg/sdk/go/invitations.go +++ b/pkg/sdk/go/invitations.go @@ -5,7 +5,6 @@ package sdk import ( "encoding/json" - "fmt" "net/http" "time" @@ -44,7 +43,7 @@ func (sdk mgSDK) SendInvitation(invitation Invitation, token string) (err error) return errors.NewSDKError(err) } - url := sdk.invitationsURL + "/" + invitation.DomainID + "/" + invitationsEndpoint + url := sdk.invitationsURL + "/" + invitationsEndpoint _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusCreated) @@ -52,7 +51,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 + "/" + domainID + "/" + invitationsEndpoint + "/" + usersEndpoint + "/" + userID + url := sdk.invitationsURL + "/" + invitationsEndpoint + "/" + userID + "/" + domainID _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) if sdkerr != nil { @@ -66,10 +65,8 @@ func (sdk mgSDK) Invitation(userID, domainID, token string) (invitation Invitati return invitation, nil } -func (sdk mgSDK) Invitations(pm PageMetadata, domainID, token string) (invitations InvitationPage, err error) { - endpoint := fmt.Sprintf("%s/%s", domainID, invitationsEndpoint) - - url, err := sdk.withQueryParams(sdk.invitationsURL, endpoint, pm) +func (sdk mgSDK) Invitations(pm PageMetadata, token string) (invitations InvitationPage, err error) { + url, err := sdk.withQueryParams(sdk.invitationsURL, invitationsEndpoint, pm) if err != nil { return InvitationPage{}, errors.NewSDKError(err) } @@ -88,23 +85,43 @@ func (sdk mgSDK) Invitations(pm PageMetadata, domainID, token string) (invitatio } func (sdk mgSDK) AcceptInvitation(domainID, token string) (err error) { - url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + acceptEndpoint + 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 - _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent) + _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) RejectInvitation(domainID, token string) (err error) { - url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + rejectEndpoint + 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 - _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent) + _, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusNoContent) return sdkerr } func (sdk mgSDK) DeleteInvitation(userID, domainID, token string) (err error) { - url := sdk.invitationsURL + "/" + domainID + "/" + invitationsEndpoint + "/" + usersEndpoint + "/" + userID + url := sdk.invitationsURL + "/" + invitationsEndpoint + "/" + userID + "/" + domainID _, _, 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 5d14f218db..cc662a3787 100644 --- a/pkg/sdk/go/invitations_test.go +++ b/pkg/sdk/go/invitations_test.go @@ -131,14 +131,14 @@ func TestSendInvitation(t *testing.T) { Relation: invitation.Relation, Resend: invitation.Resend, }, - authenticateErr: svcerr.ErrCreateEntity, - err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity), + svcErr: svcerr.ErrCreateEntity, + err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: invitation.DomainID + "_" + validID, UserID: validID, DomainID: invitation.DomainID} + if tc.token == valid { + tc.session = mgauthn.Session{UserID: tc.sendInvitationReq.UserID, DomainID: tc.sendInvitationReq.DomainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("SendInvitation", mock.Anything, tc.session, tc.svcReq).Return(tc.svcErr) @@ -206,20 +206,30 @@ func TestViewInvitation(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "view invitation with invalid domainID", - token: validToken, - userID: invitation.UserID, - domainID: wrongID, - svcRes: invitations.Invitation{}, - authenticateErr: svcerr.ErrNotFound, - response: sdk.Invitation{}, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + 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, + userID: invitation.UserID, + domainID: wrongID, + svcRes: invitations.Invitation{}, + svcErr: svcerr.ErrNotFound, + response: sdk.Invitation{}, + 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: invitation.DomainID + "_" + validID, UserID: validID, DomainID: invitation.DomainID} + if tc.token == valid { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.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) @@ -248,7 +258,6 @@ func TestListInvitation(t *testing.T) { cases := []struct { desc string token string - domainID string session mgauthn.Session pageMeta sdk.PageMetadata svcReq invitations.Page @@ -259,17 +268,15 @@ func TestListInvitation(t *testing.T) { err error }{ { - desc: "list invitations successfully", - domainID: invitation.DomainID, - token: validToken, + desc: "list invitations successfully", + token: validToken, pageMeta: sdk.PageMetadata{ Offset: 0, Limit: 10, }, svcReq: invitations.Page{ - Offset: 0, - Limit: 10, - DomainID: invitation.DomainID, + Offset: 0, + Limit: 10, }, svcRes: invitations.InvitationPage{ Total: 1, @@ -283,17 +290,15 @@ func TestListInvitation(t *testing.T) { err: nil, }, { - desc: "list invitations with invalid token", - domainID: invitation.DomainID, - token: invalidToken, + desc: "list invitations with invalid token", + token: invalidToken, pageMeta: sdk.PageMetadata{ Offset: 0, Limit: 10, }, svcReq: invitations.Page{ - Offset: 0, - Limit: 10, - DomainID: invitation.DomainID, + Offset: 0, + Limit: 10, }, svcRes: invitations.InvitationPage{}, authenticateErr: svcerr.ErrAuthentication, @@ -302,7 +307,6 @@ func TestListInvitation(t *testing.T) { }, { desc: "list invitations with empty token", - domainID: invitation.DomainID, token: "", pageMeta: sdk.PageMetadata{}, svcRes: invitations.InvitationPage{}, @@ -311,18 +315,8 @@ func TestListInvitation(t *testing.T) { 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(apiutil.ErrMissingDomainID, http.StatusBadRequest), - }, - { - desc: "list invitations with limit greater than max limit", - token: validToken, - domainID: invitation.DomainID, + desc: "list invitations with limit greater than max limit", + token: validToken, pageMeta: sdk.PageMetadata{ Offset: 0, Limit: 101, @@ -336,12 +330,12 @@ func TestListInvitation(t *testing.T) { } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - tc.session = mgauthn.Session{DomainUserID: invitation.DomainID + "_" + validID, UserID: validID, DomainID: invitation.DomainID} + if tc.token == valid { + tc.session = mgauthn.Session{DomainUserID: validID, UserID: validID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("ListInvitations", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.Invitations(tc.pageMeta, tc.domainID, tc.token) + resp, err := mgsdk.Invitations(tc.pageMeta, tc.token) assert.Equal(t, tc.err, err) assert.Equal(t, tc.response, resp) if tc.err == nil { @@ -394,17 +388,17 @@ func TestAcceptInvitation(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "accept invitation with invalid domainID", - token: validToken, - domainID: wrongID, - authenticateErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + desc: "accept invitation with invalid domainID", + token: validToken, + domainID: wrongID, + 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: invitation.DomainID + "_" + validID, UserID: validID, DomainID: invitation.DomainID} + 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("AcceptInvitation", mock.Anything, tc.session, tc.domainID).Return(tc.svcErr) @@ -460,17 +454,17 @@ func TestRejectInvitation(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "reject invitation with invalid domainID", - token: validToken, - domainID: wrongID, - authenticateErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + desc: "reject invitation with invalid domainID", + token: validToken, + domainID: wrongID, + 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: invitation.DomainID + "_" + validID, UserID: validID, DomainID: invitation.DomainID} + 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("RejectInvitation", mock.Anything, tc.session, tc.domainID).Return(tc.svcErr) @@ -530,18 +524,26 @@ func TestDeleteInvitation(t *testing.T) { err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), }, { - desc: "delete invitation with invalid domainID", - token: validToken, - userID: invitation.UserID, - domainID: wrongID, - authenticateErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), + 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, + userID: invitation.UserID, + domainID: wrongID, + 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: invitation.DomainID + "_" + validID, UserID: validID, DomainID: invitation.DomainID} + if tc.token == valid { + tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID} } authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr) svcCall := svc.On("DeleteInvitation", mock.Anything, tc.session, tc.userID, tc.domainID).Return(tc.svcErr) diff --git a/pkg/sdk/go/sdk.go b/pkg/sdk/go/sdk.go index 62db440981..6b65939768 100644 --- a/pkg/sdk/go/sdk.go +++ b/pkg/sdk/go/sdk.go @@ -1182,9 +1182,9 @@ type SDK interface { // Invitations returns a list of invitations. // // For example: - // invitations, _ := sdk.Invitations(PageMetadata{Offset: 0, Limit: 10}, "domainID", "token") + // invitations, _ := sdk.Invitations(PageMetadata{Offset: 0, Limit: 10}, "token") // fmt.Println(invitations) - Invitations(pm PageMetadata, domainID, token string) (invitations InvitationPage, err error) + Invitations(pm PageMetadata, token string) (invitations InvitationPage, err error) // AcceptInvitation accepts an invitation by adding the user to the domain that they were invited to. // diff --git a/pkg/sdk/mocks/sdk.go b/pkg/sdk/mocks/sdk.go index e3155dbfcf..0b95a2e95f 100644 --- a/pkg/sdk/mocks/sdk.go +++ b/pkg/sdk/mocks/sdk.go @@ -1344,9 +1344,9 @@ func (_m *SDK) Invitation(userID string, domainID string, token string) (sdk.Inv return r0, r1 } -// Invitations provides a mock function with given fields: pm, domainID, token -func (_m *SDK) Invitations(pm sdk.PageMetadata, domainID string, token string) (sdk.InvitationPage, error) { - ret := _m.Called(pm, domainID, token) +// Invitations provides a mock function with given fields: pm, token +func (_m *SDK) Invitations(pm sdk.PageMetadata, token string) (sdk.InvitationPage, error) { + ret := _m.Called(pm, token) if len(ret) == 0 { panic("no return value specified for Invitations") @@ -1354,17 +1354,17 @@ func (_m *SDK) Invitations(pm sdk.PageMetadata, domainID string, token string) ( var r0 sdk.InvitationPage var r1 error - if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) (sdk.InvitationPage, error)); ok { - return rf(pm, domainID, token) + if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string) (sdk.InvitationPage, error)); ok { + return rf(pm, token) } - if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) sdk.InvitationPage); ok { - r0 = rf(pm, domainID, token) + if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string) sdk.InvitationPage); ok { + r0 = rf(pm, token) } else { r0 = ret.Get(0).(sdk.InvitationPage) } - if rf, ok := ret.Get(1).(func(sdk.PageMetadata, string, string) error); ok { - r1 = rf(pm, domainID, token) + if rf, ok := ret.Get(1).(func(sdk.PageMetadata, string) error); ok { + r1 = rf(pm, token) } else { r1 = ret.Error(1) }