From 3b455524b97c358150c172f09e043db153cb7cd8 Mon Sep 17 00:00:00 2001 From: siva kumar Date: Mon, 4 Feb 2019 17:59:10 +0530 Subject: [PATCH] [ADF-3919] Add roles filtering to adf-cloud-group (#4238) * [ADF-3919] Split group roles permission service into two * [ADF-3909] Added roles filtering title input * [ADF-3909] Added candate users and groups to task models * [ADF-3909] Used group component in start task * [ADF-3909] Updated docs * [ADF-3909] Added disabling for multi selection * [ADF-3909] Improved task creation logic * [ADF-3909] Changed assignee selection mechanism * * Added role filtering to groups* Updated unit tests to the recent changes* Created getGroupDetailsById and checkGroupHasGivenRole in groupService* Updated unit test to the groupService * * After rebase * * Changed method name checkGroupHasGivenRole to checkGroupHasRole * * After rebase --- .../group-cloud.component.md | 10 +- .../components/group-cloud.component.html | 16 +- .../components/group-cloud.component.spec.ts | 50 +++++- .../group/components/group-cloud.component.ts | 155 ++++++++++-------- .../src/lib/group/mock/group-cloud.mock.ts | 6 + .../services/group-cloud.service.spec.ts | 146 ++++++++++++++++- .../lib/group/services/group-cloud.service.ts | 66 +++++++- .../src/lib/i18n/en.json | 1 + .../start-task-cloud.component.html | 17 +- .../components/start-task-cloud.component.ts | 40 +++-- .../models/start-task-cloud-request.model.ts | 4 +- .../models/task-details-cloud.model.ts | 4 +- .../start-task/start-task-cloud.module.ts | 3 +- 13 files changed, 397 insertions(+), 121 deletions(-) diff --git a/docs/process-services-cloud/group-cloud.component.md b/docs/process-services-cloud/group-cloud.component.md index 76b8538ad7..23c4bc8117 100644 --- a/docs/process-services-cloud/group-cloud.component.md +++ b/docs/process-services-cloud/group-cloud.component.md @@ -5,7 +5,7 @@ Status: Experimental Last reviewed: 2019-01-15 --- -# [Group Cloud component](../../process-services-cloud/src/lib/group/components/group-cloud.component.ts "Defined in group-cloud.component.ts") +# [Group Cloud component](../../lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts "Defined in group-cloud.component.ts") Searches Groups. @@ -28,14 +28,16 @@ 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`](../../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 | [`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. | +| roles | `string[]` | | Role names of the groups to be listed. | +| title | `string` | | Title of the field | ### Events | Name | Type | Description | | ---- | ---- | ----------- | -| removeGroup | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`GroupModel`](../../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`](../../process-services-cloud/src/lib/group/models/group.model.ts)`>` | Emitted when a group is selected. | +| 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. | ## Details diff --git a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.html b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.html index 4d296d4a31..a7a386ecb0 100644 --- a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.html +++ b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.html @@ -1,6 +1,7 @@
- + {{ (title || 'ADF_CLOUD_GROUPS.SEARCH-GROUP') | translate }} + cancel - + [matAutocomplete]="auto"> -
+
{{ 'ADF_CLOUD_GROUPS.ERROR.NOT_FOUND' | translate : { groupName : searchedValue } }} diff --git a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts index 7a43cf21bc..ef3c64b763 100644 --- a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts @@ -34,7 +34,8 @@ describe('GroupCloudComponent', () => { let service: GroupCloudService; let findGroupsByNameSpy: jasmine.Spy; let getClientIdByApplicationNameSpy: jasmine.Spy; - let checkGroupHasClientRoleMappingSpy: jasmine.Spy; + let checkGroupHasAccessSpy: jasmine.Spy; + let checkGroupHasGivenRoleSpy: jasmine.Spy; setupTestBed({ imports: [ProcessServiceCloudTestingModule, GroupCloudModule], @@ -48,7 +49,8 @@ describe('GroupCloudComponent', () => { service = TestBed.get(GroupCloudService); findGroupsByNameSpy = spyOn(service, 'findGroupsByName').and.returnValue(of(mockGroups)); getClientIdByApplicationNameSpy = spyOn(service, 'getClientIdByApplicationName').and.returnValue(of('mock-client-id')); - checkGroupHasClientRoleMappingSpy = spyOn(service, 'checkGroupHasClientRoleMapping').and.returnValue(of(true)); + checkGroupHasAccessSpy = spyOn(service, 'checkGroupHasClientApp').and.returnValue(of(true)); + checkGroupHasGivenRoleSpy = spyOn(service, 'checkGroupHasRole').and.returnValue(of(true)); component.appName = 'mock-app-name'; }); @@ -105,7 +107,7 @@ describe('GroupCloudComponent', () => { it('should show an error message if the group is invalid', async(() => { fixture.detectChanges(); - checkGroupHasClientRoleMappingSpy.and.returnValue(of(false)); + checkGroupHasAccessSpy.and.returnValue(of(false)); findGroupsByNameSpy.and.returnValue(of([])); fixture.detectChanges(); const inputHTMLElement: HTMLInputElement = element.querySelector('input'); @@ -212,7 +214,7 @@ describe('GroupCloudComponent', () => { })); it('should not list groups who do not have access to the app when appName is specified', async(() => { - checkGroupHasClientRoleMappingSpy.and.returnValue(of(false)); + checkGroupHasAccessSpy.and.returnValue(of(false)); component.appName = 'sample-app'; fixture.detectChanges(); @@ -228,9 +230,43 @@ describe('GroupCloudComponent', () => { }); })); + it('should filter groups when roles are specified', async(() => { + checkGroupHasGivenRoleSpy.and.returnValue(of(true)); + component.roles = ['mock-role-1', 'mock-role-2']; + fixture.detectChanges(); + let inputHTMLElement: HTMLInputElement = element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + const groupsList = fixture.debugElement.queryAll(By.css('mat-option')); + expect(groupsList.length).toBe(mockGroups.length); + expect(checkGroupHasGivenRoleSpy).toHaveBeenCalled(); + }); + })); + + it('should return groups when roles are not specified', async(() => { + checkGroupHasGivenRoleSpy.and.returnValue(of(false)); + component.roles = []; + fixture.detectChanges(); + let inputHTMLElement: HTMLInputElement = element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + const groupsList = fixture.debugElement.queryAll(By.css('mat-option')); + expect(groupsList.length).toBe(mockGroups.length); + expect(checkGroupHasGivenRoleSpy).not.toHaveBeenCalled(); + }); + })); + it('should validate access to the app when appName is specified', async(() => { findGroupsByNameSpy.and.returnValue(of(mockGroups)); - checkGroupHasClientRoleMappingSpy.and.returnValue(of(true)); + checkGroupHasAccessSpy.and.returnValue(of(true)); fixture.detectChanges(); let inputHTMLElement: HTMLInputElement = element.querySelector('input'); inputHTMLElement.focus(); @@ -239,7 +275,7 @@ describe('GroupCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(checkGroupHasClientRoleMappingSpy).toHaveBeenCalledTimes(mockGroups.length); + expect(checkGroupHasAccessSpy).toHaveBeenCalledTimes(mockGroups.length); }); })); @@ -252,7 +288,7 @@ describe('GroupCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(checkGroupHasClientRoleMappingSpy).not.toHaveBeenCalled(); + expect(checkGroupHasAccessSpy).not.toHaveBeenCalled(); }); })); }); diff --git a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts index 2f60b26794..b88b9dd007 100644 --- a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts @@ -22,7 +22,7 @@ import { Observable, of, BehaviorSubject } from 'rxjs'; import { GroupModel, GroupSearchParam } from '../models/group.model'; import { GroupCloudService } from '../services/group-cloud.service'; import { debounceTime } from 'rxjs/internal/operators/debounceTime'; -import { distinctUntilChanged, switchMap, flatMap, mergeMap, filter, tap } from 'rxjs/operators'; +import { distinctUntilChanged, switchMap, mergeMap, filter, tap } from 'rxjs/operators'; @Component({ selector: 'adf-cloud-group', @@ -44,12 +44,14 @@ export class GroupCloudComponent implements OnInit { static MODE_SINGLE = 'single'; static MODE_MULTIPLE = 'multiple'; - @ViewChild('groupInput') groupInput: ElementRef; - /** Name of the application. If specified this shows the users who have access to the app. */ @Input() appName: string; + /** Title of the field */ + @Input() + title: string; + /** User selection mode (single/multiple). */ @Input() mode: string = GroupCloudComponent.MODE_SINGLE; @@ -58,6 +60,10 @@ export class GroupCloudComponent implements OnInit { @Input() preSelectGroups: GroupModel[] = []; + /** Role names of the groups to be listed. */ + @Input() + roles: string[] = []; + /** Emitted when a group is selected. */ @Output() selectGroup: EventEmitter = new EventEmitter(); @@ -66,6 +72,9 @@ export class GroupCloudComponent implements OnInit { @Output() removeGroup: EventEmitter = new EventEmitter(); + @ViewChild('groupInput') + private groupInput: ElementRef; + private selectedGroups: GroupModel[] = []; private searchGroups: GroupModel[] = []; @@ -86,6 +95,10 @@ export class GroupCloudComponent implements OnInit { searchedValue = ''; + isFocused: boolean; + + isDisabled: boolean; + constructor(private groupService: GroupCloudService) { this.selectedGroupsSubject = new BehaviorSubject(this.selectedGroups); this.searchGroupsSubject = new BehaviorSubject(this.searchGroups); @@ -94,7 +107,10 @@ export class GroupCloudComponent implements OnInit { } ngOnInit() { - this.loadPreSelectGroups(); + if (this.hasPreSelectGroups()) { + this.loadPreSelectGroups(); + } + this.initSearch(); if (this.appName) { @@ -112,6 +128,17 @@ export class GroupCloudComponent implements OnInit { initSearch() { this.searchGroupsControl.valueChanges.pipe( + filter((value) => { + return typeof value === 'string'; + }), + tap((value) => { + this.searchedValue = value; + if (value) { + this.setError(); + } else { + this.clearError(); + } + }), debounceTime(500), distinctUntilChanged(), tap(() => { @@ -119,75 +146,68 @@ export class GroupCloudComponent implements OnInit { }), switchMap((inputValue) => { const queryParams = this.createSearchParam(inputValue); - return this.findGroupsByName(queryParams); + return this.groupService.findGroupsByName(queryParams); + }), + mergeMap((groups) => { + return groups; }), filter((group: any) => { return !this.isGroupAlreadySelected(group); }), mergeMap((group: any) => { - if (this.clientId) { - return this.checkGroupHasClientRoleMapping(group); + if (this.appName) { + return this.checkGroupHasAccess(group.id).pipe( + mergeMap((hasRole) => { + return hasRole ? of(group) : of(); + }) + ); + } else if (this.hasRoles()) { + return this.filterGroupsByRoles(group); } else { return of(group); } }) ).subscribe((searchedGroup) => { this.searchGroups.push(searchedGroup); - this.clearError(); this.searchGroupsSubject.next(this.searchGroups); }); } - findGroupsByName(searchParam: GroupSearchParam): Observable { - return this.groupService.findGroupsByName(searchParam).pipe( - flatMap((groups: GroupModel[]) => { - this.searchedValue = searchParam.name; - if (this.searchedValue && !this.hasGroups(groups)) { - this.setError(); - } - return groups; - }) - ); - } - - checkGroupHasClientRoleMapping(group: GroupModel): Observable { - return this.groupService.checkGroupHasClientRoleMapping(group.id, this.clientId).pipe( - mergeMap((hasRole: boolean) => { - if (hasRole) { - return of(group); - } else { - this.setError(); - return of(); - } - }) - ); + checkGroupHasAccess(groupId: string): Observable { + if (this.hasRoles()) { + return this.groupService.checkGroupHasAnyClientAppRole(groupId, this.clientId, this.roles); + } else { + return this.groupService.checkGroupHasClientApp(groupId, this.clientId); + } } isGroupAlreadySelected(group: GroupModel): boolean { - if (this.hasGroups(this.selectedGroups)) { - const result = this.selectedGroups.filter((selectedGroup: GroupModel) => { - return selectedGroup.id === group.id; - }); - if (this.hasGroups(result)) { - return true; - } - } - return false; + const result = this.selectedGroups.find((selectedGroup: GroupModel) => { + return selectedGroup.id === group.id; + }); + + return !!result; } private loadPreSelectGroups() { - if (this.hasGroups(this.preSelectGroups)) { - if (this.isMultipleMode()) { - this.preSelectGroups.forEach((group: GroupModel) => { - this.selectedGroups.push(group); - }); - } else { - this.searchGroupsControl.setValue(this.preSelectGroups[0]); - this.onSelect(this.preSelectGroups[0]); - } + if (this.isMultipleMode()) { + this.preSelectGroups.forEach((group: GroupModel) => { + this.selectedGroups.push(group); + }); + } else { + this.searchGroupsControl.setValue(this.preSelectGroups[0]); + this.onSelect(this.preSelectGroups[0]); } } + filterGroupsByRoles(group: GroupModel): Observable { + return this.groupService.checkGroupHasRole(group.id, this.roles).pipe( + mergeMap((hasRole) => { + return hasRole ? of(group) : of(); + }) + ); + } + onSelect(selectedGroup: GroupModel) { if (this.isMultipleMode()) { if (!this.isGroupAlreadySelected(selectedGroup)) { @@ -226,42 +246,31 @@ export class GroupCloudComponent implements OnInit { return group ? group.name : ''; } - private hasGroups(groups: GroupModel[]): boolean { - return groups && groups.length > 0; + private hasPreSelectGroups(): boolean { + return this.preSelectGroups && this.preSelectGroups.length > 0; } - createSearchParam(value: any): GroupSearchParam { - let queryParams: GroupSearchParam = { name: '' }; - if (this.isString(value)) { - queryParams.name = value.trim(); - } else { - queryParams.name = value.name.trim(); - } + private createSearchParam(value: string): GroupSearchParam { + const queryParams: GroupSearchParam = { name: value }; return queryParams; } - isString(value: any): boolean { - return typeof value === 'string'; - } - - setValidationError() { - if (this.hasGroups(this.searchGroups)) { - this.clearError(); - } else { - this.setError(); - } + private hasRoles(): boolean { + return this.roles && this.roles.length > 0; } private disableSearch() { this.searchGroupsControl.disable(); + this.isDisabled = true; } private enableSearch() { this.searchGroupsControl.enable(); + this.isDisabled = false; } private setError() { - this.searchGroupsControl.setErrors({invalid: true}); + this.searchGroupsControl.setErrors({ invalid: true }); } private clearError() { @@ -271,4 +280,12 @@ export class GroupCloudComponent implements OnInit { hasError(): boolean { return this.searchGroupsControl && this.searchGroupsControl.errors && this.searchGroupsControl.errors.invalid; } + + setFocus(isFocused: boolean) { + this.isFocused = isFocused; + } + + hasErrorMessage(): boolean { + return !this.isFocused && this.hasError(); + } } diff --git a/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts b/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts index 32813c8439..f41acdce1e 100644 --- a/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts @@ -102,3 +102,9 @@ export let applicationDetailsMockApi = { } } }; + +export let mockGroup = new GroupModel({ + id: 'mock-id', name: 'Mock Group', path: '/mock', realmRoles: ['MOCK-ADMIN-ROLE', 'MOCK-USER-ROLE', 'MOCK-ROLE-1'] +}); + +export let clientRoles = [ 'MOCK-ADMIN-ROLE', 'MOCK-USER-ROLE']; diff --git a/lib/process-services-cloud/src/lib/group/services/group-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/group/services/group-cloud.service.spec.ts index 35f07c725d..f0310b2034 100644 --- a/lib/process-services-cloud/src/lib/group/services/group-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/group/services/group-cloud.service.spec.ts @@ -33,9 +33,13 @@ import { mockApiError, mockError, roleMappingApi, - noRoleMappingApi + noRoleMappingApi, + mockGroup, + clientRoles } from '../mock/group-cloud.mock'; -import { GroupSearchParam } from '../models/group.model'; +import { GroupSearchParam, GroupModel } from '../models/group.model'; +import { HttpErrorResponse } from '@angular/common/http'; +import { throwError, of } from 'rxjs'; describe('GroupCloudService', () => { let service: GroupCloudService; @@ -73,7 +77,7 @@ describe('GroupCloudService', () => { it('should return true if group has client role mapping', (done) => { spyOn(apiService, 'getInstance').and.returnValue(roleMappingApi); - service.checkGroupHasClientRoleMapping('mock-group-id', 'mock-app-id').subscribe((hasRole) => { + service.checkGroupHasClientApp('mock-group-id', 'mock-app-id').subscribe((hasRole) => { expect(hasRole).toBeDefined(); expect(hasRole).toBe(true); done(); @@ -82,13 +86,147 @@ describe('GroupCloudService', () => { it('should return false if group does not have client role mapping', (done) => { spyOn(apiService, 'getInstance').and.returnValue(noRoleMappingApi); - service.checkGroupHasClientRoleMapping('mock-group-id', 'mock-app-id').subscribe((hasRole) => { + service.checkGroupHasClientApp('mock-group-id', 'mock-app-id').subscribe((hasRole) => { expect(hasRole).toBeDefined(); expect(hasRole).toBe(false); done(); }); }); + it('should fetch group by userId', (done) => { + spyOn(service, 'getGroupDetailsById').and.returnValue(of(mockGroup)); + service.getGroupDetailsById('mock-group-id').subscribe( + (res: GroupModel) => { + expect(res).toBeDefined(); + expect(res.name).toEqual('Mock Group'); + expect(res.realmRoles).toEqual(mockGroup.realmRoles); + done(); + } + ); + }); + + it('Should not fetch group if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'getGroupDetailsById').and.returnValue(throwError(errorResponse)); + + service.getGroupDetailsById('mock-group-id') + .subscribe( + () => { + fail('expected an error, not group'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should return true if group has given role', (done) => { + spyOn(service, 'getGroupDetailsById').and.returnValue(of(mockGroup)); + service.checkGroupHasRole('mock-group-id', ['MOCK-ADMIN-ROLE']).subscribe( + (res: boolean) => { + expect(res).toBeDefined(); + expect(res).toBeTruthy(); + done(); + } + ); + }); + + it('should return false if group does not have given role', (done) => { + spyOn(service, 'getGroupDetailsById').and.returnValue(of(mockGroup)); + service.checkGroupHasRole('mock-group-id', ['MOCK-ADMIN-MODELER']).subscribe( + (res: boolean) => { + expect(res).toBeDefined(); + expect(res).toBeFalsy(); + done(); + } + ); + }); + + it('should fetch client roles by groupId and clientId', (done) => { + spyOn(service, 'getClientRoles').and.returnValue(of(clientRoles)); + service.getClientRoles('mock-group-id', 'mock-client-id').subscribe( + (res: any) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(2); + expect(res).toEqual(clientRoles); + done(); + } + ); + }); + + it('Should not fetch client roles if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'getClientRoles').and.returnValue(throwError(errorResponse)); + + service.getClientRoles('mock-group-id', 'mock-client-id') + .subscribe( + () => { + fail('expected an error, not client roles'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should return true if group has client access', (done) => { + spyOn(service, 'getClientRoles').and.returnValue(of(clientRoles)); + service.checkGroupHasClientApp('mock-group-id', 'mock-client-id').subscribe( + (res: boolean) => { + expect(res).toBeDefined(); + expect(res).toBeTruthy(); + done(); + } + ); + }); + + it('should return false if group does not have client access', (done) => { + spyOn(service, 'getClientRoles').and.returnValue(of([])); + service.checkGroupHasClientApp('mock-group-id', 'mock-client-id').subscribe( + (res: boolean) => { + expect(res).toBeDefined(); + expect(res).toBeFalsy(); + done(); + } + ); + }); + + it('should return true if group has any client role', (done) => { + spyOn(service, 'checkGroupHasAnyClientAppRole').and.returnValue(of(true)); + service.checkGroupHasAnyClientAppRole('mock-group-id', 'mock-client-id', ['MOCK-USER-ROLE']).subscribe( + (res: boolean) => { + expect(res).toBeDefined(); + expect(res).toBeTruthy(); + done(); + } + ); + }); + + it('should return false if group does not have any client role', (done) => { + spyOn(service, 'getClientRoles').and.returnValue(of([])); + service.checkGroupHasAnyClientAppRole('mock-group-id', 'mock-client-id', ['MOCK-ADMIN-MODELER']).subscribe( + (res: boolean) => { + expect(res).toBeDefined(); + expect(res).toBeFalsy(); + done(); + } + ); + }); + it('should append to the call all the parameters', (done) => { spyOn(apiService, 'getInstance').and.returnValue(returnCallQueryParameters); service.findGroupsByName( {name: 'mock'}).subscribe((res) => { diff --git a/lib/process-services-cloud/src/lib/group/services/group-cloud.service.ts b/lib/process-services-cloud/src/lib/group/services/group-cloud.service.ts index 16c3c41443..28b37c44be 100644 --- a/lib/process-services-cloud/src/lib/group/services/group-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/group/services/group-cloud.service.ts @@ -20,7 +20,7 @@ import { from, of, Observable, throwError } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; -import { GroupSearchParam } from '../models/group.model'; +import { GroupSearchParam, GroupModel } from '../models/group.model'; @Injectable({ providedIn: 'root' @@ -50,6 +50,40 @@ export class GroupCloudService { ); } + getGroupDetailsById(groupId: string) { + const url = this.getGroupsApi() + '/' + 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)) + ); + } + + checkGroupHasRole(groupId: string, roleNames: string[]): Observable { + return this.getGroupDetailsById(groupId).pipe(map((response: GroupModel) => { + let availableGroupRoles = []; + let hasRole = false; + availableGroupRoles = response.realmRoles; + if (availableGroupRoles && availableGroupRoles.length > 0) { + roleNames.forEach((roleName: string) => { + const role = availableGroupRoles.find((availableRole) => { + return roleName === availableRole; + }); + if (role) { + hasRole = true; + return; + } + }); + } + return hasRole; + })); + } + getClientIdByApplicationName(applicationName: string): Observable { const url = this.getApplicationIdApi(); const httpMethod = 'GET', pathParams = {}, queryParams = {clientId: applicationName}, bodyParam = {}, headerParams = {}, formParams = {}, @@ -67,7 +101,7 @@ export class GroupCloudService { ); } - checkGroupHasClientRoleMapping(groupId: string, clientId: string): Observable { + getClientRoles(groupId: string, clientId: string): Observable { const url = this.groupClientRoleMappingApi(groupId, clientId); const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; @@ -76,7 +110,11 @@ export class GroupCloudService { url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) - ).pipe( + ); + } + + checkGroupHasClientApp(groupId: string, clientId: string): Observable { + return this.getClientRoles(groupId, clientId).pipe( map((response: any[]) => { if (response && response.length > 0) { return true; @@ -87,6 +125,28 @@ export class GroupCloudService { ); } + checkGroupHasAnyClientAppRole(groupId: string, clientId: string, roleNames: string[]): Observable { + 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}`; } diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 8ae6c89d46..5c1c3f4269 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -49,6 +49,7 @@ "DESCRIPTION": "Description", "ATTACHFORM": "Attach Form", "ASSIGNEE": "Assignee", + "CANDIDATE_GROUP": "Candidate Group", "FORM": "Form", "DATE": "Choose Date" }, diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html index 37be315b66..f857c8df87 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html @@ -60,11 +60,20 @@
- +
-
- +
+
@@ -80,7 +89,7 @@