From ae2c156c0e0132fcd601f562482b68dc5be8ffcf Mon Sep 17 00:00:00 2001 From: Maurizio Vitale Date: Fri, 1 Jul 2022 14:20:40 +0100 Subject: [PATCH] [AAE-9382] SSOGuard - Call the acs user only in case of ECM (#7696) * Call the acs user only * Fix and add unit test --- .../auth-guard-sso-role.service.spec.ts | 24 +++---- .../services/auth-guard-sso-role.service.ts | 8 +-- .../user-content-access.service.spec.ts | 68 +++++++++++++++++++ .../services/user-content-access.service.ts | 44 ++++++++++++ 4 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 lib/core/services/user-content-access.service.spec.ts create mode 100644 lib/core/services/user-content-access.service.ts diff --git a/lib/core/services/auth-guard-sso-role.service.spec.ts b/lib/core/services/auth-guard-sso-role.service.spec.ts index b8f30eb64f..4b41eed98e 100644 --- a/lib/core/services/auth-guard-sso-role.service.spec.ts +++ b/lib/core/services/auth-guard-sso-role.service.spec.ts @@ -23,16 +23,15 @@ import { AuthGuardSsoRoleService } from './auth-guard-sso-role.service'; import { JwtHelperService } from './jwt-helper.service'; import { MatDialog } from '@angular/material/dialog'; import { TranslateModule } from '@ngx-translate/core'; -import { PeopleContentService } from './people-content.service'; import { UserAccessService } from './user-access.service'; -import { of } from 'rxjs'; +import { UserContentAccessService } from './user-content-access.service'; describe('Auth Guard SSO role service', () => { let authGuard: AuthGuardSsoRoleService; let jwtHelperService: JwtHelperService; let routerService: Router; - let peopleContentService: PeopleContentService; + let userContentAccessService: UserContentAccessService; let userAccessService: UserAccessService; setupTestBed({ @@ -47,7 +46,7 @@ describe('Auth Guard SSO role service', () => { authGuard = TestBed.inject(AuthGuardSsoRoleService); jwtHelperService = TestBed.inject(JwtHelperService); routerService = TestBed.inject(Router); - peopleContentService = TestBed.inject(PeopleContentService); + userContentAccessService = TestBed.inject(UserContentAccessService); userAccessService = TestBed.inject(UserAccessService); userAccessService.resetAccess(); }); @@ -126,7 +125,7 @@ describe('Auth Guard SSO role service', () => { it('Should canActivate be false hasRealm is true and hasClientRole is false', async () => { const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - spyUserAccess([], {}); + spyUserAccess([''], {}); route.params = { appName: 'mockApp' }; route.data = { clientRoles: ['appName'], roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] }; @@ -182,8 +181,7 @@ describe('Auth Guard SSO role service', () => { describe('Content Admin', () => { it('Should give access to a content section (ALFRESCO_ADMINISTRATORS) when the user has content admin capability', async () => { - spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({})); - spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(true); + spyOn(userContentAccessService, 'isCurrentUserAdmin').and.returnValue(true); spyUserAccess([], {}); @@ -194,8 +192,7 @@ describe('Auth Guard SSO role service', () => { }); it('Should not give access to a content section (ALFRESCO_ADMINISTRATORS) when the user does not have content admin capability', async () => { - spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({})); - spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(false); + spyOn(userContentAccessService, 'isCurrentUserAdmin').and.returnValue(false); spyUserAccess([], {}); @@ -206,7 +203,7 @@ describe('Auth Guard SSO role service', () => { }); it('Should not call the service to check if the user has content admin capability when the roles do not contain ALFRESCO_ADMINISTRATORS', async () => { - const isCurrentAdminSpy = spyOn(peopleContentService, 'isCurrentUserAdmin').and.stub(); + const isCurrentAdminSpy = spyOn(userContentAccessService, 'isCurrentUserAdmin').and.stub(); spyUserAccess([], {}); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -238,8 +235,7 @@ describe('Auth Guard SSO role service', () => { }); it('Should canActivate be true when the user has none of the excluded role and is not a content admin', async () => { - spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({})); - spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(false); + spyOn(userContentAccessService, 'isCurrentUserAdmin').and.returnValue(false); spyUserAccess(['MOCK_USER_ROLE'], {}); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -249,15 +245,13 @@ describe('Auth Guard SSO role service', () => { }); it('Should canActivate be false if the user is a content admin but has one of the excluded roles', async () => { - const isCurrentAdminSpy = spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({})); - spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(true); + spyOn(userContentAccessService, 'isCurrentUserAdmin').and.returnValue(true); spyUserAccess(['MOCK_USER_ROLE'], {}); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); router.data = { roles: ['ALFRESCO_ADMINISTRATORS'], excludedRoles: ['MOCK_USER_ROLE'] }; expect(await authGuard.canActivate(router)).toBe(false); - expect(isCurrentAdminSpy).toHaveBeenCalled(); }); }); }); diff --git a/lib/core/services/auth-guard-sso-role.service.ts b/lib/core/services/auth-guard-sso-role.service.ts index a023036115..55436816db 100644 --- a/lib/core/services/auth-guard-sso-role.service.ts +++ b/lib/core/services/auth-guard-sso-role.service.ts @@ -18,8 +18,9 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; -import { ContentGroups, PeopleContentService } from './people-content.service'; +import { ContentGroups } from './people-content.service'; import { UserAccessService } from './user-access.service'; +import { UserContentAccessService } from './user-content-access.service'; @Injectable({ providedIn: 'root' @@ -28,7 +29,7 @@ export class AuthGuardSsoRoleService implements CanActivate { constructor(private userAccessService: UserAccessService, private router: Router, private dialog: MatDialog, - private peopleContentService: PeopleContentService) { + private userContentAccessService: UserContentAccessService) { } async canActivate(route: ActivatedRouteSnapshot): Promise { @@ -74,8 +75,7 @@ export class AuthGuardSsoRoleService implements CanActivate { private async hasRoles(roles: string[] = []): Promise { if (this.containsAlfrescoAdminRole(roles)) { - await this.peopleContentService.getCurrentUserInfo().toPromise(); - return this.peopleContentService.isCurrentUserAdmin() || this.userAccessService.hasGlobalAccess(roles); + return await this.userContentAccessService.isCurrentUserAdmin() || this.userAccessService.hasGlobalAccess(roles); } return this.userAccessService.hasGlobalAccess(roles); } diff --git a/lib/core/services/user-content-access.service.spec.ts b/lib/core/services/user-content-access.service.spec.ts new file mode 100644 index 0000000000..834f8c080e --- /dev/null +++ b/lib/core/services/user-content-access.service.spec.ts @@ -0,0 +1,68 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CoreTestingModule, setupTestBed } from '../testing'; +import { TestBed } from '@angular/core/testing'; +import { of } from 'rxjs'; +import { AppConfigService } from '../app-config'; +import { UserContentAccessService } from './user-content-access.service'; +import { PeopleContentService } from './people-content.service'; + +describe('UserContentAccessService', () => { + let userContentAccessService: UserContentAccessService; + let peopleContentService: PeopleContentService; + let appConfigService: AppConfigService; + + setupTestBed({ + imports: [CoreTestingModule], + providers: [UserContentAccessService] + }); + + beforeEach(() => { + userContentAccessService = TestBed.inject(UserContentAccessService); + peopleContentService = TestBed.inject(PeopleContentService); + appConfigService = TestBed.inject(AppConfigService); + }); + + it('should return true if user is content admin and provider is ECM', async () => { + appConfigService.config.providers = 'ECM'; + spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({})); + spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(true); + const isContentAdmin = await userContentAccessService.isCurrentUserAdmin(); + + expect(isContentAdmin).toEqual(true); + }); + + it('should return true if user is content admin and provider is ALL', async () => { + appConfigService.config.providers = 'ALL'; + spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({})); + spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(true); + const isContentAdmin = await userContentAccessService.isCurrentUserAdmin(); + + expect(isContentAdmin).toEqual(true); + }); + + it('should return false if provider is BPM', async () => { + appConfigService.config.providers = 'BPM'; + const isCurrentUserAdminSpy = spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(true); + const isContentAdmin = await userContentAccessService.isCurrentUserAdmin(); + + expect(isContentAdmin).toEqual(false); + expect(isCurrentUserAdminSpy).not.toHaveBeenCalled(); + }); + +}); diff --git a/lib/core/services/user-content-access.service.ts b/lib/core/services/user-content-access.service.ts new file mode 100644 index 0000000000..4540576fe2 --- /dev/null +++ b/lib/core/services/user-content-access.service.ts @@ -0,0 +1,44 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { AppConfigService } from '../app-config/app-config.service'; +import { PeopleContentService } from './people-content.service'; + +@Injectable({ + providedIn: 'root' +}) +export class UserContentAccessService { + + constructor( + private appConfigService: AppConfigService, + private peopleContentService: PeopleContentService) { + } + + private hasContentProvider(): boolean { + return this.appConfigService.get('providers') === 'ECM' || this.appConfigService.get('providers') === 'ALL'; + } + + async isCurrentUserAdmin(): Promise { + if( this.hasContentProvider()) { + await this.peopleContentService.getCurrentUserInfo().toPromise(); + return this.peopleContentService.isCurrentUserAdmin(); + } + return false; + } + +}