mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[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:
committed by
Eugenio Romano
parent
4ead51d2a6
commit
eb2811fdd0
@@ -16,8 +16,9 @@
|
||||
*/
|
||||
|
||||
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 { IdentityGroupModel } from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-people-groups-cloud',
|
||||
@@ -39,8 +40,8 @@ export class PeopleGroupCloudDemoComponent {
|
||||
peoplePreselectValidation: Boolean = false;
|
||||
|
||||
groupMode: string = GroupCloudComponent.MODE_SINGLE;
|
||||
preSelectGroup: GroupModel[] = [];
|
||||
selectedGroupList: GroupModel[] = [];
|
||||
preSelectGroup: IdentityGroupModel[] = [];
|
||||
selectedGroupList: IdentityGroupModel[] = [];
|
||||
groupRoles: string[];
|
||||
groupAppName: string;
|
||||
groupFilterMode: string = this.DEFAULT_FILTER_MODE;
|
||||
@@ -144,11 +145,11 @@ export class PeopleGroupCloudDemoComponent {
|
||||
return this.groupMode === GroupCloudComponent.MODE_MULTIPLE;
|
||||
}
|
||||
|
||||
onRemoveGroup(group: GroupModel) {
|
||||
onRemoveGroup(group: IdentityGroupModel) {
|
||||
this.preSelectGroup = this.preSelectGroup.filter((value: any) => value.id !== group.id);
|
||||
}
|
||||
|
||||
onSelectGroup(group: GroupModel) {
|
||||
onSelectGroup(group: IdentityGroupModel) {
|
||||
if (this.groupMode === GroupCloudComponent.MODE_MULTIPLE) {
|
||||
this.preSelectGroup.push(group);
|
||||
}
|
||||
|
75
docs/core/services/identity-group.service.md
Normal file
75
docs/core/services/identity-group.service.md
Normal 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)
|
@@ -28,7 +28,7 @@ Searches Groups.
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| 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). |
|
||||
| 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. |
|
||||
| searchGroupsControl | `FormControl` | new FormControl() | FormControl to search the group |
|
||||
| title | `string` | | Title of the field |
|
||||
@@ -37,8 +37,8 @@ Searches Groups.
|
||||
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 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)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`>` | Emitted when a group is selected. |
|
||||
|
||||
## Details
|
||||
|
||||
|
@@ -23,7 +23,7 @@ Extracts the initial character from a group name.
|
||||
|
||||
## 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`
|
||||
property. The initial is a handy way to identify the group in lists and
|
||||
other situations where there is limited screen space available.
|
||||
|
163
lib/core/mock/identity-group.service.mock.ts
Normal file
163
lib/core/mock/identity-group.service.mock.ts
Normal 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'];
|
@@ -37,3 +37,4 @@ export * from './form/start-form.component.mock';
|
||||
export * from './form/form.service.mock';
|
||||
export * from './form/widget-visibility.service.mock';
|
||||
export * from './jwt-helper.service.spec';
|
||||
export * from './identity-group.service.mock';
|
||||
|
@@ -14,6 +14,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
|
||||
export class IdentityGroupModel {
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -19,8 +19,10 @@ export * from './components/user-info.component';
|
||||
export * from './services/bpm-user.service';
|
||||
export * from './services/ecm-user.service';
|
||||
export * from './services/identity-user.service';
|
||||
export * from './services/identity-group.service';
|
||||
export * from './models/bpm-user.model';
|
||||
export * from './models/ecm-user.model';
|
||||
export * from './models/identity-group.model';
|
||||
export * from './models/identity-user.model';
|
||||
export * from './models/identity-role.model';
|
||||
export * from './models/identity-group.model';
|
||||
|
@@ -17,32 +17,37 @@
|
||||
|
||||
import { async } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { GroupCloudService } from './group-cloud.service';
|
||||
import {
|
||||
AlfrescoApiServiceMock,
|
||||
CoreModule,
|
||||
setupTestBed,
|
||||
AlfrescoApiService,
|
||||
LogService
|
||||
LogService,
|
||||
IdentityGroupService,
|
||||
IdentityGroupSearchParam,
|
||||
groupAPIMockError
|
||||
} 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 { 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', () => {
|
||||
let service: GroupCloudService;
|
||||
describe('IdentityGroupService', () => {
|
||||
let service: IdentityGroupService;
|
||||
let apiService: AlfrescoApiService;
|
||||
let logService: LogService;
|
||||
|
||||
@@ -54,23 +59,23 @@ describe('GroupCloudService', () => {
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
service = TestBed.get(GroupCloudService);
|
||||
service = TestBed.get(IdentityGroupService);
|
||||
apiService = TestBed.get(AlfrescoApiService);
|
||||
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);
|
||||
service.findGroupsByName(<GroupSearchParam> {name: 'mock'}).subscribe((res) => {
|
||||
service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).not.toBeNull();
|
||||
expect(res.length).toBe(3);
|
||||
expect(res[0].id).toBe('mock-id-1');
|
||||
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-id-2');
|
||||
expect(res[1].id).toBe('mock-group-id-2');
|
||||
expect(res[1].name).toBe('Mock Group 2');
|
||||
expect(res[2].id).toBe('mock-id-3');
|
||||
expect(res[2].name).toBe('Fake Group 3');
|
||||
expect(res[2].id).toBe('mock-group-id-3');
|
||||
expect(res[2].name).toBe('Mock Group 3');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -94,7 +99,7 @@ describe('GroupCloudService', () => {
|
||||
});
|
||||
|
||||
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(
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
@@ -130,7 +135,7 @@ describe('GroupCloudService', () => {
|
||||
});
|
||||
|
||||
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(
|
||||
(res: boolean) => {
|
||||
expect(res).toBeDefined();
|
||||
@@ -141,7 +146,7 @@ describe('GroupCloudService', () => {
|
||||
});
|
||||
|
||||
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(
|
||||
(res: boolean) => {
|
||||
expect(res).toBeDefined();
|
||||
@@ -231,7 +236,7 @@ describe('GroupCloudService', () => {
|
||||
|
||||
it('should append to the call all the parameters', (done) => {
|
||||
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).not.toBeNull();
|
||||
expect(res.search).toBe('mock');
|
||||
@@ -241,7 +246,7 @@ describe('GroupCloudService', () => {
|
||||
|
||||
it('should request groups api url', (done) => {
|
||||
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).not.toBeNull();
|
||||
expect(requestUrl).toContain('/groups');
|
||||
@@ -262,14 +267,184 @@ describe('GroupCloudService', () => {
|
||||
it('should notify errors returned from the API', (done) => {
|
||||
const logServiceSpy = spyOn(logService, 'error').and.callThrough();
|
||||
spyOn(apiService, 'getInstance').and.returnValue(mockApiError);
|
||||
service.findGroupsByName(<GroupSearchParam> {name: 'mock'}).subscribe(
|
||||
service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe(
|
||||
() => {},
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).toEqual(mockError);
|
||||
expect(res).toEqual(groupAPIMockError);
|
||||
expect(logServiceSpy).toHaveBeenCalled();
|
||||
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();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
347
lib/core/userinfo/services/identity-group.service.ts
Normal file
347
lib/core/userinfo/services/identity-group.service.ts
Normal 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');
|
||||
}
|
||||
}
|
@@ -667,19 +667,19 @@ export class IdentityUserService {
|
||||
);
|
||||
}
|
||||
|
||||
private buildUserUrl(): any {
|
||||
private buildUserUrl(): string {
|
||||
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}`;
|
||||
}
|
||||
|
||||
private buildRolesUrl(userId: string): any {
|
||||
private buildRolesUrl(userId: string): string {
|
||||
return `${this.appConfigService.get('identityHost')}/users/${userId}/role-mappings/realm/composite`;
|
||||
}
|
||||
|
||||
private buildGetClientsUrl() {
|
||||
private buildGetClientsUrl(): string {
|
||||
return `${this.appConfigService.get('identityHost')}/clients`;
|
||||
}
|
||||
|
||||
|
@@ -22,17 +22,20 @@ import { ProcessServiceCloudTestingModule } from './../../testing/process-servic
|
||||
|
||||
import { GroupCloudModule } from '../group-cloud.module';
|
||||
import { GroupCloudComponent } from './group-cloud.component';
|
||||
import { GroupCloudService } from '../services/group-cloud.service';
|
||||
import { setupTestBed, AlfrescoApiServiceMock } from '@alfresco/adf-core';
|
||||
import { mockGroups } from '../mock/group-cloud.mock';
|
||||
import { GroupModel } from '../models/group.model';
|
||||
import {
|
||||
setupTestBed,
|
||||
AlfrescoApiServiceMock,
|
||||
IdentityGroupService,
|
||||
IdentityGroupModel,
|
||||
mockIdentityGroups
|
||||
} from '@alfresco/adf-core';
|
||||
import { SimpleChange } from '@angular/core';
|
||||
|
||||
describe('GroupCloudComponent', () => {
|
||||
let component: GroupCloudComponent;
|
||||
let fixture: ComponentFixture<GroupCloudComponent>;
|
||||
let element: HTMLElement;
|
||||
let service: GroupCloudService;
|
||||
let service: IdentityGroupService;
|
||||
let findGroupsByNameSpy: jasmine.Spy;
|
||||
let getClientIdByApplicationNameSpy: jasmine.Spy;
|
||||
let checkGroupHasAccessSpy: jasmine.Spy;
|
||||
@@ -40,15 +43,15 @@ describe('GroupCloudComponent', () => {
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessServiceCloudTestingModule, GroupCloudModule],
|
||||
providers: [AlfrescoApiServiceMock, GroupCloudService]
|
||||
providers: [AlfrescoApiServiceMock, IdentityGroupService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GroupCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
service = TestBed.get(GroupCloudService);
|
||||
findGroupsByNameSpy = spyOn(service, 'findGroupsByName').and.returnValue(of(mockGroups));
|
||||
service = TestBed.get(IdentityGroupService);
|
||||
findGroupsByNameSpy = spyOn(service, 'findGroupsByName').and.returnValue(of(mockIdentityGroups));
|
||||
getClientIdByApplicationNameSpy = spyOn(service, 'getClientIdByApplicationName').and.returnValue(of('mock-client-id'));
|
||||
checkGroupHasAccessSpy = spyOn(service, 'checkGroupHasClientApp').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(() => {
|
||||
fixture.detectChanges();
|
||||
component.searchGroups$ = of(<GroupModel[]> mockGroups);
|
||||
component.searchGroups$.next(<IdentityGroupModel[]> mockIdentityGroups);
|
||||
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
||||
inputHTMLElement.focus();
|
||||
inputHTMLElement.dispatchEvent(new Event('input'));
|
||||
@@ -103,7 +106,7 @@ describe('GroupCloudComponent', () => {
|
||||
it('should emit selectedGroup if option is valid', async(() => {
|
||||
fixture.detectChanges();
|
||||
const selectEmitSpy = spyOn(component.selectGroup, 'emit');
|
||||
component.onSelect(new GroupModel({ name: 'group name'}));
|
||||
component.onSelect(new IdentityGroupModel({ name: 'group name'}));
|
||||
fixture.whenStable().then(() => {
|
||||
expect(selectEmitSpy).toHaveBeenCalled();
|
||||
});
|
||||
@@ -147,7 +150,7 @@ describe('GroupCloudComponent', () => {
|
||||
|
||||
it('should pre-select all preSelectGroups when mode=multiple', async(() => {
|
||||
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.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
@@ -168,11 +171,11 @@ describe('GroupCloudComponent', () => {
|
||||
|
||||
it('should pre-select preSelectGroups[0] when mode=single', async(() => {
|
||||
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.whenStable().then(() => {
|
||||
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');
|
||||
|
||||
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.whenStable().then(() => {
|
||||
@@ -197,7 +200,7 @@ describe('GroupCloudComponent', () => {
|
||||
const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon'));
|
||||
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.detectChanges();
|
||||
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.detectChanges();
|
||||
const groupsList = fixture.debugElement.queryAll(By.css('mat-option'));
|
||||
expect(groupsList.length).toBe(mockGroups.length);
|
||||
expect(groupsList.length).toBe(mockIdentityGroups.length);
|
||||
expect(checkGroupHasGivenRoleSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
@@ -263,13 +266,13 @@ describe('GroupCloudComponent', () => {
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
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();
|
||||
});
|
||||
}));
|
||||
|
||||
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));
|
||||
fixture.detectChanges();
|
||||
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
||||
@@ -279,7 +282,7 @@ describe('GroupCloudComponent', () => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(checkGroupHasAccessSpy).toHaveBeenCalledTimes(mockGroups.length);
|
||||
expect(checkGroupHasAccessSpy).toHaveBeenCalledTimes(mockIdentityGroups.length);
|
||||
});
|
||||
}));
|
||||
|
||||
|
@@ -25,15 +25,15 @@ import {
|
||||
ViewEncapsulation,
|
||||
Input,
|
||||
SimpleChanges,
|
||||
OnChanges
|
||||
OnChanges,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { trigger, state, style, transition, animate } from '@angular/animations';
|
||||
import { Observable, of, BehaviorSubject } from 'rxjs';
|
||||
import { GroupModel, GroupSearchParam } from '../models/group.model';
|
||||
import { GroupCloudService } from '../services/group-cloud.service';
|
||||
import { Observable, of, BehaviorSubject, Subject } from 'rxjs';
|
||||
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({
|
||||
selector: 'adf-cloud-group',
|
||||
@@ -50,7 +50,7 @@ import { distinctUntilChanged, switchMap, mergeMap, filter, tap, map } from 'rxj
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
static MODE_SINGLE = 'single';
|
||||
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. */
|
||||
@Input()
|
||||
preSelectGroups: GroupModel[] = [];
|
||||
preSelectGroups: IdentityGroupModel[] = [];
|
||||
|
||||
/** FormControl to search the group */
|
||||
@Input()
|
||||
@@ -81,26 +81,22 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
|
||||
/** Emitted when a group is selected. */
|
||||
@Output()
|
||||
selectGroup: EventEmitter<GroupModel> = new EventEmitter<GroupModel>();
|
||||
selectGroup = new EventEmitter<IdentityGroupModel>();
|
||||
|
||||
/** Emitted when a group is removed. */
|
||||
@Output()
|
||||
removeGroup: EventEmitter<GroupModel> = new EventEmitter<GroupModel>();
|
||||
removeGroup = new EventEmitter<IdentityGroupModel>();
|
||||
|
||||
@ViewChild('groupInput')
|
||||
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[]>;
|
||||
|
||||
searchGroups$: Observable<GroupModel[]>;
|
||||
|
||||
selectedGroups$: Observable<GroupModel[]>;
|
||||
selectedGroups$ = new BehaviorSubject<IdentityGroupModel[]>([]);
|
||||
|
||||
_subscriptAnimationState = 'enter';
|
||||
|
||||
@@ -112,12 +108,9 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
|
||||
isDisabled: boolean;
|
||||
|
||||
constructor(private groupService: GroupCloudService) {
|
||||
this.selectedGroupsSubject = new BehaviorSubject<GroupModel[]>(this.selectedGroups);
|
||||
this.searchGroupsSubject = new BehaviorSubject<GroupModel[]>(this.searchGroups);
|
||||
this.selectedGroups$ = this.selectedGroupsSubject.asObservable();
|
||||
this.searchGroups$ = this.searchGroupsSubject.asObservable();
|
||||
}
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private identityGroupService: IdentityGroupService) { }
|
||||
|
||||
ngOnInit() {
|
||||
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;
|
||||
}
|
||||
|
||||
private async loadClientId() {
|
||||
this.clientId = await this.groupService.getClientIdByApplicationName(this.appName).toPromise();
|
||||
this.clientId = await this.identityGroupService.getClientIdByApplicationName(this.appName).toPromise();
|
||||
if (this.clientId) {
|
||||
this.enableSearch();
|
||||
}
|
||||
@@ -165,7 +158,7 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
}),
|
||||
switchMap((inputValue) => {
|
||||
const queryParams = this.createSearchParam(inputValue);
|
||||
return this.groupService.findGroupsByName(queryParams);
|
||||
return this.identityGroupService.findGroupsByName(queryParams);
|
||||
}),
|
||||
mergeMap((groups) => {
|
||||
return groups;
|
||||
@@ -185,23 +178,24 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
} else {
|
||||
return of(group);
|
||||
}
|
||||
})
|
||||
).subscribe((searchedGroup) => {
|
||||
}),
|
||||
takeUntil(this.onDestroy$)
|
||||
).subscribe((searchedGroup: any) => {
|
||||
this.searchGroups.push(searchedGroup);
|
||||
this.searchGroupsSubject.next(this.searchGroups);
|
||||
this.searchGroups$.next(this.searchGroups);
|
||||
});
|
||||
}
|
||||
|
||||
checkGroupHasAccess(groupId: string): Observable<boolean> {
|
||||
if (this.hasRoles()) {
|
||||
return this.groupService.checkGroupHasAnyClientAppRole(groupId, this.clientId, this.roles);
|
||||
return this.identityGroupService.checkGroupHasAnyClientAppRole(groupId, this.clientId, this.roles);
|
||||
} else {
|
||||
return this.groupService.checkGroupHasClientApp(groupId, this.clientId);
|
||||
return this.identityGroupService.checkGroupHasClientApp(groupId, this.clientId);
|
||||
}
|
||||
}
|
||||
|
||||
isGroupAlreadySelected(group: GroupModel): boolean {
|
||||
const result = this.selectedGroups.find((selectedGroup: GroupModel) => {
|
||||
isGroupAlreadySelected(group: IdentityGroupModel): boolean {
|
||||
const result = this.selectedGroups.find((selectedGroup: IdentityGroupModel) => {
|
||||
return selectedGroup.id === group.id;
|
||||
});
|
||||
|
||||
@@ -211,30 +205,30 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
private loadPreSelectGroups() {
|
||||
if (this.isMultipleMode()) {
|
||||
this.selectedGroups = [];
|
||||
this.preSelectGroups.forEach((group: GroupModel) => {
|
||||
this.preSelectGroups.forEach((group: IdentityGroupModel) => {
|
||||
this.selectedGroups.push(group);
|
||||
});
|
||||
this.selectedGroupsSubject.next(this.selectedGroups);
|
||||
this.selectedGroups$.next(this.selectedGroups);
|
||||
} else {
|
||||
this.searchGroupsControl.setValue(this.preSelectGroups[0]);
|
||||
this.onSelect(this.preSelectGroups[0]);
|
||||
}
|
||||
}
|
||||
|
||||
filterGroupsByRoles(group: GroupModel): Observable<GroupModel> {
|
||||
return this.groupService.checkGroupHasRole(group.id, this.roles).pipe(
|
||||
filterGroupsByRoles(group: IdentityGroupModel): Observable<IdentityGroupModel> {
|
||||
return this.identityGroupService.checkGroupHasRole(group.id, this.roles).pipe(
|
||||
map((hasRole: boolean) => ({ hasRole: hasRole, group: group })),
|
||||
filter((filteredGroup: { hasRole: boolean, group: GroupModel }) => filteredGroup.hasRole),
|
||||
map((filteredGroup: { hasRole: boolean, group: GroupModel }) => filteredGroup.group));
|
||||
filter((filteredGroup: { hasRole: boolean, group: IdentityGroupModel }) => filteredGroup.hasRole),
|
||||
map((filteredGroup: { hasRole: boolean, group: IdentityGroupModel }) => filteredGroup.group));
|
||||
}
|
||||
|
||||
onSelect(selectedGroup: GroupModel) {
|
||||
onSelect(selectedGroup: IdentityGroupModel) {
|
||||
if (this.isMultipleMode()) {
|
||||
if (!this.isGroupAlreadySelected(selectedGroup)) {
|
||||
this.selectedGroups.push(selectedGroup);
|
||||
this.selectedGroupsSubject.next(this.selectedGroups);
|
||||
this.selectedGroups$.next(this.selectedGroups);
|
||||
this.selectGroup.emit(selectedGroup);
|
||||
this.searchGroupsSubject.next([]);
|
||||
this.searchGroups$.next([]);
|
||||
}
|
||||
this.groupInput.nativeElement.value = '';
|
||||
this.searchGroupsControl.setValue('');
|
||||
@@ -246,25 +240,25 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
this.resetSearchGroups();
|
||||
}
|
||||
|
||||
onRemove(selectedGroup: GroupModel) {
|
||||
onRemove(selectedGroup: IdentityGroupModel) {
|
||||
this.removeGroup.emit(selectedGroup);
|
||||
const indexToRemove = this.selectedGroups.findIndex((group: GroupModel) => {
|
||||
const indexToRemove = this.selectedGroups.findIndex((group: IdentityGroupModel) => {
|
||||
return group.id === selectedGroup.id;
|
||||
});
|
||||
this.selectedGroups.splice(indexToRemove, 1);
|
||||
this.selectedGroupsSubject.next(this.selectedGroups);
|
||||
this.selectedGroups$.next(this.selectedGroups);
|
||||
}
|
||||
|
||||
private resetSearchGroups() {
|
||||
this.searchGroups = [];
|
||||
this.searchGroupsSubject.next([]);
|
||||
this.searchGroups$.next([]);
|
||||
}
|
||||
|
||||
isMultipleMode(): boolean {
|
||||
return this.mode === GroupCloudComponent.MODE_MULTIPLE;
|
||||
}
|
||||
|
||||
getDisplayName(group: GroupModel): string {
|
||||
getDisplayName(group: IdentityGroupModel): string {
|
||||
return group ? group.name : '';
|
||||
}
|
||||
|
||||
@@ -272,8 +266,8 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
return this.preSelectGroups && this.preSelectGroups.length > 0;
|
||||
}
|
||||
|
||||
private createSearchParam(value: string): GroupSearchParam {
|
||||
const queryParams: GroupSearchParam = { name: value };
|
||||
private createSearchParam(value: string): IdentityGroupSearchParam {
|
||||
const queryParams: IdentityGroupSearchParam = { name: value };
|
||||
return queryParams;
|
||||
}
|
||||
|
||||
@@ -310,4 +304,9 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
hasErrorMessage(): boolean {
|
||||
return !this.isFocused && this.hasError();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
}
|
||||
|
@@ -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'];
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,16 +16,16 @@
|
||||
*/
|
||||
|
||||
import { InitialGroupNamePipe } from './group-initial.pipe';
|
||||
import { GroupModel } from '../models/group.model';
|
||||
import { IdentityGroupModel } from '@alfresco/adf-core';
|
||||
|
||||
describe('InitialGroupNamePipe', () => {
|
||||
|
||||
let pipe: InitialGroupNamePipe;
|
||||
let fakeGroup: GroupModel;
|
||||
let fakeGroup: IdentityGroupModel;
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new InitialGroupNamePipe();
|
||||
fakeGroup = new GroupModel({name: 'mock'});
|
||||
fakeGroup = new IdentityGroupModel({name: 'mock'});
|
||||
});
|
||||
|
||||
it('should return with the group initial', () => {
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { GroupModel } from '../models/group.model';
|
||||
import { IdentityGroupModel } from '@alfresco/adf-core';
|
||||
|
||||
@Pipe({
|
||||
name: 'groupNameInitial'
|
||||
@@ -25,7 +25,7 @@ export class InitialGroupNamePipe implements PipeTransform {
|
||||
|
||||
constructor() {}
|
||||
|
||||
transform(group: GroupModel): string {
|
||||
transform(group: IdentityGroupModel): string {
|
||||
let result = '';
|
||||
if (group) {
|
||||
result = this.getInitialGroupName(group.name).toUpperCase();
|
||||
|
@@ -15,7 +15,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './models/group.model';
|
||||
export * from './services/group-cloud.service';
|
||||
export * from './components/group-cloud.component';
|
||||
export * from './group-cloud.module';
|
||||
|
@@ -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');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user