From 05b71e13f12f296d44ae11232d85062a71a8ce4b Mon Sep 17 00:00:00 2001 From: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:00:28 +0300 Subject: [PATCH] test: update tests with domains Added test cases to cover the authn and authz functionality of the user service with domains integration. The tests involve mocking function calls, setting up expectations, and checking for expected results. The code includes conditional statements and different scenarios to ensure the proper behavior of the functions. This commit also fixes updating client secret Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --- auth/mocks/service.go | 6 -- users/service.go | 10 +-- users/service_test.go | 151 ++++++++++++++---------------------------- 3 files changed, 53 insertions(+), 114 deletions(-) diff --git a/auth/mocks/service.go b/auth/mocks/service.go index 4107bb098..f174c91d3 100644 --- a/auth/mocks/service.go +++ b/auth/mocks/service.go @@ -25,9 +25,6 @@ func (m *Service) Issue(ctx context.Context, in *magistrala.IssueReq, opts ...gr if in.GetUserId() == InvalidValue || in.GetUserId() == "" { return &magistrala.Token{}, errors.ErrAuthentication } - if in.GetDomainId() == InvalidValue || in.GetDomainId() == "" { - return &magistrala.Token{}, errors.ErrAuthentication - } return ret.Get(0).(*magistrala.Token), ret.Error(1) } @@ -37,9 +34,6 @@ func (m *Service) Refresh(ctx context.Context, in *magistrala.RefreshReq, opts . if in.GetRefreshToken() == InvalidValue || in.GetRefreshToken() == "" { return &magistrala.Token{}, errors.ErrAuthentication } - if in.GetDomainId() == InvalidValue || in.GetDomainId() == "" { - return &magistrala.Token{}, errors.ErrAuthentication - } return ret.Get(0).(*magistrala.Token), ret.Error(1) } diff --git a/users/service.go b/users/service.go index 69b44dfe6..cf5140d4c 100644 --- a/users/service.go +++ b/users/service.go @@ -320,7 +320,7 @@ func (svc service) UpdateClientSecret(ctx context.Context, token, oldSecret, new if err != nil { return mgclients.Client{}, err } - if _, err := svc.IssueToken(ctx, dbClient.Credentials.Identity, "", oldSecret); err != nil { + if _, err := svc.IssueToken(ctx, dbClient.Credentials.Identity, oldSecret, ""); err != nil { return mgclients.Client{}, err } newSecret, err = svc.hasher.Hash(newSecret) @@ -471,12 +471,12 @@ func (svc service) ListMembers(ctx context.Context, token, objectKind string, ob } func (svc *service) checkSuperAdmin(ctx context.Context, adminID string) error { - if err := svc.clients.CheckSuperAdmin(ctx, adminID); err != nil { - return err - } if _, err := svc.authorize(ctx, auth.UserType, auth.UsersKind, adminID, auth.AdminPermission, auth.PlatformType, auth.MagistralaObject); err != nil { - return err + if err := svc.clients.CheckSuperAdmin(ctx, adminID); err != nil { + return err + } } + return nil } diff --git a/users/service_test.go b/users/service_test.go index 0e8c3d5e0..c505aaf8a 100644 --- a/users/service_test.go +++ b/users/service_test.go @@ -44,10 +44,7 @@ var ( validToken = "token" inValidToken = "invalid" validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" - - ownerRelation = "owner" - userKind = "users" - userType = "user" + domainID = testsutil.GenerateUUID(&testing.T{}) ) func TestRegisterClient(t *testing.T) { @@ -244,6 +241,7 @@ func TestRegisterClient(t *testing.T) { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) } repoCall1 := auth.On("AddPolicy", mock.Anything, mock.Anything).Return(&magistrala.AddPolicyRes{Authorized: true}, nil) + repoCall2 := auth.On("DeletePolicy", mock.Anything, mock.Anything).Return(&magistrala.DeletePolicyRes{Deleted: true}, nil) repoCall3 := cRepo.On("Save", context.Background(), mock.Anything).Return(&mgclients.Client{}, tc.err) registerTime := time.Now() expected, err := svc.RegisterClient(context.Background(), tc.token, tc.client) @@ -262,6 +260,7 @@ func TestRegisterClient(t *testing.T) { assert.True(t, ok, fmt.Sprintf("Save was not called on %s", tc.desc)) } repoCall3.Unset() + repoCall2.Unset() repoCall1.Unset() repoCall.Unset() } @@ -311,20 +310,11 @@ func TestViewClient(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.clientID, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) - authReq.Subject = mock.Anything - repoCall1 = auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) + repoCall1 = auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) } repoCall2 := cRepo.On("RetrieveByID", context.Background(), tc.clientID).Return(tc.response, tc.err) @@ -608,20 +598,22 @@ func TestListClients(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) } - repoCall1 := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.response, tc.err) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall2 := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.response, tc.err) page, err := svc.ListClients(context.Background(), tc.token, tc.page) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) assert.Equal(t, tc.response, page, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, page)) if tc.err == nil { - ok := repoCall1.Parent.AssertCalled(t, "RetrieveAll", context.Background(), mock.Anything) + ok := repoCall2.Parent.AssertCalled(t, "RetrieveAll", context.Background(), mock.Anything) assert.True(t, ok, fmt.Sprintf("RetrieveAll was not called on %s", tc.desc)) } repoCall.Unset() repoCall1.Unset() + repoCall2.Unset() } } @@ -684,20 +676,11 @@ func TestUpdateClient(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.client.ID, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) - authReq.Subject = mock.Anything - repoCall1 = auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) + repoCall1 = auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) } repoCall2 := cRepo.On("Update", context.Background(), mock.Anything).Return(tc.response, tc.err) updatedClient, err := svc.UpdateClient(context.Background(), tc.token, tc.client) @@ -755,20 +738,11 @@ func TestUpdateClientTags(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.client.ID, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) - authReq.Subject = mock.Anything - repoCall1 = auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) + repoCall1 = auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) } repoCall2 := cRepo.On("UpdateTags", context.Background(), mock.Anything).Return(tc.response, tc.err) updatedClient, err := svc.UpdateClientTags(context.Background(), tc.token, tc.client) @@ -828,20 +802,11 @@ func TestUpdateClientIdentity(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.id, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) - authReq.Subject = mock.Anything - repoCall1 = auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) + repoCall1 = auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) } repoCall2 := cRepo.On("UpdateIdentity", context.Background(), mock.Anything).Return(tc.response, tc.err) updatedClient, err := svc.UpdateClientIdentity(context.Background(), tc.token, tc.id, tc.identity) @@ -899,29 +864,13 @@ func TestUpdateClientOwner(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.client.ID, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) - deleteReq := &magistrala.DeletePolicyReq{ - SubjectType: userType, - Subject: validID, - Relation: ownerRelation, - ObjectType: userType, - Object: tc.client.ID, - } - repoCall2 := auth.On("DeletePolicy", mock.Anything, deleteReq).Return(&magistrala.DeletePolicyRes{Deleted: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall2 := auth.On("DeletePolicy", mock.Anything, mock.Anything).Return(&magistrala.DeletePolicyRes{Deleted: true}, nil) repoCall3 := auth.On("AddPolicy", mock.Anything, mock.Anything).Return(&magistrala.AddPolicyRes{Authorized: true}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) - authReq.Subject = mock.Anything - repoCall1 = auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) + repoCall1 = auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) } repoCall4 := cRepo.On("UpdateOwner", context.Background(), mock.Anything).Return(tc.response, tc.err) updatedClient, err := svc.UpdateClientRole(context.Background(), tc.token, tc.client) @@ -939,7 +888,7 @@ func TestUpdateClientOwner(t *testing.T) { } } -func TestUpdateClientRole(t *testing.T) { +func TestUpdateClientSecret(t *testing.T) { cRepo := new(mocks.Repository) auth := new(authmocks.Service) e := mocks.NewEmailer() @@ -983,7 +932,7 @@ func TestUpdateClientRole(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: client.ID}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: client.ID}, nil) if tc.token == inValidToken { repoCall = auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: inValidToken}).Return(&magistrala.IdentityRes{}, errors.ErrAuthentication) } @@ -1056,16 +1005,8 @@ func TestEnableClient(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.id, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) repoCall2 := cRepo.On("RetrieveByID", context.Background(), tc.id).Return(tc.client, tc.err) repoCall3 := cRepo.On("ChangeStatus", context.Background(), mock.Anything).Return(tc.response, tc.err) _, err := svc.EnableClient(context.Background(), tc.token, tc.id) @@ -1135,14 +1076,16 @@ func TestEnableClient(t *testing.T) { Limit: 100, Status: tc.status, } - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: client.ID}, nil) - repoCall1 := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.response, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: client.ID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall2 := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.response, nil) page, err := svc.ListClients(context.Background(), validToken, pm) require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) size := uint64(len(page.Clients)) assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", tc.desc, tc.size, size)) repoCall.Unset() repoCall1.Unset() + repoCall2.Unset() } } @@ -1192,16 +1135,8 @@ func TestDisableClient(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: validID}, nil) - authReq := &magistrala.AuthorizeReq{ - SubjectType: userType, - SubjectKind: userKind, - Subject: validID, - Permission: ownerRelation, - ObjectType: userType, - Object: tc.id, - } - repoCall1 := auth.On("Authorize", mock.Anything, authReq).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: validID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) repoCall2 := cRepo.On("RetrieveByID", context.Background(), tc.id).Return(tc.client, tc.err) repoCall3 := cRepo.On("ChangeStatus", context.Background(), mock.Anything).Return(tc.response, tc.err) _, err := svc.DisableClient(context.Background(), tc.token, tc.id) @@ -1271,14 +1206,16 @@ func TestDisableClient(t *testing.T) { Limit: 100, Status: tc.status, } - repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{Id: client.ID}, nil) - repoCall1 := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.response, nil) + repoCall := auth.On("Identify", mock.Anything, &magistrala.IdentityReq{Token: validToken}).Return(&magistrala.IdentityRes{UserId: client.ID}, nil) + repoCall1 := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall2 := cRepo.On("RetrieveAll", context.Background(), mock.Anything).Return(tc.response, nil) page, err := svc.ListClients(context.Background(), validToken, pm) require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) size := uint64(len(page.Clients)) assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", tc.desc, tc.size, size)) repoCall.Unset() repoCall1.Unset() + repoCall2.Unset() } } @@ -1383,12 +1320,12 @@ func TestListMembers(t *testing.T) { } for _, tc := range cases { - repoCall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true}, nil) + repoCall := auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: true, Id: validID}, nil) if tc.token == inValidToken { repoCall = auth.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.AuthorizeRes{Authorized: false}, errors.ErrAuthorization) } - repoCall1 := auth.On("ListAllSubjects", mock.Anything, mock.Anything).Return(&magistrala.ListSubjectsRes{Policies: clientsToUUIDs(tc.response.Members)}, nil) + repoCall1 := auth.On("ListAllSubjects", mock.Anything, mock.Anything).Return(&magistrala.ListSubjectsRes{Policies: prefixClientUUIDSWithDomain(tc.response.Members)}, nil) repoCall2 := cRepo.On("RetrieveAll", context.Background(), tc.page).Return(mgclients.ClientsPage{Page: tc.response.Page, Clients: tc.response.Members}, tc.err) page, err := svc.ListMembers(context.Background(), tc.token, "groups", tc.groupID, tc.page) assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) @@ -1524,3 +1461,11 @@ func clientsToUUIDs(clients []mgclients.Client) []string { } return ids } + +func prefixClientUUIDSWithDomain(clients []mgclients.Client) []string { + ids := []string{} + for _, c := range clients { + ids = append(ids, fmt.Sprintf("%s_%s", domainID, c.ID)) + } + return ids +}