mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
Fetch the userInfo once loggedIn and expose the capability of admin (#7682)
* Fetch the userInfo once loggedIn and expose the cabilibility of admin * Rollback method * Return same use if defined * Use the same pepleContent service for UserInfoCOmpnent * Remove useless import * Use interface * Use angular resolver instead of guard * Remove fdescribe * Fix linting * Regenerate doc * Improve doc * Fix optional * Fix the unit test * Fix comment * Fix lint * Fix unit * Add fetch user as part of the ssoGuard * Fix unit test after fetch * Add additional unit * Fix await
This commit is contained in:
@@ -149,7 +149,7 @@ describe('ColumnsSelectorComponent', () => {
|
||||
const firstColumnCheckbox = await loader.getHarness(MatCheckboxHarness);
|
||||
const checkBoxName = await firstColumnCheckbox.getLabelText();
|
||||
|
||||
let toggledColumnItem = component.columnItems.find(item => item.title === checkBoxName);
|
||||
const toggledColumnItem = component.columnItems.find(item => item.title === checkBoxName);
|
||||
expect(toggledColumnItem.isHidden).toBeFalsy();
|
||||
|
||||
await firstColumnCheckbox.toggle();
|
||||
|
@@ -17,7 +17,6 @@
|
||||
|
||||
import { EcmCompanyModel } from '../models/ecm-company.model';
|
||||
import { PersonEntry, Person, PersonPaging } from '@alfresco/js-api';
|
||||
import { EcmUserModel } from '../models';
|
||||
|
||||
export const fakeEcmCompany: EcmCompanyModel = {
|
||||
organization: 'company-fake-name',
|
||||
@@ -30,7 +29,7 @@ export const fakeEcmCompany: EcmCompanyModel = {
|
||||
email: 'fakeCompany@fake.com'
|
||||
};
|
||||
|
||||
export const fakeEcmUser = new EcmUserModel({
|
||||
export const fakeEcmUser = {
|
||||
id: 'fake-id',
|
||||
firstName: 'fake-ecm-first-name',
|
||||
lastName: 'fake-ecm-last-name',
|
||||
@@ -49,7 +48,14 @@ export const fakeEcmUser = new EcmUserModel({
|
||||
userStatus: 'active',
|
||||
enabled: true,
|
||||
emailNotificationsEnabled: true
|
||||
});
|
||||
};
|
||||
|
||||
export const fakeEcmAdminUser = {
|
||||
...fakeEcmUser,
|
||||
capabilities: {
|
||||
isAdmin: true
|
||||
}
|
||||
};
|
||||
|
||||
export const fakeEcmUser2 = {
|
||||
id: 'another-fake-id',
|
||||
|
@@ -65,4 +65,8 @@ export class EcmUserModel {
|
||||
this.properties = obj && obj.properties;
|
||||
this.capabilities = obj && obj.capabilities;
|
||||
}
|
||||
|
||||
isAdmin(): boolean {
|
||||
return this.capabilities?.isAdmin;
|
||||
}
|
||||
}
|
||||
|
@@ -24,10 +24,8 @@ 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 { of } from 'rxjs';
|
||||
import { getFakeUserWithContentAdminCapability, getFakeUserWithContentUserCapability } from '../mock/ecm-user.service.mock';
|
||||
import { UserAccessService } from './user-access.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
describe('Auth Guard SSO role service', () => {
|
||||
|
||||
@@ -36,7 +34,6 @@ describe('Auth Guard SSO role service', () => {
|
||||
let routerService: Router;
|
||||
let peopleContentService: PeopleContentService;
|
||||
let userAccessService: UserAccessService;
|
||||
let appConfig: AppConfigService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
@@ -46,8 +43,6 @@ describe('Auth Guard SSO role service', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
appConfig = TestBed.inject(AppConfigService);
|
||||
appConfig.config.providers = 'ECM';
|
||||
localStorage.clear();
|
||||
authGuard = TestBed.inject(AuthGuardSsoRoleService);
|
||||
jwtHelperService = TestBed.inject(JwtHelperService);
|
||||
@@ -186,76 +181,51 @@ describe('Auth Guard SSO role service', () => {
|
||||
|
||||
describe('Content Admin', () => {
|
||||
|
||||
afterEach(() => {
|
||||
peopleContentService.hasCheckedIsContentAdmin = false;
|
||||
});
|
||||
|
||||
it('Should give access to a content section (ALFRESCO_ADMINISTRATORS) when the user has content admin capability', async () => {
|
||||
spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentAdminCapability()));
|
||||
spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({}));
|
||||
spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(true);
|
||||
|
||||
spyUserAccess([], {});
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['ALFRESCO_ADMINISTRATORS'] };
|
||||
|
||||
expect(await authGuard.canActivate(router)).toBeTruthy();
|
||||
expect(await authGuard.canActivate(router)).toBe(true);
|
||||
});
|
||||
|
||||
it('Should not give access to a content section (ALFRESCO_ADMINISTRATORS) when the user does not have content admin capability', async () => {
|
||||
spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentUserCapability()));
|
||||
spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of({}));
|
||||
spyOn(peopleContentService, 'isCurrentUserAdmin').and.returnValue(false);
|
||||
|
||||
spyUserAccess([], {});
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['ALFRESCO_ADMINISTRATORS'] };
|
||||
|
||||
expect(await authGuard.canActivate(router)).toBeFalsy();
|
||||
expect(await authGuard.canActivate(router)).toBe(false);
|
||||
});
|
||||
|
||||
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 getCurrentPersonSpy = spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentAdminCapability()));
|
||||
const isCurrentAdminSpy = spyOn(peopleContentService, 'isCurrentUserAdmin').and.stub();
|
||||
spyUserAccess([], {});
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['fakeRole'] };
|
||||
|
||||
await authGuard.canActivate(router);
|
||||
|
||||
expect(getCurrentPersonSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should not retrieve the user when the provider is BPM', async () => {
|
||||
spyUserAccess([], {});
|
||||
spyOn(peopleContentService, 'getCurrentPerson');
|
||||
appConfig.config.providers = 'BPM';
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['ALFRESCO_ADMINISTRATORS'] };
|
||||
|
||||
const result = await authGuard.canActivate(router);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
expect(peopleContentService.getCurrentPerson).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should not fail when the people service throws an error', async () => {
|
||||
spyUserAccess([], {});
|
||||
spyOn(peopleContentService, 'getCurrentPerson').and.throwError('404 Not found');
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['ALFRESCO_ADMINISTRATORS'] };
|
||||
|
||||
const result = await authGuard.canActivate(router);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
expect(peopleContentService.getCurrentPerson).toHaveBeenCalled();
|
||||
expect(isCurrentAdminSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Excluded Roles', () => {
|
||||
it('Should canActivate be false when the user has one of the excluded roles', async () => {
|
||||
spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentAdminCapability()));
|
||||
spyUserAccess(['MOCK_USER_ROLE'], {});
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['ALFRESCO_ADMINISTRATORS'], excludedRoles: ['MOCK_USER_ROLE'] };
|
||||
router.data = { roles: ['MOCK_ANOTHER_ROLE'], excludedRoles: ['MOCK_USER_ROLE'] };
|
||||
|
||||
expect(await authGuard.canActivate(router)).toBeFalsy();
|
||||
expect(await authGuard.canActivate(router)).toBe(false);
|
||||
});
|
||||
|
||||
it('Should canActivate be true when the user has none of the excluded roles', async () => {
|
||||
@@ -263,18 +233,31 @@ describe('Auth Guard SSO role service', () => {
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'], excludedRoles: ['MOCK_ROOT_USER_ROLE'] };
|
||||
|
||||
expect(await authGuard.canActivate(router)).toBeTruthy();
|
||||
const result = await authGuard.canActivate(router);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should canActivate be false when the user is a content admin and the ALFRESCO_ADMINISTRATORS role is excluded', async () => {
|
||||
spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentAdminCapability()));
|
||||
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);
|
||||
spyUserAccess(['MOCK_USER_ROLE'], {});
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
router.data = { roles: ['MOCK_USER_ROLE'], excludedRoles: ['ALFRESCO_ADMINISTRATORS'] };
|
||||
|
||||
expect(await authGuard.canActivate(router)).toBeFalsy();
|
||||
expect(await authGuard.canActivate(router)).toBe(true);
|
||||
});
|
||||
|
||||
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);
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -20,7 +20,6 @@ import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ContentGroups, PeopleContentService } from './people-content.service';
|
||||
import { UserAccessService } from './user-access.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -29,15 +28,13 @@ export class AuthGuardSsoRoleService implements CanActivate {
|
||||
constructor(private userAccessService: UserAccessService,
|
||||
private router: Router,
|
||||
private dialog: MatDialog,
|
||||
private peopleContentService: PeopleContentService,
|
||||
private appConfig: AppConfigService) {
|
||||
private peopleContentService: PeopleContentService) {
|
||||
}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
await this.userAccessService.fetchUserAccess();
|
||||
let hasRealmRole = false;
|
||||
let hasClientRole = true;
|
||||
|
||||
if (route.data) {
|
||||
if (route.data['roles']) {
|
||||
const rolesToCheck: string[] = route.data['roles'];
|
||||
@@ -45,11 +42,7 @@ export class AuthGuardSsoRoleService implements CanActivate {
|
||||
hasRealmRole = true;
|
||||
} else {
|
||||
const excludedRoles = route.data['excludedRoles'] || [];
|
||||
let isContentAdmin = false;
|
||||
if (this.checkContentAdministratorRole(rolesToCheck, excludedRoles)) {
|
||||
isContentAdmin = await this.peopleContentService.isContentAdmin().catch(() => false);
|
||||
}
|
||||
hasRealmRole = excludedRoles.length ? this.checkAccessWithExcludedRoles(rolesToCheck, excludedRoles, isContentAdmin) : this.hasRoles(rolesToCheck, isContentAdmin);
|
||||
hasRealmRole = await this.validateRoles(rolesToCheck, excludedRoles);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +52,6 @@ export class AuthGuardSsoRoleService implements CanActivate {
|
||||
hasClientRole = this.userAccessService.hasApplicationAccess(clientRoleName, rolesToCheck);
|
||||
}
|
||||
}
|
||||
|
||||
const hasRole = hasRealmRole && hasClientRole;
|
||||
|
||||
if (!hasRole && route?.data && route.data['redirectUrl']) {
|
||||
@@ -73,19 +65,23 @@ export class AuthGuardSsoRoleService implements CanActivate {
|
||||
return hasRole;
|
||||
}
|
||||
|
||||
private checkContentAdministratorRole(rolesToCheck: string[], excludedRoles: string[]): boolean {
|
||||
const hasContentProvider = this.appConfig.config.providers === 'ECM' || this.appConfig.config.providers === 'ALL';
|
||||
const checkAdminRole = rolesToCheck.includes(ContentGroups.ALFRESCO_ADMINISTRATORS) || excludedRoles.includes(ContentGroups.ALFRESCO_ADMINISTRATORS);
|
||||
return hasContentProvider && checkAdminRole;
|
||||
private async validateRoles(rolesToCheck: string[], excludedRoles?: string[]): Promise<boolean> {
|
||||
if (excludedRoles?.length > 0) {
|
||||
return await this.hasRoles(rolesToCheck) && !await this.hasRoles(excludedRoles);
|
||||
}
|
||||
return this.hasRoles(rolesToCheck);
|
||||
}
|
||||
|
||||
private checkAccessWithExcludedRoles(rolesToCheck: string[], excludedRoles: string[], isContentAdmin: boolean): boolean {
|
||||
return this.hasRoles(rolesToCheck, isContentAdmin) && !this.hasRoles(excludedRoles, isContentAdmin);
|
||||
private async hasRoles(roles: string[] = []): Promise<boolean> {
|
||||
if (this.containsAlfrescoAdminRole(roles)) {
|
||||
await this.peopleContentService.getCurrentUserInfo().toPromise();
|
||||
return this.peopleContentService.isCurrentUserAdmin() || this.userAccessService.hasGlobalAccess(roles);
|
||||
}
|
||||
return this.userAccessService.hasGlobalAccess(roles);
|
||||
}
|
||||
|
||||
private hasRoles(rolesToCheck: string[], isContentAdmin: boolean): boolean {
|
||||
return rolesToCheck.includes(ContentGroups.ALFRESCO_ADMINISTRATORS)
|
||||
? this.userAccessService.hasGlobalAccess(rolesToCheck) || isContentAdmin
|
||||
: this.userAccessService.hasGlobalAccess(rolesToCheck);
|
||||
private containsAlfrescoAdminRole(roles: string []): boolean {
|
||||
return roles.includes(ContentGroups.ALFRESCO_ADMINISTRATORS);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,16 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { fakeEcmUser, fakeEcmUserList, createNewPersonMock, getFakeUserWithContentAdminCapability } from '../mock/ecm-user.service.mock';
|
||||
import { fakeEcmUserList, createNewPersonMock, fakeEcmUser, fakeEcmAdminUser } from '../mock/ecm-user.service.mock';
|
||||
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { PeopleContentService, PeopleContentQueryResponse, PeopleContentQueryRequestModel } from './people-content.service';
|
||||
import { PeopleContentService, PeopleContentQueryRequestModel } from './people-content.service';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { LogService } from './log.service';
|
||||
import { PersonEntry } from '@alfresco/js-api';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
describe('PeopleContentService', () => {
|
||||
|
||||
@@ -48,58 +48,31 @@ describe('PeopleContentService', () => {
|
||||
logService = TestBed.inject(LogService);
|
||||
});
|
||||
|
||||
it('should be able to fetch person details based on id', (done) => {
|
||||
spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
|
||||
peopleContentService.getPerson('fake-id').subscribe((person) => {
|
||||
expect(person.entry.id).toEqual('fake-id');
|
||||
expect(person.entry.email).toEqual('fakeEcm@ecmUser.com');
|
||||
done();
|
||||
});
|
||||
it('should be able to fetch person details based on id', async () => {
|
||||
spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(of({entry: fakeEcmUser }));
|
||||
const person = await peopleContentService.getPerson('fake-id').toPromise();
|
||||
expect(person.id).toEqual('fake-id');
|
||||
expect(person.email).toEqual('fakeEcm@ecmUser.com');
|
||||
});
|
||||
|
||||
it('calls getPerson api method by an id', (done) => {
|
||||
const getPersonSpy = spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(null));
|
||||
peopleContentService.getPerson('fake-id').subscribe(() => {
|
||||
expect(getPersonSpy).toHaveBeenCalledWith('fake-id');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be able to list people', async () => {
|
||||
spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(of(fakeEcmUserList));
|
||||
const response = await peopleContentService.listPeople().toPromise();
|
||||
const people = response.entries;
|
||||
const pagination = response.pagination;
|
||||
|
||||
it('calls getPerson api method with "-me-"', (done) => {
|
||||
const getPersonSpy = spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(null));
|
||||
peopleContentService.getPerson('-me-').subscribe(() => {
|
||||
expect(getPersonSpy).toHaveBeenCalledWith('-me-');
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(people).toBeDefined();
|
||||
expect(people[0].id).toEqual('fake-id');
|
||||
expect(people[1].id).toEqual('another-fake-id');
|
||||
expect(pagination.count).toEqual(2);
|
||||
expect(pagination.totalItems).toEqual(2);
|
||||
expect(pagination.hasMoreItems).toBeFalsy();
|
||||
expect(pagination.skipCount).toEqual(0);
|
||||
|
||||
it('should be able to list people', (done) => {
|
||||
spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
|
||||
peopleContentService.listPeople().subscribe((response: PeopleContentQueryResponse) => {
|
||||
const people = response.entries;
|
||||
const pagination = response.pagination;
|
||||
|
||||
expect(people).toBeDefined();
|
||||
expect(people[0].id).toEqual('fake-id');
|
||||
expect(people[1].id).toEqual('another-fake-id');
|
||||
expect(pagination.count).toEqual(2);
|
||||
expect(pagination.totalItems).toEqual(2);
|
||||
expect(pagination.hasMoreItems).toBeFalsy();
|
||||
expect(pagination.skipCount).toEqual(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call listPeople api method', (done) => {
|
||||
const listPeopleSpy = spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
|
||||
peopleContentService.listPeople().subscribe(() => {
|
||||
expect(listPeopleSpy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call listPeople api with requested sorting params', async () => {
|
||||
const listPeopleSpy = spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
|
||||
const listPeopleSpy = spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(of(fakeEcmUserList));
|
||||
const requestQueryParams: PeopleContentQueryRequestModel = { skipCount: 10, maxItems: 20, sorting: { orderBy: 'firstName', direction: 'asc' } };
|
||||
const expectedValue = { skipCount: 10, maxItems: 20, orderBy: ['firstName ASC'] };
|
||||
|
||||
@@ -109,7 +82,7 @@ describe('PeopleContentService', () => {
|
||||
});
|
||||
|
||||
it('should not call listPeople api with sorting params if sorting is not defined', async () => {
|
||||
const listPeopleSpy = spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
|
||||
const listPeopleSpy = spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(of(fakeEcmUserList));
|
||||
const requestQueryParams: PeopleContentQueryRequestModel = { skipCount: 10, maxItems: 20, sorting: undefined };
|
||||
const expectedValue = { skipCount: 10, maxItems: 20 };
|
||||
|
||||
@@ -118,60 +91,48 @@ describe('PeopleContentService', () => {
|
||||
expect(listPeopleSpy).toHaveBeenCalledWith(expectedValue);
|
||||
});
|
||||
|
||||
it('should be able to create new person', (done) => {
|
||||
spyOn(peopleContentService.peopleApi, 'createPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
|
||||
peopleContentService.createPerson(createNewPersonMock).subscribe((person) => {
|
||||
expect(person.id).toEqual('fake-id');
|
||||
expect(person.email).toEqual('fakeEcm@ecmUser.com');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to call createPerson api with new person details', (done) => {
|
||||
const createPersonSpy = spyOn(peopleContentService.peopleApi, 'createPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
|
||||
peopleContentService.createPerson(createNewPersonMock).subscribe((person) => {
|
||||
expect(person.id).toEqual('fake-id');
|
||||
expect(person.email).toEqual('fakeEcm@ecmUser.com');
|
||||
expect(createPersonSpy).toHaveBeenCalledWith(createNewPersonMock, undefined);
|
||||
done();
|
||||
});
|
||||
it('should be able to create new person', async () => {
|
||||
spyOn(peopleContentService.peopleApi, 'createPerson').and.returnValue(of({entry: fakeEcmUser }));
|
||||
const newUser = await peopleContentService.createPerson(createNewPersonMock).toPromise();
|
||||
expect(newUser.id).toEqual('fake-id');
|
||||
expect(newUser.email).toEqual('fakeEcm@ecmUser.com');
|
||||
});
|
||||
|
||||
it('should be able to throw an error if createPerson api failed', (done) => {
|
||||
const createPersonSpy = spyOn(peopleContentService.peopleApi, 'createPerson').and.returnValue(Promise.reject({ message: 'failed to create new person' }));
|
||||
spyOn(peopleContentService.peopleApi, 'createPerson').and.returnValue(Promise.reject('failed to create new person'));
|
||||
const logErrorSpy = spyOn(logService, 'error');
|
||||
peopleContentService.createPerson(createNewPersonMock).subscribe(
|
||||
() => {},
|
||||
(error) => {
|
||||
expect(error).toEqual({ message: 'failed to create new person' });
|
||||
expect(createPersonSpy).toHaveBeenCalled();
|
||||
expect(logErrorSpy).toHaveBeenCalledWith({ message: 'failed to create new person' });
|
||||
done();
|
||||
});
|
||||
() => {},
|
||||
(error) => {
|
||||
expect(logErrorSpy).toHaveBeenCalledWith('failed to create new person');
|
||||
expect(error).toEqual('failed to create new person');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should make the api call to check if the user is a content admin only once', async () => {
|
||||
const getCurrentPersonSpy = spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(getFakeUserWithContentAdminCapability()));
|
||||
const getCurrentPersonSpy = spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(of({entry: fakeEcmAdminUser}));
|
||||
|
||||
expect(await peopleContentService.isContentAdmin()).toBe(true);
|
||||
const user = await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
expect(user.id).toEqual('fake-id');
|
||||
expect(peopleContentService.isCurrentUserAdmin()).toBe(true);
|
||||
expect(getCurrentPersonSpy.calls.count()).toEqual(1);
|
||||
|
||||
await peopleContentService.isContentAdmin();
|
||||
await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
|
||||
expect(await peopleContentService.isContentAdmin()).toBe(true);
|
||||
expect(await peopleContentService.isCurrentUserAdmin()).toBe(true);
|
||||
expect(getCurrentPersonSpy.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should reset the admin cache upon logout', async () => {
|
||||
const getCurrentPersonSpy = spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(getFakeUserWithContentAdminCapability()));
|
||||
spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(of({entry: fakeEcmAdminUser}));
|
||||
|
||||
expect(await peopleContentService.isContentAdmin()).toBeTruthy();
|
||||
expect(peopleContentService.hasCheckedIsContentAdmin).toBeTruthy();
|
||||
const user = await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
expect(user.id).toEqual('fake-id');
|
||||
expect(peopleContentService.isCurrentUserAdmin()).toBe(true);
|
||||
|
||||
authenticationService.onLogout.next(true);
|
||||
expect(peopleContentService.hasCheckedIsContentAdmin).toBeFalsy();
|
||||
|
||||
expect(await peopleContentService.isContentAdmin()).toBe(true);
|
||||
expect(getCurrentPersonSpy.calls.count()).toEqual(2);
|
||||
expect(peopleContentService.isCurrentUserAdmin()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@@ -16,13 +16,14 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, from, throwError } from 'rxjs';
|
||||
import { Observable, from, throwError, of } from 'rxjs';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { PersonEntry, PeopleApi, PersonBodyCreate, Pagination, PersonBodyUpdate } from '@alfresco/js-api';
|
||||
import { catchError, map, tap } from 'rxjs/operators';
|
||||
import { PeopleApi, PersonBodyCreate, Pagination, PersonBodyUpdate } from '@alfresco/js-api';
|
||||
import { EcmUserModel } from '../models/ecm-user.model';
|
||||
import { LogService } from './log.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { ContentService } from './content.service';
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
export enum ContentGroups {
|
||||
@@ -49,8 +50,7 @@ export interface PeopleContentQueryRequestModel {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PeopleContentService {
|
||||
private hasContentAdminRole: boolean = false;
|
||||
hasCheckedIsContentAdmin: boolean = false;
|
||||
private currentUser: EcmUserModel;
|
||||
|
||||
private _peopleApi: PeopleApi;
|
||||
get peopleApi(): PeopleApi {
|
||||
@@ -61,11 +61,11 @@ export class PeopleContentService {
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
authenticationService: AuthenticationService,
|
||||
private logService: LogService
|
||||
private logService: LogService,
|
||||
private contentService: ContentService
|
||||
) {
|
||||
authenticationService.onLogout.subscribe(() => {
|
||||
this.hasCheckedIsContentAdmin = false;
|
||||
this.hasContentAdminRole = false;
|
||||
this.resetLocalCurrentUser();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,23 +75,46 @@ export class PeopleContentService {
|
||||
* @param personId ID of the target user
|
||||
* @returns User information
|
||||
*/
|
||||
getPerson(personId: string): Observable<any> {
|
||||
const promise = this.peopleApi.getPerson(personId);
|
||||
getPerson(personId: string): Observable<EcmUserModel> {
|
||||
return from(this.peopleApi.getPerson(personId))
|
||||
.pipe(
|
||||
map((personEntry) => new EcmUserModel(personEntry.entry)),
|
||||
tap( user => this.currentUser = user),
|
||||
catchError((error) => this.handleError(error)));
|
||||
}
|
||||
|
||||
return from(promise).pipe(
|
||||
catchError((error) => this.handleError(error))
|
||||
);
|
||||
getCurrentPerson(): Observable<EcmUserModel> {
|
||||
return this.getCurrentUserInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about the user who is currently logged in.
|
||||
* Gets information about the current user alias -me-
|
||||
*
|
||||
* @returns User information
|
||||
*/
|
||||
getCurrentPerson(): Observable<any> {
|
||||
getCurrentUserInfo(): Observable<EcmUserModel> {
|
||||
if (this.currentUser) {
|
||||
return of(this.currentUser);
|
||||
}
|
||||
return this.getPerson('-me-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to know if the current user has the admin capability
|
||||
*
|
||||
* @returns true or false
|
||||
*/
|
||||
isCurrentUserAdmin(): boolean {
|
||||
return this.currentUser?.isAdmin() ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the local current user object
|
||||
*/
|
||||
resetLocalCurrentUser() {
|
||||
this.currentUser = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of people.
|
||||
*
|
||||
@@ -144,13 +167,14 @@ export class PeopleContentService {
|
||||
);
|
||||
}
|
||||
|
||||
async isContentAdmin(): Promise<boolean> {
|
||||
if (!this.hasCheckedIsContentAdmin) {
|
||||
const user: PersonEntry = await this.getCurrentPerson().toPromise();
|
||||
this.hasContentAdminRole = user?.entry?.capabilities?.isAdmin;
|
||||
this.hasCheckedIsContentAdmin = true;
|
||||
}
|
||||
return this.hasContentAdminRole;
|
||||
/**
|
||||
* Returns a profile image as a URL.
|
||||
*
|
||||
* @param avatarId Target avatar
|
||||
* @returns Image URL
|
||||
*/
|
||||
getUserProfileImage(avatarId: string): string {
|
||||
return this.contentService.getContentUrl(avatarId);
|
||||
}
|
||||
|
||||
private buildOrderArray(sorting: PeopleContentSortingModel): string[] {
|
||||
|
@@ -70,3 +70,4 @@ export * from './identity-group.interface';
|
||||
export * from './language-item.interface';
|
||||
export * from './sort-by-category.service';
|
||||
export * from './user-access.service';
|
||||
export * from './user-info-resolver.service';
|
||||
|
41
lib/core/services/user-info-resolver.service.ts
Normal file
41
lib/core/services/user-info-resolver.service.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @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 {
|
||||
Resolve,
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot
|
||||
} from '@angular/router';
|
||||
import { EcmUserModel } from '../models/ecm-user.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { PeopleContentService } from './people-content.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserInfoResolverService implements Resolve<EcmUserModel> {
|
||||
constructor(private peopleContentService: PeopleContentService) {}
|
||||
|
||||
resolve(
|
||||
_route: ActivatedRouteSnapshot,
|
||||
_state: RouterStateSnapshot
|
||||
): Observable<EcmUserModel> {
|
||||
return this.peopleContentService.getCurrentUserInfo();
|
||||
}
|
||||
|
||||
}
|
@@ -17,12 +17,11 @@
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By, DomSanitizer } from '@angular/platform-browser';
|
||||
import { AuthenticationService, ContentService } from '../../services';
|
||||
import { AuthenticationService, ContentService, PeopleContentService } from '../../services';
|
||||
import { InitialUsernamePipe } from '../../pipes';
|
||||
import { fakeBpmUser } from '../../mock/bpm-user.service.mock';
|
||||
import { fakeEcmEditedUser, fakeEcmUser, fakeEcmUserNoImage } from '../../mock/ecm-user.service.mock';
|
||||
import { BpmUserService } from '../../services/bpm-user.service';
|
||||
import { EcmUserService } from '../../services/ecm-user.service';
|
||||
import { IdentityUserService } from '../../services/identity-user.service';
|
||||
import { BpmUserModel } from '../../models/bpm-user.model';
|
||||
import { EcmUserModel } from '../../models/ecm-user.model';
|
||||
@@ -71,7 +70,7 @@ describe('User info component', () => {
|
||||
let element: HTMLElement;
|
||||
let authService: AuthenticationService;
|
||||
let contentService: ContentService;
|
||||
let ecmUserService: EcmUserService;
|
||||
let peopleContentService: PeopleContentService;
|
||||
let bpmUserService: BpmUserService;
|
||||
let identityUserService: IdentityUserService;
|
||||
|
||||
@@ -106,7 +105,7 @@ describe('User info component', () => {
|
||||
element = fixture.nativeElement;
|
||||
|
||||
authService = TestBed.inject(AuthenticationService);
|
||||
ecmUserService = TestBed.inject(EcmUserService);
|
||||
peopleContentService = TestBed.inject(PeopleContentService);
|
||||
bpmUserService = TestBed.inject(BpmUserService);
|
||||
contentService = TestBed.inject(ContentService);
|
||||
identityUserService = TestBed.inject(IdentityUserService);
|
||||
@@ -145,7 +144,7 @@ describe('User info component', () => {
|
||||
isEcmLoggedInStub = spyOn(authService, 'isEcmLoggedIn').and.returnValue(true);
|
||||
isLoggedInStub = spyOn(authService, 'isLoggedIn').and.returnValue(true);
|
||||
isBpmLoggedInStub = spyOn(authService, 'isBpmLoggedIn').and.returnValue(false);
|
||||
getCurrenEcmtUserInfoStub = spyOn(ecmUserService, 'getCurrentUserInfo').and.returnValue(of(fakeEcmUser));
|
||||
getCurrenEcmtUserInfoStub = spyOn(peopleContentService, 'getCurrentUserInfo').and.returnValue(of(fakeEcmUser));
|
||||
});
|
||||
|
||||
describe('ui ', () => {
|
||||
|
@@ -21,10 +21,10 @@ import { BpmUserModel } from '../../models/bpm-user.model';
|
||||
import { EcmUserModel } from '../../models/ecm-user.model';
|
||||
import { IdentityUserModel } from '../../models/identity-user.model';
|
||||
import { BpmUserService } from '../../services/bpm-user.service';
|
||||
import { EcmUserService } from '../../services/ecm-user.service';
|
||||
import { IdentityUserService } from '../../services/identity-user.service';
|
||||
import { of, Observable, Subject } from 'rxjs';
|
||||
import { MatMenuTrigger, MenuPositionX, MenuPositionY } from '@angular/material/menu';
|
||||
import { PeopleContentService } from '../../services/people-content.service';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-userinfo',
|
||||
@@ -70,7 +70,7 @@ export class UserInfoComponent implements OnInit, OnDestroy {
|
||||
selectedIndex: number;
|
||||
private destroy$ = new Subject();
|
||||
|
||||
constructor(private ecmUserService: EcmUserService,
|
||||
constructor(private peopleContentService: PeopleContentService,
|
||||
private bpmUserService: BpmUserService,
|
||||
private identityUserService: IdentityUserService,
|
||||
private authService: AuthenticationService) {
|
||||
@@ -125,7 +125,7 @@ export class UserInfoComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private loadEcmUserInfo(): void {
|
||||
this.ecmUser$ = this.ecmUserService.getCurrentUserInfo();
|
||||
this.ecmUser$ = this.peopleContentService.getCurrentUserInfo();
|
||||
}
|
||||
|
||||
private loadBpmUserInfo() {
|
||||
@@ -153,7 +153,7 @@ export class UserInfoComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
getEcmAvatar(avatarId: any): string {
|
||||
return this.ecmUserService.getUserProfileImage(avatarId);
|
||||
return this.peopleContentService.getUserProfileImage(avatarId);
|
||||
}
|
||||
|
||||
getBpmUserImage(): string {
|
||||
|
Reference in New Issue
Block a user