NOISSUE - Update removal of view invitation endpoint in sdk and cli (#3055)

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
This commit is contained in:
Felix Gateru
2025-08-13 15:48:12 +03:00
committed by GitHub
parent bc7b988098
commit 8188da16b3
11 changed files with 28 additions and 336 deletions
+5 -4
View File
@@ -206,12 +206,13 @@ jobs:
- "certs/**"
- "http/**"
- "internal/*"
- "internal/api/**"
- "internal/apiutil/**"
- "internal/groups/**"
- "invitations/**"
- "clients/**"
- "users/**"
- "channels/**"
- "domains/**"
- "groups/**"
- "journal/**"
- "api/http/**"
pkg-transformers:
- "pkg/transformers/**"
+5 -5
View File
@@ -28,8 +28,8 @@ tags:
- name: Roles
description: All operations involving roles for clients
externalDocs:
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
- name: Health
description: Health check operations
externalDocs:
@@ -436,7 +436,7 @@ paths:
- bearerAuth: []
responses:
"201":
$ref: "./schemas/roles.yaml#/components/responses/CreateRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/CreateRoleRes"
"400":
description: Failed due to malformed client's ID.
"401":
@@ -946,7 +946,7 @@ components:
ParentGroupReqObj:
type: object
properties:
parent_group_id:
parent_group_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -1337,7 +1337,7 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Client"
ClientPageRes:
description: Data retrieved.
content:
+3 -31
View File
@@ -3,16 +3,16 @@
openapi: 3.0.3
info:
title: Magistrala Domains Service
title: SuperMQ Domains Service
description: |
This is the Domains Server based on the OpenAPI 3.0 specification. It is the HTTP API for managing platform domains. You can now help us improve the API whether it's by making changes to the definition itself or to the code.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
@@ -758,34 +758,6 @@ paths:
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/invitations/{userID}:
get:
operationId: getInvitation
summary: Retrieves a specific invitation
description: |
Retrieves a specific invitation that is identifier by the user ID and domain ID.
tags:
- Invitations
parameters:
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/UserID"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/InvitationRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: deleteInvitation
summary: Deletes a specific invitation
+7 -7
View File
@@ -34,23 +34,22 @@ var cmdInvitations = []cobra.Command{
},
},
{
Use: "get [all | <user_id> <domain_id> ] <user_auth_token>",
Use: "get [all | <domain_id> ] <user_auth_token>",
Short: "Get invitations",
Long: "Get invitations\n" +
"Usage:\n" +
"\tsupermq-cli invitations get all <user_auth_token> - lists all invitations\n" +
"\tsupermq-cli invitations get all <user_auth_token> --offset <offset> --limit <limit> - lists all invitations with provided offset and limit\n" +
"\tsupermq-cli invitations get <user_id> <domain_id> <user_auth_token> - shows invitation by user id and domain id\n",
"\tsupermq-cli invitations get <domain_id> <user_auth_token> - shows invitation by domain id\n",
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 && len(args) != 3 {
if len(args) != 2 {
logUsageCmd(*cmd, cmd.Use)
return
}
pageMetadata := smqsdk.PageMetadata{
Identity: Identity,
Offset: Offset,
Limit: Limit,
Offset: Offset,
Limit: Limit,
}
if args[0] == all {
l, err := sdk.Invitations(cmd.Context(), pageMetadata, args[1])
@@ -61,7 +60,8 @@ var cmdInvitations = []cobra.Command{
logJSONCmd(*cmd, l)
return
}
u, err := sdk.Invitation(cmd.Context(), args[0], args[1], args[2])
pageMetadata.DomainID = args[0]
u, err := sdk.Invitations(cmd.Context(), pageMetadata, args[1])
if err != nil {
logErrorCmd(*cmd, err)
return
+8 -8
View File
@@ -124,14 +124,18 @@ func TestGetInvitationCmd(t *testing.T) {
logType: entityLog,
},
{
desc: "get invitation with user id",
desc: "get invitation with domain id",
args: []string{
user.ID,
domain.ID,
token,
},
logType: entityLog,
inv: invitation,
page: mgsdk.InvitationPage{
Total: 1,
Offset: 0,
Limit: 10,
Invitations: []mgsdk.Invitation{invitation},
},
},
{
desc: "get invitation with invalid args",
@@ -139,7 +143,6 @@ func TestGetInvitationCmd(t *testing.T) {
all,
token,
extraArg,
extraArg,
},
logType: usageLog,
},
@@ -156,7 +159,6 @@ func TestGetInvitationCmd(t *testing.T) {
{
desc: "get invitation with invalid token",
args: []string{
user.ID,
domain.ID,
invalidToken,
},
@@ -168,8 +170,7 @@ func TestGetInvitationCmd(t *testing.T) {
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
sdkCall := sdkMock.On("Invitation", mock.Anything, tc.args[0], tc.args[1], mock.Anything).Return(tc.inv, tc.sdkErr)
sdkCall1 := sdkMock.On("Invitations", mock.Anything, mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr)
sdkCall := sdkMock.On("Invitations", mock.Anything, mock.Anything, tc.args[1]).Return(tc.page, tc.sdkErr)
out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...)
@@ -190,7 +191,6 @@ func TestGetInvitationCmd(t *testing.T) {
assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out))
}
sdkCall.Unset()
sdkCall1.Unset()
})
}
}
-17
View File
@@ -18,7 +18,6 @@ var (
_ supermq.Response = (*disableDomainRes)(nil)
_ supermq.Response = (*freezeDomainRes)(nil)
_ supermq.Response = (*sendInvitationRes)(nil)
_ supermq.Response = (*viewInvitationRes)(nil)
_ supermq.Response = (*listInvitationsRes)(nil)
_ supermq.Response = (*acceptInvitationRes)(nil)
_ supermq.Response = (*rejectInvitationRes)(nil)
@@ -147,22 +146,6 @@ func (res sendInvitationRes) Empty() bool {
return true
}
type viewInvitationRes struct {
domains.Invitation `json:",inline"`
}
func (res viewInvitationRes) Code() int {
return http.StatusOK
}
func (res viewInvitationRes) Headers() map[string]string {
return map[string]string{}
}
func (res viewInvitationRes) Empty() bool {
return false
}
type listInvitationsRes struct {
domains.InvitationPage `json:",inline"`
}
-72
View File
@@ -2458,75 +2458,3 @@ func (_c *Service_UpdateRoleName_Call) RunAndReturn(run func(ctx context.Context
_c.Call.Return(run)
return _c
}
// ViewDomainInvitation provides a mock function for the type Service
func (_mock *Service) ViewDomainInvitation(ctx context.Context, session authn.Session, inviteeUserID string) (domains.Invitation, error) {
ret := _mock.Called(ctx, session, inviteeUserID)
if len(ret) == 0 {
panic("no return value specified for ViewDomainInvitation")
}
var r0 domains.Invitation
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, string) (domains.Invitation, error)); ok {
return returnFunc(ctx, session, inviteeUserID)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, string) domains.Invitation); ok {
r0 = returnFunc(ctx, session, inviteeUserID)
} else {
r0 = ret.Get(0).(domains.Invitation)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, authn.Session, string) error); ok {
r1 = returnFunc(ctx, session, inviteeUserID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Service_ViewDomainInvitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewDomainInvitation'
type Service_ViewDomainInvitation_Call struct {
*mock.Call
}
// ViewDomainInvitation is a helper method to define mock.On call
// - ctx context.Context
// - session authn.Session
// - inviteeUserID string
func (_e *Service_Expecter) ViewDomainInvitation(ctx interface{}, session interface{}, inviteeUserID interface{}) *Service_ViewDomainInvitation_Call {
return &Service_ViewDomainInvitation_Call{Call: _e.mock.On("ViewDomainInvitation", ctx, session, inviteeUserID)}
}
func (_c *Service_ViewDomainInvitation_Call) Run(run func(ctx context.Context, session authn.Session, inviteeUserID string)) *Service_ViewDomainInvitation_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 authn.Session
if args[1] != nil {
arg1 = args[1].(authn.Session)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Service_ViewDomainInvitation_Call) Return(invitation domains.Invitation, err error) *Service_ViewDomainInvitation_Call {
_c.Call.Return(invitation, err)
return _c
}
func (_c *Service_ViewDomainInvitation_Call) RunAndReturn(run func(ctx context.Context, session authn.Session, inviteeUserID string) (domains.Invitation, error)) *Service_ViewDomainInvitation_Call {
_c.Call.Return(run)
return _c
}
-15
View File
@@ -54,21 +54,6 @@ func (sdk mgSDK) SendInvitation(ctx context.Context, invitation Invitation, toke
return sdkErr
}
func (sdk mgSDK) Invitation(ctx context.Context, userID, domainID, token string) (invitation Invitation, err error) {
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.domainsURL, domainsEndpoint, domainID, invitationsEndpoint, userID)
_, body, sdkErr := sdk.processRequest(ctx, http.MethodGet, url, token, nil, nil, http.StatusOK)
if sdkErr != nil {
return Invitation{}, sdkErr
}
if err := json.Unmarshal(body, &invitation); err != nil {
return Invitation{}, errors.NewSDKError(err)
}
return invitation, nil
}
func (sdk mgSDK) DomainInvitations(ctx context.Context, pm PageMetadata, token, domainID string) (invitations InvitationPage, err error) {
url := fmt.Sprintf("%s/%s/%s", domainsEndpoint, domainID, invitationsEndpoint)
url, err = sdk.withQueryParams(sdk.domainsURL, url, pm)
-92
View File
@@ -139,98 +139,6 @@ func TestSendInvitation(t *testing.T) {
}
}
func TestViewInvitation(t *testing.T) {
is, svc, auth := setupDomains()
defer is.Close()
conf := sdk.Config{
DomainsURL: is.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
token string
session smqauthn.Session
userID string
domainID string
svcRes domains.Invitation
svcErr error
authenticateErr error
response sdk.Invitation
err error
}{
{
desc: "view invitation successfully",
token: validToken,
userID: invitation.InviteeUserID,
domainID: invitation.DomainID,
svcRes: invitation,
svcErr: nil,
response: sdkInvitation,
err: nil,
},
{
desc: "view invitation with invalid token",
token: invalidToken,
userID: invitation.InviteeUserID,
domainID: invitation.DomainID,
svcRes: domains.Invitation{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.Invitation{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "view invitation with empty token",
token: "",
userID: invitation.InviteeUserID,
domainID: invitation.DomainID,
svcRes: domains.Invitation{},
svcErr: nil,
response: sdk.Invitation{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "view invitation with empty domainID",
token: validToken,
userID: invitation.InviteeUserID,
domainID: "",
svcRes: domains.Invitation{},
svcErr: nil,
response: sdk.Invitation{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingDomainID, http.StatusBadRequest),
},
{
desc: "view invitation with invalid domainID",
token: validToken,
userID: invitation.InviteeUserID,
domainID: wrongID,
svcRes: domains.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 == valid {
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: fmt.Sprintf("%s_%s", tc.domainID, tc.userID)}
}
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)
resp, err := mgsdk.Invitation(context.Background(), tc.userID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "ViewInvitation", mock.Anything, tc.session, tc.userID, tc.domainID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListInvitation(t *testing.T) {
is, svc, auth := setupDomains()
defer is.Close()
-78
View File
@@ -5504,84 +5504,6 @@ func (_c *SDK_Hierarchy_Call) RunAndReturn(run func(ctx context.Context, id stri
return _c
}
// Invitation provides a mock function for the type SDK
func (_mock *SDK) Invitation(ctx context.Context, userID string, domainID string, token string) (sdk.Invitation, error) {
ret := _mock.Called(ctx, userID, domainID, token)
if len(ret) == 0 {
panic("no return value specified for Invitation")
}
var r0 sdk.Invitation
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string) (sdk.Invitation, error)); ok {
return returnFunc(ctx, userID, domainID, token)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string) sdk.Invitation); ok {
r0 = returnFunc(ctx, userID, domainID, token)
} else {
r0 = ret.Get(0).(sdk.Invitation)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
r1 = returnFunc(ctx, userID, domainID, token)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SDK_Invitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Invitation'
type SDK_Invitation_Call struct {
*mock.Call
}
// Invitation is a helper method to define mock.On call
// - ctx context.Context
// - userID string
// - domainID string
// - token string
func (_e *SDK_Expecter) Invitation(ctx interface{}, userID interface{}, domainID interface{}, token interface{}) *SDK_Invitation_Call {
return &SDK_Invitation_Call{Call: _e.mock.On("Invitation", ctx, userID, domainID, token)}
}
func (_c *SDK_Invitation_Call) Run(run func(ctx context.Context, userID string, domainID string, token string)) *SDK_Invitation_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
var arg3 string
if args[3] != nil {
arg3 = args[3].(string)
}
run(
arg0,
arg1,
arg2,
arg3,
)
})
return _c
}
func (_c *SDK_Invitation_Call) Return(invitation sdk.Invitation, err error) *SDK_Invitation_Call {
_c.Call.Return(invitation, err)
return _c
}
func (_c *SDK_Invitation_Call) RunAndReturn(run func(ctx context.Context, userID string, domainID string, token string) (sdk.Invitation, error)) *SDK_Invitation_Call {
_c.Call.Return(run)
return _c
}
// Invitations provides a mock function for the type SDK
func (_mock *SDK) Invitations(ctx context.Context, pm sdk.PageMetadata, token string) (sdk.InvitationPage, error) {
ret := _mock.Called(ctx, pm, token)
-7
View File
@@ -1285,13 +1285,6 @@ type SDK interface {
// fmt.Println(err)
SendInvitation(ctx context.Context, invitation Invitation, token string) (err error)
// Invitation returns an invitation.
//
// For example:
// invitation, _ := sdk.Invitation("userID", "domainID", "token")
// fmt.Println(invitation)
Invitation(ctx context.Context, userID, domainID, token string) (invitation Invitation, err error)
// Invitations returns a list of invitations.
//
// For example: