[ADF-4738] [Process -Cloud] Move GroupCloudService to adf-core (#4928)

* [ADF-4738] [Process -Cloud] Move GroupCloudService to adf-core lib.

* * Changed GroupModel to IdentityGroupModel
* Updated unit tests the recent changes.

* * Added documentation to the identityGroupService
* Updated GroupInitial and GroupCoudcomponent doc.

* * Created groupCount model. * Updated unit test to the recent changes

* * After rebase updated doc

* * Fixed comments.
This commit is contained in:
siva kumar
2019-08-12 20:57:30 +05:30
committed by Eugenio Romano
parent 4ead51d2a6
commit eb2811fdd0
19 changed files with 915 additions and 499 deletions

View File

@@ -16,8 +16,9 @@
*/ */
import { Component, ViewEncapsulation } from '@angular/core'; import { Component, ViewEncapsulation } from '@angular/core';
import { PeopleCloudComponent, GroupCloudComponent, GroupModel } from '@alfresco/adf-process-services-cloud'; import { PeopleCloudComponent, GroupCloudComponent } from '@alfresco/adf-process-services-cloud';
import { MatRadioChange, MatCheckboxChange } from '@angular/material'; import { MatRadioChange, MatCheckboxChange } from '@angular/material';
import { IdentityGroupModel } from '@alfresco/adf-core';
@Component({ @Component({
selector: 'app-people-groups-cloud', selector: 'app-people-groups-cloud',
@@ -39,8 +40,8 @@ export class PeopleGroupCloudDemoComponent {
peoplePreselectValidation: Boolean = false; peoplePreselectValidation: Boolean = false;
groupMode: string = GroupCloudComponent.MODE_SINGLE; groupMode: string = GroupCloudComponent.MODE_SINGLE;
preSelectGroup: GroupModel[] = []; preSelectGroup: IdentityGroupModel[] = [];
selectedGroupList: GroupModel[] = []; selectedGroupList: IdentityGroupModel[] = [];
groupRoles: string[]; groupRoles: string[];
groupAppName: string; groupAppName: string;
groupFilterMode: string = this.DEFAULT_FILTER_MODE; groupFilterMode: string = this.DEFAULT_FILTER_MODE;
@@ -144,11 +145,11 @@ export class PeopleGroupCloudDemoComponent {
return this.groupMode === GroupCloudComponent.MODE_MULTIPLE; return this.groupMode === GroupCloudComponent.MODE_MULTIPLE;
} }
onRemoveGroup(group: GroupModel) { onRemoveGroup(group: IdentityGroupModel) {
this.preSelectGroup = this.preSelectGroup.filter((value: any) => value.id !== group.id); this.preSelectGroup = this.preSelectGroup.filter((value: any) => value.id !== group.id);
} }
onSelectGroup(group: GroupModel) { onSelectGroup(group: IdentityGroupModel) {
if (this.groupMode === GroupCloudComponent.MODE_MULTIPLE) { if (this.groupMode === GroupCloudComponent.MODE_MULTIPLE) {
this.preSelectGroup.push(group); this.preSelectGroup.push(group);
} }

View File

@@ -0,0 +1,75 @@
---
Title: Identity Group service
Added: v3.4.0
Status: Active
Last reviewed: 2019-07-13
---
# [Identity Group service](../../../lib/core/userinfo/services/identity-group.service.ts "Defined in identity-group.service.ts")
Performs CRUD operations on identity groups.
## Class members
### Methods
- **checkGroupHasAnyClientAppRole**(groupId: `string`, clientId: `string`, roleNames: `string[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<boolean>`<br/>
Check if a group has any of the client app roles in the supplied list.
- _groupId:_ `string` - Id of the target group
- _clientId:_ `string` - Id of the client
- _roleNames:_ `string[]` - Array of role names to check
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<boolean>` - True if the group has one or more of the roles, false otherwise
- **checkGroupHasClientApp**(groupId: `string`, clientId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<boolean>`<br/>
Checks if a group has a client app.
- _groupId:_ `string` - Id of the target group
- _clientId:_ `string` - Id of the client
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<boolean>` - True if the group has the client app, false otherwise
- **checkGroupHasRole**(groupId: `string`, roleNames: `string[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<boolean>`<br/>
Check that a group has one or more roles from the supplied list.
- _groupId:_ `string` - Id of the target group
- _roleNames:_ `string[]` - Array of role names
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<boolean>` - True if the group has one or more of the roles, false otherwise
- **createGroup**(newGroup: [`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
Creates new group.
- _newGroup:_ [`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts) - Object of containing the new group details.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Empty response when the group created.
- **deleteGroup**(groupId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
Deletes Group.
- _groupId:_ `string` - Id of the group.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Empty response when the group deleted.
- **findGroupsByName**(searchParams: [`IdentityGroupSearchParam`](../../../lib/core/userinfo/models/identity-group.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
Finds groups filtered by name.
- _searchParams:_ [`IdentityGroupSearchParam`](../../../lib/core/userinfo/models/identity-group.model.ts) - Object containing the name filter string
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - List of group information
- **getClientIdByApplicationName**(applicationName: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<string>`<br/>
Gets the client ID using the app name.
- _applicationName:_ `string` - Name of the app
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<string>` - client ID string
- **getClientRoles**(groupId: `string`, clientId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>`<br/>
Gets client roles.
- _groupId:_ `string` - ID of the target group
- _clientId:_ `string` - ID of the client
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - List of roles
- **getGroupRoles**(groupId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>`<br/>
Gets details for a specified group.
- _groupId:_ `string` - ID of the target group
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - Group details
- **getGroups**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`[]>`<br/>
Gets all groups.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`[]>` - Array of group information objects
- **getTotalGroupsCount**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupCountModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`>`<br/>
Gets groups total count.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupCountModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`>` - Number of groups count.
- **queryGroups**(requestQuery: [`IdentityGroupQueryCloudRequestModel`](../../../lib/core/userinfo/models/identity-group.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupQueryResponse`](../../../lib/core/userinfo/models/identity-group.model.ts)`>`<br/>
Queries groups.
- _requestQuery:_ [`IdentityGroupQueryCloudRequestModel`](../../../lib/core/userinfo/models/identity-group.model.ts) -
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupQueryResponse`](../../../lib/core/userinfo/models/identity-group.model.ts)`>` - Array of user information objects
- **updateGroup**(groupId: `string`, updatedGroup: [`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
Updates group details.
- _groupId:_ `string` - Id of the targeted group.
- _updatedGroup:_ [`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts) - Object of containing the group details
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Empty response when the group updated.
## See also
- [Identity user service](../../core/userInfo/services/identity-user.service.md)

View File

@@ -28,7 +28,7 @@ Searches Groups.
| ---- | ---- | ------------- | ----------- | | ---- | ---- | ------------- | ----------- |
| appName | `string` | | Name of the application. If specified this shows the users who have access to the app. | | appName | `string` | | Name of the application. If specified this shows the users who have access to the app. |
| mode | `string` | | User selection mode (single/multiple). | | mode | `string` | | User selection mode (single/multiple). |
| preSelectGroups | [`GroupModel`](../../../lib/process-services-cloud/src/lib/group/models/group.model.ts)`[]` | \[] | Array of users to be pre-selected. This pre-selects all users in multi selection mode and only the first user of the array in single selection mode. | | preSelectGroups | [`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`[]` | \[] | Array of users to be pre-selected. This pre-selects all users in multi selection mode and only the first user of the array in single selection mode. |
| roles | `string[]` | \[] | Role names of the groups to be listed. | | roles | `string[]` | \[] | Role names of the groups to be listed. |
| searchGroupsControl | `FormControl` | new FormControl() | FormControl to search the group | | searchGroupsControl | `FormControl` | new FormControl() | FormControl to search the group |
| title | `string` | | Title of the field | | title | `string` | | Title of the field |
@@ -37,8 +37,8 @@ Searches Groups.
| Name | Type | Description | | Name | Type | Description |
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| removeGroup | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`GroupModel`](../../../lib/process-services-cloud/src/lib/group/models/group.model.ts)`>` | Emitted when a group is removed. | | removeGroup | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`>` | Emitted when a group is removed. |
| selectGroup | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`GroupModel`](../../../lib/process-services-cloud/src/lib/group/models/group.model.ts)`>` | Emitted when a group is selected. | | selectGroup | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`>` | Emitted when a group is selected. |
## Details ## Details

View File

@@ -23,7 +23,7 @@ Extracts the initial character from a group name.
## Details ## Details
This pipe takes a [`GroupModel`](../../../lib/process-services-cloud/src/lib/group/models/group.model.ts) This pipe takes a [`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)
object as its parameter and extracts the initial character from the `name` object as its parameter and extracts the initial character from the `name`
property. The initial is a handy way to identify the group in lists and property. The initial is a handy way to identify the group in lists and
other situations where there is limited screen space available. other situations where there is limited screen space available.

View File

@@ -0,0 +1,163 @@
/*!
* @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 { IdentityGroupModel, IdentityGroupCountModel } from '../userinfo/models/identity-group.model';
import { IdentityRoleModel } from '../userinfo/models/identity-role.model';
export let mockIdentityGroup1 = new IdentityGroupModel({
id: 'mock-group-id-1', name: 'Mock Group 1', path: '/mock', subGroups: []
});
export let mockIdentityGroup2 = new IdentityGroupModel({
id: 'mock-group-id-2', name: 'Mock Group 2', path: '', subGroups: []
});
export let mockIdentityGroup3 = new IdentityGroupModel({
id: 'mock-group-id-3', name: 'Mock Group 3', path: '', subGroups: []
});
export let mockIdentityGroup4 = new IdentityGroupModel({
id: 'mock-group-id-4', name: 'Mock Group 4', path: '', subGroups: []
});
export let mockIdentityGroup5 = new IdentityGroupModel({
id: 'mock-group-id-5', name: 'Mock Group 5', path: '', subGroups: []
});
export let mockIdentityGroupsCount = <IdentityGroupCountModel> { count: 10 };
export let mockIdentityGroups = [
mockIdentityGroup1, mockIdentityGroup2, mockIdentityGroup3, mockIdentityGroup5, mockIdentityGroup5
];
export let mockApplicationDetails = {id: 'mock-app-id', name: 'mock-app-name'};
export let groupAPIMockError = {
error: {
errorKey: 'failed',
statusCode: 400,
stackTrace: 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.'
}
};
export let mockApiError = {
oauth2Auth: {
callCustomApi: () => {
return Promise.reject(groupAPIMockError);
}
}
};
export let roleMappingMock = [
{ id: 'role-id-1', name: 'role-name-1' }, { id: 'role-id-2', name: 'role-name-2' }
];
export let roleMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(roleMappingMock);
}
}
};
export let noRoleMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve([]);
}
}
};
export let groupsMockApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(mockIdentityGroups);
}
}
};
export let getGroupsCountMockApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(10);
}
}
};
export let queryGroupsMockApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(mockIdentityGroups);
}
}
};
export let createGroupMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve();
}
}
};
export let updateGroupMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve();
}
}
};
export let deleteGroupMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve();
}
}
};
export let returnCallQueryParameters = {
oauth2Auth: {
callCustomApi: (queryUrl, operation, context, queryParams) => {
return Promise.resolve(queryParams);
}
}
};
export let returnCallUrl = {
oauth2Auth: {
callCustomApi: (queryUrl, operation, context, queryParams) => {
return Promise.resolve(queryUrl);
}
}
};
export let applicationDetailsMockApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve([mockApplicationDetails]);
}
}
};
export let mockIdentityRoles = [
new IdentityRoleModel({id: 'mock-role-id', name: 'MOCK-ADMIN-ROLE'}),
new IdentityRoleModel({id: 'mock-role-id', name: 'MOCK-USER-ROLE'}),
new IdentityRoleModel({id: 'mock-role-id', name: 'MOCK-ROLE-1'})
];
export let clientRoles = [ 'MOCK-ADMIN-ROLE', 'MOCK-USER-ROLE'];

View File

@@ -37,3 +37,4 @@ export * from './form/start-form.component.mock';
export * from './form/form.service.mock'; export * from './form/form.service.mock';
export * from './form/widget-visibility.service.mock'; export * from './form/widget-visibility.service.mock';
export * from './jwt-helper.service.spec'; export * from './jwt-helper.service.spec';
export * from './identity-group.service.mock';

View File

@@ -14,6 +14,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { Pagination } from '@alfresco/js-api';
export class IdentityGroupModel { export class IdentityGroupModel {
id: string; id: string;
@@ -36,3 +39,30 @@ export class IdentityGroupModel {
} }
} }
} }
export interface IdentityGroupSearchParam {
name?: string;
}
export interface IdentityGroupQueryResponse {
entries: IdentityGroupModel[];
pagination: Pagination;
}
export class IdentityGroupQueryCloudRequestModel {
first: number;
max: number;
constructor(obj?: any) {
if (obj) {
this.first = obj.first;
this.max = obj.max;
}
}
}
export interface IdentityGroupCountModel {
count: number;
}

View File

@@ -19,8 +19,10 @@ export * from './components/user-info.component';
export * from './services/bpm-user.service'; export * from './services/bpm-user.service';
export * from './services/ecm-user.service'; export * from './services/ecm-user.service';
export * from './services/identity-user.service'; export * from './services/identity-user.service';
export * from './services/identity-group.service';
export * from './models/bpm-user.model'; export * from './models/bpm-user.model';
export * from './models/ecm-user.model'; export * from './models/ecm-user.model';
export * from './models/identity-group.model';
export * from './models/identity-user.model'; export * from './models/identity-user.model';
export * from './models/identity-role.model'; export * from './models/identity-role.model';
export * from './models/identity-group.model'; export * from './models/identity-group.model';

View File

@@ -17,32 +17,37 @@
import { async } from '@angular/core/testing'; import { async } from '@angular/core/testing';
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { GroupCloudService } from './group-cloud.service';
import { import {
AlfrescoApiServiceMock, AlfrescoApiServiceMock,
CoreModule, CoreModule,
setupTestBed, setupTestBed,
AlfrescoApiService, AlfrescoApiService,
LogService LogService,
IdentityGroupService,
IdentityGroupSearchParam,
groupAPIMockError
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import {
applicationDetailsMockApi,
groupsMockApi,
returnCallQueryParameters,
returnCallUrl,
mockApiError,
mockError,
roleMappingApi,
noRoleMappingApi,
groupRoles,
clientRoles
} from '../mock/group-cloud.mock';
import { GroupSearchParam } from '../models/group.model';
import { HttpErrorResponse } from '@angular/common/http'; import { HttpErrorResponse } from '@angular/common/http';
import { throwError, of } from 'rxjs'; import { throwError, of } from 'rxjs';
import {
noRoleMappingApi,
mockIdentityRoles,
groupsMockApi,
roleMappingApi,
clientRoles,
returnCallQueryParameters,
returnCallUrl,
applicationDetailsMockApi,
mockApiError,
mockIdentityGroup1,
createGroupMappingApi,
updateGroupMappingApi,
deleteGroupMappingApi,
mockIdentityGroupsCount
} from '../../mock/identity-group.service.mock';
describe('GroupCloudService', () => { describe('IdentityGroupService', () => {
let service: GroupCloudService; let service: IdentityGroupService;
let apiService: AlfrescoApiService; let apiService: AlfrescoApiService;
let logService: LogService; let logService: LogService;
@@ -54,23 +59,23 @@ describe('GroupCloudService', () => {
}); });
beforeEach(async(() => { beforeEach(async(() => {
service = TestBed.get(GroupCloudService); service = TestBed.get(IdentityGroupService);
apiService = TestBed.get(AlfrescoApiService); apiService = TestBed.get(AlfrescoApiService);
logService = TestBed.get(LogService); logService = TestBed.get(LogService);
})); }));
it('should be able to fetch groups', (done) => { it('should be able to fetch groups based on group name', (done) => {
spyOn(apiService, 'getInstance').and.returnValue(groupsMockApi); spyOn(apiService, 'getInstance').and.returnValue(groupsMockApi);
service.findGroupsByName(<GroupSearchParam> {name: 'mock'}).subscribe((res) => { service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res.length).toBe(3); expect(res.length).toBe(5);
expect(res[0].id).toBe('mock-id-1'); expect(res[0].id).toBe('mock-group-id-1');
expect(res[0].name).toBe('Mock Group 1'); expect(res[0].name).toBe('Mock Group 1');
expect(res[1].id).toBe('mock-id-2'); expect(res[1].id).toBe('mock-group-id-2');
expect(res[1].name).toBe('Mock Group 2'); expect(res[1].name).toBe('Mock Group 2');
expect(res[2].id).toBe('mock-id-3'); expect(res[2].id).toBe('mock-group-id-3');
expect(res[2].name).toBe('Fake Group 3'); expect(res[2].name).toBe('Mock Group 3');
done(); done();
}); });
}); });
@@ -94,7 +99,7 @@ describe('GroupCloudService', () => {
}); });
it('should able to fetch group roles by groupId', (done) => { it('should able to fetch group roles by groupId', (done) => {
spyOn(service, 'getGroupRoles').and.returnValue(of(groupRoles)); spyOn(service, 'getGroupRoles').and.returnValue(of(mockIdentityRoles));
service.getGroupRoles('mock-group-id').subscribe( service.getGroupRoles('mock-group-id').subscribe(
(res: any) => { (res: any) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
@@ -130,7 +135,7 @@ describe('GroupCloudService', () => {
}); });
it('should return true if group has given role', (done) => { it('should return true if group has given role', (done) => {
spyOn(service, 'getGroupRoles').and.returnValue(of(groupRoles)); spyOn(service, 'getGroupRoles').and.returnValue(of(mockIdentityRoles));
service.checkGroupHasRole('mock-group-id', ['MOCK-ADMIN-ROLE']).subscribe( service.checkGroupHasRole('mock-group-id', ['MOCK-ADMIN-ROLE']).subscribe(
(res: boolean) => { (res: boolean) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
@@ -141,7 +146,7 @@ describe('GroupCloudService', () => {
}); });
it('should return false if group does not have given role', (done) => { it('should return false if group does not have given role', (done) => {
spyOn(service, 'getGroupRoles').and.returnValue(of(groupRoles)); spyOn(service, 'getGroupRoles').and.returnValue(of(mockIdentityRoles));
service.checkGroupHasRole('mock-group-id', ['MOCK-ADMIN-MODELER']).subscribe( service.checkGroupHasRole('mock-group-id', ['MOCK-ADMIN-MODELER']).subscribe(
(res: boolean) => { (res: boolean) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
@@ -231,7 +236,7 @@ describe('GroupCloudService', () => {
it('should append to the call all the parameters', (done) => { it('should append to the call all the parameters', (done) => {
spyOn(apiService, 'getInstance').and.returnValue(returnCallQueryParameters); spyOn(apiService, 'getInstance').and.returnValue(returnCallQueryParameters);
service.findGroupsByName(<GroupSearchParam> {name: 'mock'}).subscribe((res) => { service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res.search).toBe('mock'); expect(res.search).toBe('mock');
@@ -241,7 +246,7 @@ describe('GroupCloudService', () => {
it('should request groups api url', (done) => { it('should request groups api url', (done) => {
spyOn(apiService, 'getInstance').and.returnValue(returnCallUrl); spyOn(apiService, 'getInstance').and.returnValue(returnCallUrl);
service.findGroupsByName(<GroupSearchParam> {name: 'mock'}).subscribe((requestUrl) => { service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((requestUrl) => {
expect(requestUrl).toBeDefined(); expect(requestUrl).toBeDefined();
expect(requestUrl).not.toBeNull(); expect(requestUrl).not.toBeNull();
expect(requestUrl).toContain('/groups'); expect(requestUrl).toContain('/groups');
@@ -262,14 +267,184 @@ describe('GroupCloudService', () => {
it('should notify errors returned from the API', (done) => { it('should notify errors returned from the API', (done) => {
const logServiceSpy = spyOn(logService, 'error').and.callThrough(); const logServiceSpy = spyOn(logService, 'error').and.callThrough();
spyOn(apiService, 'getInstance').and.returnValue(mockApiError); spyOn(apiService, 'getInstance').and.returnValue(mockApiError);
service.findGroupsByName(<GroupSearchParam> {name: 'mock'}).subscribe( service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe(
() => {}, () => {},
(res: any) => { (res: any) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(res).toEqual(mockError); expect(res).toEqual(groupAPIMockError);
expect(logServiceSpy).toHaveBeenCalled(); expect(logServiceSpy).toHaveBeenCalled();
done(); done();
} }
); );
}); });
it('should be able to all fetch groups', (done) => {
spyOn(apiService, 'getInstance').and.returnValue(groupsMockApi);
service.getGroups().subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(5);
expect(res[0].id).toBe('mock-group-id-1');
expect(res[0].name).toBe('Mock Group 1');
expect(res[1].id).toBe('mock-group-id-2');
expect(res[1].name).toBe('Mock Group 2');
expect(res[2].id).toBe('mock-group-id-3');
expect(res[2].name).toBe('Mock Group 3');
done();
});
});
it('Should not able to fetch all group if error occurred', (done) => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
});
spyOn(service, 'getGroups').and.returnValue(throwError(errorResponse));
service.getGroups()
.subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should be able to query groups based on first & max params', (done) => {
spyOn(service, 'getTotalGroupsCount').and.returnValue(of(mockIdentityGroupsCount));
spyOn(apiService, 'getInstance').and.returnValue(groupsMockApi);
service.queryGroups({first: 0, max: 5}).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.entries.length).toBe(5);
expect(res.entries[0].id).toBe('mock-group-id-1');
expect(res.entries[0].name).toBe('Mock Group 1');
expect(res.entries[1].id).toBe('mock-group-id-2');
expect(res.entries[1].name).toBe('Mock Group 2');
expect(res.entries[2].id).toBe('mock-group-id-3');
expect(res.entries[2].name).toBe('Mock Group 3');
expect(res.pagination.totalItems).toBe(10);
expect(res.pagination.skipCount).toBe(0);
expect(res.pagination.maxItems).toBe(5);
done();
});
});
it('Should not able to query groups if error occurred', (done) => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
});
spyOn(service, 'queryGroups').and.returnValue(throwError(errorResponse));
service.queryGroups({first: 0, max: 5})
.subscribe(
() => {
fail('expected an error, not query groups');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should be able to create group', (done) => {
const createCustomApiSpy = spyOn(apiService, 'getInstance').and.returnValue(createGroupMappingApi);
service.createGroup(mockIdentityGroup1).subscribe((res) => {
expect(createCustomApiSpy).toHaveBeenCalled();
done();
});
});
it('Should not able to create group if error occurred', (done) => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
});
spyOn(service, 'createGroup').and.returnValue(throwError(errorResponse));
service.createGroup(mockIdentityGroup1)
.subscribe(
() => {
fail('expected an error, not to create group');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should be able to update group', (done) => {
const updateCustomApiSpy = spyOn(apiService, 'getInstance').and.returnValue(updateGroupMappingApi);
service.updateGroup('mock-group-id', mockIdentityGroup1).subscribe((res) => {
expect(updateCustomApiSpy).toHaveBeenCalled();
done();
});
});
it('Should not able to update group if error occurred', (done) => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
});
spyOn(service, 'updateGroup').and.returnValue(throwError(errorResponse));
service.updateGroup('mock-group-id', mockIdentityGroup1)
.subscribe(
() => {
fail('expected an error, not to update group');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should be able to delete group', (done) => {
const deleteCustomApiSpy = spyOn(apiService, 'getInstance').and.returnValue(deleteGroupMappingApi);
service.deleteGroup('mock-group-id').subscribe((res) => {
expect(deleteCustomApiSpy).toHaveBeenCalled();
done();
});
});
it('Should not able to delete group if error occurred', (done) => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
});
spyOn(service, 'deleteGroup').and.returnValue(throwError(errorResponse));
service.deleteGroup('mock-group-id')
.subscribe(
() => {
fail('expected an error, not to delete group');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
}); });

View File

@@ -0,0 +1,347 @@
/*!
* @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 { Observable, of, from, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { AppConfigService } from '../../app-config/app-config.service';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { LogService } from '../../services/log.service';
import {
IdentityGroupSearchParam,
IdentityGroupQueryCloudRequestModel,
IdentityGroupModel,
IdentityGroupQueryResponse,
IdentityGroupCountModel
} from '../models/identity-group.model';
import { IdentityRoleModel } from '../models/identity-role.model';
@Injectable({
providedIn: 'root'
})
export class IdentityGroupService {
constructor(
private alfrescoApiService: AlfrescoApiService,
private appConfigService: AppConfigService,
private logService: LogService
) {}
/**
* Gets all groups.
* @returns Array of group information objects
*/
getGroups(): Observable<IdentityGroupModel[]> {
const url = this.getGroupsApi();
const httpMethod = 'GET', pathParams = {},
queryParams = {}, bodyParam = {}, headerParams = {},
formParams = {}, authNames = [], contentTypes = ['application/json'];
return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam, authNames,
contentTypes, null, null, null
)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Queries groups.
* @returns Array of user information objects
*/
queryGroups(requestQuery: IdentityGroupQueryCloudRequestModel): Observable<IdentityGroupQueryResponse> {
const url = this.getGroupsApi();
const httpMethod = 'GET', pathParams = {},
queryParams = { first: requestQuery.first || 0, max: requestQuery.max || 5 }, bodyParam = {}, headerParams = {},
formParams = {}, authNames = [], contentTypes = ['application/json'];
return this.getTotalGroupsCount().pipe(
switchMap((totalCount: IdentityGroupCountModel) =>
from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam, authNames,
contentTypes, null, null, null)
).pipe(
map((response: any[]) => {
return <IdentityGroupQueryResponse> {
entries: response,
pagination: {
skipCount: requestQuery.first,
maxItems: requestQuery.max,
count: totalCount.count,
hasMoreItems: false,
totalItems: totalCount.count
}
};
}),
catchError((error) => this.handleError(error))
))
);
}
/**
* Gets groups total count.
* @returns Number of groups count.
*/
getTotalGroupsCount(): Observable<IdentityGroupCountModel> {
const url = this.getGroupsApi() + `/count`;
const contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.alfrescoApiService.getInstance()
.oauth2Auth.callCustomApi(url, 'GET',
null, null, null,
null, null, contentTypes,
accepts, null, null, null)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Creates new group.
* @param newGroup Object of containing the new group details.
* @returns Empty response when the group created.
*/
createGroup(newGroup: IdentityGroupModel): Observable<any> {
const url = this.getGroupsApi();
const httpMethod = 'POST', pathParams = {}, queryParams = {}, bodyParam = newGroup, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, null, null, null
)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Updates group details.
* @param groupId Id of the targeted group.
* @param updatedGroup Object of containing the group details
* @returns Empty response when the group updated.
*/
updateGroup(groupId: string, updatedGroup: IdentityGroupModel): Observable<any> {
const url = this.getGroupsApi() + `/${groupId}`;
const request = JSON.stringify(updatedGroup);
const httpMethod = 'PUT', pathParams = {} , queryParams = {}, bodyParam = request, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, null, null, null
)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Deletes Group.
* @param groupId Id of the group.
* @returns Empty response when the group deleted.
*/
deleteGroup(groupId: string): Observable<any> {
const url = this.getGroupsApi() + `/${groupId}`;
const httpMethod = 'DELETE', pathParams = {} , queryParams = {}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, null, null, null
)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Finds groups filtered by name.
* @param searchParams Object containing the name filter string
* @returns List of group information
*/
findGroupsByName(searchParams: IdentityGroupSearchParam): Observable<any> {
if (searchParams.name === '') {
return of([]);
}
const url = this.getGroupsApi();
const httpMethod = 'GET', pathParams = {}, queryParams = {search: searchParams.name}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null)
)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Gets details for a specified group.
* @param groupId Id of the target group
* @returns Group details
*/
getGroupRoles(groupId: string): Observable<IdentityRoleModel[]> {
const url = this.buildRolesUrl(groupId);
const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null)
)).pipe(
catchError((error) => this.handleError(error))
);
}
/**
* Check that a group has one or more roles from the supplied list.
* @param groupId Id of the target group
* @param roleNames Array of role names
* @returns True if the group has one or more of the roles, false otherwise
*/
checkGroupHasRole(groupId: string, roleNames: string[]): Observable<boolean> {
return this.getGroupRoles(groupId).pipe(map((groupRoles: IdentityRoleModel[]) => {
let hasRole = false;
if (groupRoles && groupRoles.length > 0) {
roleNames.forEach((roleName: string) => {
const role = groupRoles.find((groupRole) => {
return roleName === groupRole.name;
});
if (role) {
hasRole = true;
return;
}
});
}
return hasRole;
}));
}
/**
* Gets the client Id using the app name.
* @param applicationName Name of the app
* @returns client Id string
*/
getClientIdByApplicationName(applicationName: string): Observable<string> {
const url = this.getApplicationIdApi();
const httpMethod = 'GET', pathParams = {}, queryParams = {clientId: applicationName}, bodyParam = {}, headerParams = {}, formParams = {},
contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.alfrescoApiService.getInstance()
.oauth2Auth.callCustomApi(url, httpMethod, pathParams, queryParams, headerParams,
formParams, bodyParam, contentTypes,
accepts, Object, null, null)
).pipe(
map((response: any[]) => {
const clientId = response && response.length > 0 ? response[0].id : '';
return clientId;
}),
catchError((error) => this.handleError(error))
);
}
/**
* Gets client roles.
* @param groupId Id of the target group
* @param clientId Id of the client
* @returns List of roles
*/
getClientRoles(groupId: string, clientId: string): Observable<IdentityRoleModel[]> {
const url = this.groupClientRoleMappingApi(groupId, clientId);
const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null)
);
}
/**
* Checks if a group has a client app.
* @param groupId Id of the target group
* @param clientId Id of the client
* @returns True if the group has the client app, false otherwise
*/
checkGroupHasClientApp(groupId: string, clientId: string): Observable<boolean> {
return this.getClientRoles(groupId, clientId).pipe(
map((response: any[]) => {
if (response && response.length > 0) {
return true;
}
return false;
}),
catchError((error) => this.handleError(error))
);
}
/**
* Check if a group has any of the client app roles in the supplied list.
* @param groupId Id of the target group
* @param clientId Id of the client
* @param roleNames Array of role names to check
* @returns True if the group has one or more of the roles, false otherwise
*/
checkGroupHasAnyClientAppRole(groupId: string, clientId: string, roleNames: string[]): Observable<boolean> {
return this.getClientRoles(groupId, clientId).pipe(
map((clientRoles: any[]) => {
let hasRole = false;
if (clientRoles.length > 0) {
roleNames.forEach((roleName) => {
const role = clientRoles.find((availableRole) => {
return availableRole.name === roleName;
});
if (role) {
hasRole = true;
return;
}
});
}
return hasRole;
}),
catchError((error) => this.handleError(error))
);
}
private groupClientRoleMappingApi(groupId: string, clientId: string): string {
return `${this.appConfigService.get('identityHost')}/groups/${groupId}/role-mappings/clients/${clientId}`;
}
private getApplicationIdApi(): string {
return `${this.appConfigService.get('identityHost')}/clients`;
}
private getGroupsApi(): string {
return `${this.appConfigService.get('identityHost')}/groups`;
}
private buildRolesUrl(groupId: string): string {
return `${this.appConfigService.get('identityHost')}/groups/${groupId}/role-mappings/realm/composite`;
}
/**
* Throw the error
* @param error
*/
private handleError(error: Response) {
this.logService.error(error);
return throwError(error || 'Server error');
}
}

View File

@@ -667,19 +667,19 @@ export class IdentityUserService {
); );
} }
private buildUserUrl(): any { private buildUserUrl(): string {
return `${this.appConfigService.get('identityHost')}/users`; return `${this.appConfigService.get('identityHost')}/users`;
} }
private buildUserClientRoleMapping(userId: string, clientId: string): any { private buildUserClientRoleMapping(userId: string, clientId: string): string {
return `${this.appConfigService.get('identityHost')}/users/${userId}/role-mappings/clients/${clientId}`; return `${this.appConfigService.get('identityHost')}/users/${userId}/role-mappings/clients/${clientId}`;
} }
private buildRolesUrl(userId: string): any { private buildRolesUrl(userId: string): string {
return `${this.appConfigService.get('identityHost')}/users/${userId}/role-mappings/realm/composite`; return `${this.appConfigService.get('identityHost')}/users/${userId}/role-mappings/realm/composite`;
} }
private buildGetClientsUrl() { private buildGetClientsUrl(): string {
return `${this.appConfigService.get('identityHost')}/clients`; return `${this.appConfigService.get('identityHost')}/clients`;
} }

View File

@@ -22,17 +22,20 @@ import { ProcessServiceCloudTestingModule } from './../../testing/process-servic
import { GroupCloudModule } from '../group-cloud.module'; import { GroupCloudModule } from '../group-cloud.module';
import { GroupCloudComponent } from './group-cloud.component'; import { GroupCloudComponent } from './group-cloud.component';
import { GroupCloudService } from '../services/group-cloud.service'; import {
import { setupTestBed, AlfrescoApiServiceMock } from '@alfresco/adf-core'; setupTestBed,
import { mockGroups } from '../mock/group-cloud.mock'; AlfrescoApiServiceMock,
import { GroupModel } from '../models/group.model'; IdentityGroupService,
IdentityGroupModel,
mockIdentityGroups
} from '@alfresco/adf-core';
import { SimpleChange } from '@angular/core'; import { SimpleChange } from '@angular/core';
describe('GroupCloudComponent', () => { describe('GroupCloudComponent', () => {
let component: GroupCloudComponent; let component: GroupCloudComponent;
let fixture: ComponentFixture<GroupCloudComponent>; let fixture: ComponentFixture<GroupCloudComponent>;
let element: HTMLElement; let element: HTMLElement;
let service: GroupCloudService; let service: IdentityGroupService;
let findGroupsByNameSpy: jasmine.Spy; let findGroupsByNameSpy: jasmine.Spy;
let getClientIdByApplicationNameSpy: jasmine.Spy; let getClientIdByApplicationNameSpy: jasmine.Spy;
let checkGroupHasAccessSpy: jasmine.Spy; let checkGroupHasAccessSpy: jasmine.Spy;
@@ -40,15 +43,15 @@ describe('GroupCloudComponent', () => {
setupTestBed({ setupTestBed({
imports: [ProcessServiceCloudTestingModule, GroupCloudModule], imports: [ProcessServiceCloudTestingModule, GroupCloudModule],
providers: [AlfrescoApiServiceMock, GroupCloudService] providers: [AlfrescoApiServiceMock, IdentityGroupService]
}); });
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(GroupCloudComponent); fixture = TestBed.createComponent(GroupCloudComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
element = fixture.nativeElement; element = fixture.nativeElement;
service = TestBed.get(GroupCloudService); service = TestBed.get(IdentityGroupService);
findGroupsByNameSpy = spyOn(service, 'findGroupsByName').and.returnValue(of(mockGroups)); findGroupsByNameSpy = spyOn(service, 'findGroupsByName').and.returnValue(of(mockIdentityGroups));
getClientIdByApplicationNameSpy = spyOn(service, 'getClientIdByApplicationName').and.returnValue(of('mock-client-id')); getClientIdByApplicationNameSpy = spyOn(service, 'getClientIdByApplicationName').and.returnValue(of('mock-client-id'));
checkGroupHasAccessSpy = spyOn(service, 'checkGroupHasClientApp').and.returnValue(of(true)); checkGroupHasAccessSpy = spyOn(service, 'checkGroupHasClientApp').and.returnValue(of(true));
checkGroupHasGivenRoleSpy = spyOn(service, 'checkGroupHasRole').and.returnValue(of(true)); checkGroupHasGivenRoleSpy = spyOn(service, 'checkGroupHasRole').and.returnValue(of(true));
@@ -72,7 +75,7 @@ describe('GroupCloudComponent', () => {
it('should show the groups if the typed result match', async(() => { it('should show the groups if the typed result match', async(() => {
fixture.detectChanges(); fixture.detectChanges();
component.searchGroups$ = of(<GroupModel[]> mockGroups); component.searchGroups$.next(<IdentityGroupModel[]> mockIdentityGroups);
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
inputHTMLElement.focus(); inputHTMLElement.focus();
inputHTMLElement.dispatchEvent(new Event('input')); inputHTMLElement.dispatchEvent(new Event('input'));
@@ -103,7 +106,7 @@ describe('GroupCloudComponent', () => {
it('should emit selectedGroup if option is valid', async(() => { it('should emit selectedGroup if option is valid', async(() => {
fixture.detectChanges(); fixture.detectChanges();
const selectEmitSpy = spyOn(component.selectGroup, 'emit'); const selectEmitSpy = spyOn(component.selectGroup, 'emit');
component.onSelect(new GroupModel({ name: 'group name'})); component.onSelect(new IdentityGroupModel({ name: 'group name'}));
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
expect(selectEmitSpy).toHaveBeenCalled(); expect(selectEmitSpy).toHaveBeenCalled();
}); });
@@ -147,7 +150,7 @@ describe('GroupCloudComponent', () => {
it('should pre-select all preSelectGroups when mode=multiple', async(() => { it('should pre-select all preSelectGroups when mode=multiple', async(() => {
component.mode = 'multiple'; component.mode = 'multiple';
component.preSelectGroups = <any> [{id: mockGroups[1].id}, {id: mockGroups[2].id}]; component.preSelectGroups = <any> [{id: mockIdentityGroups[1].id}, {id: mockIdentityGroups[2].id}];
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
@@ -168,11 +171,11 @@ describe('GroupCloudComponent', () => {
it('should pre-select preSelectGroups[0] when mode=single', async(() => { it('should pre-select preSelectGroups[0] when mode=single', async(() => {
component.mode = 'single'; component.mode = 'single';
component.preSelectGroups = <any> [{id: mockGroups[1].id}, {id: mockGroups[2].id}]; component.preSelectGroups = <any> [{id: mockIdentityGroups[1].id}, {id: mockIdentityGroups[2].id}];
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
const selectedGroup = component.searchGroupsControl.value; const selectedGroup = component.searchGroupsControl.value;
expect(selectedGroup.id).toBe(mockGroups[1].id); expect(selectedGroup.id).toBe(mockIdentityGroups[1].id);
}); });
})); }));
@@ -189,7 +192,7 @@ describe('GroupCloudComponent', () => {
const removeGroupSpy = spyOn(component.removeGroup, 'emit'); const removeGroupSpy = spyOn(component.removeGroup, 'emit');
component.mode = 'multiple'; component.mode = 'multiple';
component.preSelectGroups = <any> [{id: mockGroups[1].id}, {id: mockGroups[2].id}]; component.preSelectGroups = <any> [{id: mockIdentityGroups[1].id}, {id: mockIdentityGroups[2].id}];
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
@@ -197,7 +200,7 @@ describe('GroupCloudComponent', () => {
const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon')); const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon'));
removeIcon.nativeElement.click(); removeIcon.nativeElement.click();
expect(removeGroupSpy).toHaveBeenCalledWith({ id: mockGroups[1].id }); expect(removeGroupSpy).toHaveBeenCalledWith({ id: mockIdentityGroups[1].id });
}); });
})); }));
@@ -213,7 +216,7 @@ describe('GroupCloudComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
const groupsList = fixture.debugElement.queryAll(By.css('mat-option')); const groupsList = fixture.debugElement.queryAll(By.css('mat-option'));
expect(groupsList.length).toBe(mockGroups.length); expect(groupsList.length).toBe(mockIdentityGroups.length);
}); });
})); }));
@@ -246,7 +249,7 @@ describe('GroupCloudComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
const groupsList = fixture.debugElement.queryAll(By.css('mat-option')); const groupsList = fixture.debugElement.queryAll(By.css('mat-option'));
expect(groupsList.length).toBe(mockGroups.length); expect(groupsList.length).toBe(mockIdentityGroups.length);
expect(checkGroupHasGivenRoleSpy).toHaveBeenCalled(); expect(checkGroupHasGivenRoleSpy).toHaveBeenCalled();
}); });
})); }));
@@ -263,13 +266,13 @@ describe('GroupCloudComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
const groupsList = fixture.debugElement.queryAll(By.css('mat-option')); const groupsList = fixture.debugElement.queryAll(By.css('mat-option'));
expect(groupsList.length).toBe(mockGroups.length); expect(groupsList.length).toBe(mockIdentityGroups.length);
expect(checkGroupHasGivenRoleSpy).not.toHaveBeenCalled(); expect(checkGroupHasGivenRoleSpy).not.toHaveBeenCalled();
}); });
})); }));
it('should validate access to the app when appName is specified', async(() => { it('should validate access to the app when appName is specified', async(() => {
findGroupsByNameSpy.and.returnValue(of(mockGroups)); findGroupsByNameSpy.and.returnValue(of(mockIdentityGroups));
checkGroupHasAccessSpy.and.returnValue(of(true)); checkGroupHasAccessSpy.and.returnValue(of(true));
fixture.detectChanges(); fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
@@ -279,7 +282,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(checkGroupHasAccessSpy).toHaveBeenCalledTimes(mockGroups.length); expect(checkGroupHasAccessSpy).toHaveBeenCalledTimes(mockIdentityGroups.length);
}); });
})); }));

View File

@@ -25,15 +25,15 @@ import {
ViewEncapsulation, ViewEncapsulation,
Input, Input,
SimpleChanges, SimpleChanges,
OnChanges OnChanges,
OnDestroy
} from '@angular/core'; } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { trigger, state, style, transition, animate } from '@angular/animations'; import { trigger, state, style, transition, animate } from '@angular/animations';
import { Observable, of, BehaviorSubject } from 'rxjs'; import { Observable, of, BehaviorSubject, Subject } from 'rxjs';
import { GroupModel, GroupSearchParam } from '../models/group.model';
import { GroupCloudService } from '../services/group-cloud.service';
import { debounceTime } from 'rxjs/internal/operators/debounceTime'; import { debounceTime } from 'rxjs/internal/operators/debounceTime';
import { distinctUntilChanged, switchMap, mergeMap, filter, tap, map } from 'rxjs/operators'; import { distinctUntilChanged, switchMap, mergeMap, filter, tap, map, takeUntil } from 'rxjs/operators';
import { IdentityGroupModel, IdentityGroupSearchParam, IdentityGroupService } from '@alfresco/adf-core';
@Component({ @Component({
selector: 'adf-cloud-group', selector: 'adf-cloud-group',
@@ -50,7 +50,7 @@ import { distinctUntilChanged, switchMap, mergeMap, filter, tap, map } from 'rxj
], ],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class GroupCloudComponent implements OnInit, OnChanges { export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
static MODE_SINGLE = 'single'; static MODE_SINGLE = 'single';
static MODE_MULTIPLE = 'multiple'; static MODE_MULTIPLE = 'multiple';
@@ -69,7 +69,7 @@ export class GroupCloudComponent implements OnInit, OnChanges {
/** Array of users to be pre-selected. This pre-selects all users in multi selection mode and only the first user of the array in single selection mode. */ /** Array of users to be pre-selected. This pre-selects all users in multi selection mode and only the first user of the array in single selection mode. */
@Input() @Input()
preSelectGroups: GroupModel[] = []; preSelectGroups: IdentityGroupModel[] = [];
/** FormControl to search the group */ /** FormControl to search the group */
@Input() @Input()
@@ -81,26 +81,22 @@ export class GroupCloudComponent implements OnInit, OnChanges {
/** Emitted when a group is selected. */ /** Emitted when a group is selected. */
@Output() @Output()
selectGroup: EventEmitter<GroupModel> = new EventEmitter<GroupModel>(); selectGroup = new EventEmitter<IdentityGroupModel>();
/** Emitted when a group is removed. */ /** Emitted when a group is removed. */
@Output() @Output()
removeGroup: EventEmitter<GroupModel> = new EventEmitter<GroupModel>(); removeGroup = new EventEmitter<IdentityGroupModel>();
@ViewChild('groupInput') @ViewChild('groupInput')
private groupInput: ElementRef<HTMLInputElement>; private groupInput: ElementRef<HTMLInputElement>;
private selectedGroups: GroupModel[] = []; private selectedGroups: IdentityGroupModel[] = [];
private searchGroups: GroupModel[] = []; private searchGroups: IdentityGroupModel[] = [];
private searchGroupsSubject: BehaviorSubject<GroupModel[]>; searchGroups$ = new BehaviorSubject<IdentityGroupModel[]>([]);
private selectedGroupsSubject: BehaviorSubject<GroupModel[]>; selectedGroups$ = new BehaviorSubject<IdentityGroupModel[]>([]);
searchGroups$: Observable<GroupModel[]>;
selectedGroups$: Observable<GroupModel[]>;
_subscriptAnimationState = 'enter'; _subscriptAnimationState = 'enter';
@@ -112,12 +108,9 @@ export class GroupCloudComponent implements OnInit, OnChanges {
isDisabled: boolean; isDisabled: boolean;
constructor(private groupService: GroupCloudService) { private onDestroy$ = new Subject<boolean>();
this.selectedGroupsSubject = new BehaviorSubject<GroupModel[]>(this.selectedGroups);
this.searchGroupsSubject = new BehaviorSubject<GroupModel[]>(this.searchGroups); constructor(private identityGroupService: IdentityGroupService) { }
this.selectedGroups$ = this.selectedGroupsSubject.asObservable();
this.searchGroups$ = this.searchGroupsSubject.asObservable();
}
ngOnInit() { ngOnInit() {
this.initSearch(); this.initSearch();
@@ -136,12 +129,12 @@ export class GroupCloudComponent implements OnInit, OnChanges {
} }
} }
private isAppNameChanged(change) { private isAppNameChanged(change): boolean {
return change.previousValue !== change.currentValue && this.appName && this.appName.length > 0; return change.previousValue !== change.currentValue && this.appName && this.appName.length > 0;
} }
private async loadClientId() { private async loadClientId() {
this.clientId = await this.groupService.getClientIdByApplicationName(this.appName).toPromise(); this.clientId = await this.identityGroupService.getClientIdByApplicationName(this.appName).toPromise();
if (this.clientId) { if (this.clientId) {
this.enableSearch(); this.enableSearch();
} }
@@ -165,7 +158,7 @@ export class GroupCloudComponent implements OnInit, OnChanges {
}), }),
switchMap((inputValue) => { switchMap((inputValue) => {
const queryParams = this.createSearchParam(inputValue); const queryParams = this.createSearchParam(inputValue);
return this.groupService.findGroupsByName(queryParams); return this.identityGroupService.findGroupsByName(queryParams);
}), }),
mergeMap((groups) => { mergeMap((groups) => {
return groups; return groups;
@@ -185,23 +178,24 @@ export class GroupCloudComponent implements OnInit, OnChanges {
} else { } else {
return of(group); return of(group);
} }
}) }),
).subscribe((searchedGroup) => { takeUntil(this.onDestroy$)
).subscribe((searchedGroup: any) => {
this.searchGroups.push(searchedGroup); this.searchGroups.push(searchedGroup);
this.searchGroupsSubject.next(this.searchGroups); this.searchGroups$.next(this.searchGroups);
}); });
} }
checkGroupHasAccess(groupId: string): Observable<boolean> { checkGroupHasAccess(groupId: string): Observable<boolean> {
if (this.hasRoles()) { if (this.hasRoles()) {
return this.groupService.checkGroupHasAnyClientAppRole(groupId, this.clientId, this.roles); return this.identityGroupService.checkGroupHasAnyClientAppRole(groupId, this.clientId, this.roles);
} else { } else {
return this.groupService.checkGroupHasClientApp(groupId, this.clientId); return this.identityGroupService.checkGroupHasClientApp(groupId, this.clientId);
} }
} }
isGroupAlreadySelected(group: GroupModel): boolean { isGroupAlreadySelected(group: IdentityGroupModel): boolean {
const result = this.selectedGroups.find((selectedGroup: GroupModel) => { const result = this.selectedGroups.find((selectedGroup: IdentityGroupModel) => {
return selectedGroup.id === group.id; return selectedGroup.id === group.id;
}); });
@@ -211,30 +205,30 @@ export class GroupCloudComponent implements OnInit, OnChanges {
private loadPreSelectGroups() { private loadPreSelectGroups() {
if (this.isMultipleMode()) { if (this.isMultipleMode()) {
this.selectedGroups = []; this.selectedGroups = [];
this.preSelectGroups.forEach((group: GroupModel) => { this.preSelectGroups.forEach((group: IdentityGroupModel) => {
this.selectedGroups.push(group); this.selectedGroups.push(group);
}); });
this.selectedGroupsSubject.next(this.selectedGroups); this.selectedGroups$.next(this.selectedGroups);
} else { } else {
this.searchGroupsControl.setValue(this.preSelectGroups[0]); this.searchGroupsControl.setValue(this.preSelectGroups[0]);
this.onSelect(this.preSelectGroups[0]); this.onSelect(this.preSelectGroups[0]);
} }
} }
filterGroupsByRoles(group: GroupModel): Observable<GroupModel> { filterGroupsByRoles(group: IdentityGroupModel): Observable<IdentityGroupModel> {
return this.groupService.checkGroupHasRole(group.id, this.roles).pipe( return this.identityGroupService.checkGroupHasRole(group.id, this.roles).pipe(
map((hasRole: boolean) => ({ hasRole: hasRole, group: group })), map((hasRole: boolean) => ({ hasRole: hasRole, group: group })),
filter((filteredGroup: { hasRole: boolean, group: GroupModel }) => filteredGroup.hasRole), filter((filteredGroup: { hasRole: boolean, group: IdentityGroupModel }) => filteredGroup.hasRole),
map((filteredGroup: { hasRole: boolean, group: GroupModel }) => filteredGroup.group)); map((filteredGroup: { hasRole: boolean, group: IdentityGroupModel }) => filteredGroup.group));
} }
onSelect(selectedGroup: GroupModel) { onSelect(selectedGroup: IdentityGroupModel) {
if (this.isMultipleMode()) { if (this.isMultipleMode()) {
if (!this.isGroupAlreadySelected(selectedGroup)) { if (!this.isGroupAlreadySelected(selectedGroup)) {
this.selectedGroups.push(selectedGroup); this.selectedGroups.push(selectedGroup);
this.selectedGroupsSubject.next(this.selectedGroups); this.selectedGroups$.next(this.selectedGroups);
this.selectGroup.emit(selectedGroup); this.selectGroup.emit(selectedGroup);
this.searchGroupsSubject.next([]); this.searchGroups$.next([]);
} }
this.groupInput.nativeElement.value = ''; this.groupInput.nativeElement.value = '';
this.searchGroupsControl.setValue(''); this.searchGroupsControl.setValue('');
@@ -246,25 +240,25 @@ export class GroupCloudComponent implements OnInit, OnChanges {
this.resetSearchGroups(); this.resetSearchGroups();
} }
onRemove(selectedGroup: GroupModel) { onRemove(selectedGroup: IdentityGroupModel) {
this.removeGroup.emit(selectedGroup); this.removeGroup.emit(selectedGroup);
const indexToRemove = this.selectedGroups.findIndex((group: GroupModel) => { const indexToRemove = this.selectedGroups.findIndex((group: IdentityGroupModel) => {
return group.id === selectedGroup.id; return group.id === selectedGroup.id;
}); });
this.selectedGroups.splice(indexToRemove, 1); this.selectedGroups.splice(indexToRemove, 1);
this.selectedGroupsSubject.next(this.selectedGroups); this.selectedGroups$.next(this.selectedGroups);
} }
private resetSearchGroups() { private resetSearchGroups() {
this.searchGroups = []; this.searchGroups = [];
this.searchGroupsSubject.next([]); this.searchGroups$.next([]);
} }
isMultipleMode(): boolean { isMultipleMode(): boolean {
return this.mode === GroupCloudComponent.MODE_MULTIPLE; return this.mode === GroupCloudComponent.MODE_MULTIPLE;
} }
getDisplayName(group: GroupModel): string { getDisplayName(group: IdentityGroupModel): string {
return group ? group.name : ''; return group ? group.name : '';
} }
@@ -272,8 +266,8 @@ export class GroupCloudComponent implements OnInit, OnChanges {
return this.preSelectGroups && this.preSelectGroups.length > 0; return this.preSelectGroups && this.preSelectGroups.length > 0;
} }
private createSearchParam(value: string): GroupSearchParam { private createSearchParam(value: string): IdentityGroupSearchParam {
const queryParams: GroupSearchParam = { name: value }; const queryParams: IdentityGroupSearchParam = { name: value };
return queryParams; return queryParams;
} }
@@ -310,4 +304,9 @@ export class GroupCloudComponent implements OnInit, OnChanges {
hasErrorMessage(): boolean { hasErrorMessage(): boolean {
return !this.isFocused && this.hasError(); return !this.isFocused && this.hasError();
} }
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
} }

View File

@@ -1,112 +0,0 @@
/*!
* @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 { GroupModel, GroupRoleModel } from '../models/group.model';
export let mockGroup1 = new GroupModel({
id: 'mock-id-1', name: 'Mock Group 1', path: '/mock', subGroups: []
});
export let mockGroup2 = new GroupModel({
id: 'mock-id-2', name: 'Mock Group 2', path: '', subGroups: []
});
export let mockGroup3 = new GroupModel({
id: 'mock-id-3', name: 'Fake Group 3', path: '', subGroups: []
});
export let mockGroups = [
mockGroup1, mockGroup2, mockGroup3
];
export let mockApplicationDetails = {id: 'mock-app-id', name: 'mock-app-name'};
export let mockError = {
error: {
errorKey: 'failed',
statusCode: 400,
stackTrace: 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.'
}
};
export let mockApiError = {
oauth2Auth: {
callCustomApi: () => {
return Promise.reject(mockError);
}
}
};
export let roleMappingMock = [
{ id: 'role-id-1', name: 'role-name-1' }, { id: 'role-id-2', name: 'role-name-2' }
];
export let roleMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(roleMappingMock);
}
}
};
export let noRoleMappingApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve([]);
}
}
};
export let groupsMockApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(mockGroups);
}
}
};
export let returnCallQueryParameters = {
oauth2Auth: {
callCustomApi: (queryUrl, operation, context, queryParams) => {
return Promise.resolve(queryParams);
}
}
};
export let returnCallUrl = {
oauth2Auth: {
callCustomApi: (queryUrl, operation, context, queryParams) => {
return Promise.resolve(queryUrl);
}
}
};
export let applicationDetailsMockApi = {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve([mockApplicationDetails]);
}
}
};
export let groupRoles = [
new GroupRoleModel({id: 'mock-id', name: 'MOCK-ADMIN-ROLE'}),
new GroupRoleModel({id: 'mock-id', name: 'MOCK-USER-ROLE'}),
new GroupRoleModel({id: 'mock-id', name: 'MOCK-ROLE-1'})
];
export let clientRoles = [ 'MOCK-ADMIN-ROLE', 'MOCK-USER-ROLE'];

View File

@@ -1,54 +0,0 @@
/*!
* @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.
*/
export class GroupModel {
id: string;
name: string;
path: string;
realmRoles: string[];
access: any;
attributes: any;
clientRoles: any;
constructor(obj?: any) {
this.id = obj.id || null;
this.name = obj.name || null;
this.path = obj.path || null;
this.realmRoles = obj.realmRoles || null;
this.access = obj.access || null;
this.attributes = obj.attributes || null;
this.clientRoles = obj.clientRoles || null;
}
}
export interface GroupSearchParam {
name?: string;
}
export class GroupRoleModel {
id?: string;
name: string;
constructor(obj?: any) {
if (obj) {
this.id = obj.id || null;
this.name = obj.name || null;
}
}
}

View File

@@ -16,16 +16,16 @@
*/ */
import { InitialGroupNamePipe } from './group-initial.pipe'; import { InitialGroupNamePipe } from './group-initial.pipe';
import { GroupModel } from '../models/group.model'; import { IdentityGroupModel } from '@alfresco/adf-core';
describe('InitialGroupNamePipe', () => { describe('InitialGroupNamePipe', () => {
let pipe: InitialGroupNamePipe; let pipe: InitialGroupNamePipe;
let fakeGroup: GroupModel; let fakeGroup: IdentityGroupModel;
beforeEach(() => { beforeEach(() => {
pipe = new InitialGroupNamePipe(); pipe = new InitialGroupNamePipe();
fakeGroup = new GroupModel({name: 'mock'}); fakeGroup = new IdentityGroupModel({name: 'mock'});
}); });
it('should return with the group initial', () => { it('should return with the group initial', () => {

View File

@@ -16,7 +16,7 @@
*/ */
import { Pipe, PipeTransform } from '@angular/core'; import { Pipe, PipeTransform } from '@angular/core';
import { GroupModel } from '../models/group.model'; import { IdentityGroupModel } from '@alfresco/adf-core';
@Pipe({ @Pipe({
name: 'groupNameInitial' name: 'groupNameInitial'
@@ -25,7 +25,7 @@ export class InitialGroupNamePipe implements PipeTransform {
constructor() {} constructor() {}
transform(group: GroupModel): string { transform(group: IdentityGroupModel): string {
let result = ''; let result = '';
if (group) { if (group) {
result = this.getInitialGroupName(group.name).toUpperCase(); result = this.getInitialGroupName(group.name).toUpperCase();

View File

@@ -15,7 +15,5 @@
* limitations under the License. * limitations under the License.
*/ */
export * from './models/group.model';
export * from './services/group-cloud.service';
export * from './components/group-cloud.component'; export * from './components/group-cloud.component';
export * from './group-cloud.module'; export * from './group-cloud.module';

View File

@@ -1,212 +0,0 @@
/*!
* @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 { from, of, Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
import { GroupSearchParam, GroupRoleModel } from '../models/group.model';
@Injectable({
providedIn: 'root'
})
export class GroupCloudService {
constructor(
private apiService: AlfrescoApiService,
private appConfigService: AppConfigService,
private logService: LogService
) {}
/**
* Finds groups filtered by name.
* @param searchParams Object containing the name filter string
* @returns List of group information
*/
findGroupsByName(searchParams: GroupSearchParam): Observable<any> {
if (searchParams.name === '') {
return of([]);
}
const url = this.getGroupsApi();
const httpMethod = 'GET', pathParams = {}, queryParams = {search: searchParams.name}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.apiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null)
)).pipe(
catchError((err) => this.handleError(err))
);
}
/**
* Gets details for a specified group.
* @param groupId ID of the target group
* @returns Group details
*/
getGroupRoles(groupId: string): Observable<GroupRoleModel[]> {
const url = this.buildRolesUrl(groupId);
const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.apiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null)
)).pipe(
catchError((err) => this.handleError(err))
);
}
/**
* Check that a group has one or more roles from the supplied list.
* @param groupId ID of the target group
* @param roleNames Array of role names
* @returns True if the group has one or more of the roles, false otherwise
*/
checkGroupHasRole(groupId: string, roleNames: string[]): Observable<boolean> {
return this.getGroupRoles(groupId).pipe(map((groupRoles: GroupRoleModel[]) => {
let hasRole = false;
if (groupRoles && groupRoles.length > 0) {
roleNames.forEach((roleName: string) => {
const role = groupRoles.find((groupRole) => {
return roleName === groupRole.name;
});
if (role) {
hasRole = true;
return;
}
});
}
return hasRole;
}));
}
/**
* Gets the client ID using the app name.
* @param applicationName Name of the app
* @returns client ID string
*/
getClientIdByApplicationName(applicationName: string): Observable<string> {
const url = this.getApplicationIdApi();
const httpMethod = 'GET', pathParams = {}, queryParams = {clientId: applicationName}, bodyParam = {}, headerParams = {}, formParams = {},
contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(url, httpMethod, pathParams, queryParams, headerParams,
formParams, bodyParam, contentTypes,
accepts, Object, null, null)
).pipe(
map((response: any[]) => {
const clientId = response && response.length > 0 ? response[0].id : '';
return clientId;
}),
catchError((err) => this.handleError(err))
);
}
/**
* Gets client roles.
* @param groupId ID of the target group
* @param clientId ID of the client
* @returns List of roles
*/
getClientRoles(groupId: string, clientId: string): Observable<any[]> {
const url = this.groupClientRoleMappingApi(groupId, clientId);
const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.apiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null)
);
}
/**
* Checks if a group has a client app.
* @param groupId ID of the target group
* @param clientId ID of the client
* @returns True if the group has the client app, false otherwise
*/
checkGroupHasClientApp(groupId: string, clientId: string): Observable<boolean> {
return this.getClientRoles(groupId, clientId).pipe(
map((response: any[]) => {
if (response && response.length > 0) {
return true;
}
return false;
}),
catchError((err) => this.handleError(err))
);
}
/**
* Check if a group has any of the client app roles in the supplied list.
* @param groupId ID of the target group
* @param clientId ID of the client
* @param roleNames Array of role names to check
* @returns True if the group has one or more of the roles, false otherwise
*/
checkGroupHasAnyClientAppRole(groupId: string, clientId: string, roleNames: string[]): Observable<boolean> {
return this.getClientRoles(groupId, clientId).pipe(
map((clientRoles: any[]) => {
let hasRole = false;
if (clientRoles.length > 0) {
roleNames.forEach((roleName) => {
const role = clientRoles.find((availableRole) => {
return availableRole.name === roleName;
});
if (role) {
hasRole = true;
return;
}
});
}
return hasRole;
}),
catchError((err) => this.handleError(err))
);
}
private groupClientRoleMappingApi(groupId: string, clientId: string): any {
return `${this.appConfigService.get('identityHost')}/groups/${groupId}/role-mappings/clients/${clientId}`;
}
private getApplicationIdApi() {
return `${this.appConfigService.get('identityHost')}/clients`;
}
private getGroupsApi() {
return `${this.appConfigService.get('identityHost')}/groups`;
}
private buildRolesUrl(groupId: string): any {
return `${this.appConfigService.get('identityHost')}/groups/${groupId}/role-mappings/realm/composite`;
}
/**
* Throw the error
* @param error
*/
private handleError(error: Response) {
this.logService.error(error);
return throwError(error || 'Server error');
}
}