From 8d2229cf9986d7004a460fa32f3b418d0ff026d7 Mon Sep 17 00:00:00 2001 From: siva kumar Date: Mon, 15 Jul 2019 23:58:07 +0530 Subject: [PATCH] [ADF-4731] [Process - Cloud] - Improve IdentityUserService (#4924) * [ADF-4731][Process - Cloud] - Improve IdentityUserService. * * Updated unit tests. * * Updated IdentityUserService document * Fixed comments on the pr. * * Added missing 'createdTimestamp' property to the IdentityUserModel. * * Created IdentityJoinGroupRequestModel. * Updated doc. * Updated unit tests. --- docs/core/services/identity-user.service.md | 149 +++++- lib/core/mock/identity-user.service.mock.ts | 180 +++++++ .../userinfo/models/identity-group.model.ts | 38 ++ .../userinfo/models/identity-role.model.ts | 11 +- .../userinfo/models/identity-user.model.ts | 57 +++ lib/core/userinfo/public-api.ts | 1 + .../services/identity-user.service.spec.ts | 472 +++++++++++++++++- .../services/identity-user.service.ts | 319 +++++++++++- .../src/lib/services/identity-user.service.ts | 60 --- .../src/lib/services/public-api.ts | 1 - 10 files changed, 1179 insertions(+), 109 deletions(-) create mode 100644 lib/core/mock/identity-user.service.mock.ts create mode 100644 lib/core/userinfo/models/identity-group.model.ts delete mode 100644 lib/process-services-cloud/src/lib/services/identity-user.service.ts diff --git a/docs/core/services/identity-user.service.md b/docs/core/services/identity-user.service.md index e77b6392fd..6ae1fbce41 100644 --- a/docs/core/services/identity-user.service.md +++ b/docs/core/services/identity-user.service.md @@ -2,30 +2,147 @@ Title: Identity user service Added: v3.0.0 Status: Active -Last reviewed: 2019-02-08 +Last reviewed: 2019-07-12 --- -# [Identity user service](../../../lib/process-services-cloud/src/lib/services/identity-user.service.ts "Defined in identity-user.service.ts") +# [Identity user service](../../../lib/core/userinfo/services/identity-user.service.ts "Defined in identity-user.service.ts") -Gets OAuth2 personal details and roles for users. +Gets OAuth2 personal details and roles for users and performs CRUD operations on identity users. ## Class members ### Methods -- **findUsersByUsername**(username: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
- Finds groups filtered by username. - - _username:_ `string` - Object containing the name filter string - - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users information - -## Details - -[OAuth2](https://oauth.net/2/) defines an _access token_ (used when -authenticating a user) and a number of _authentication roles_ that the user -can participate in (see -[this page](https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2) -for an introduction to OAuth2 and a description of the roles). You can use the -[Identity user service](identity-user.service.md) to access this information for users, including the current user. +- **assignRoles**(userId: `string`, roles: [`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Assigns roles to the user. + - _userId:_ `string` - Id of the user. + - _roles:_ [`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]` - Array of roles. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the role assigned. +- **changePassword**(userId: `string`, newPassword: [`IdentityUserPasswordModel`](../../../lib/core/userinfo/models/identity-user.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Changes user password. + - _userId:_ `string` - Id of the user. + - _newPassword:_ [`IdentityUserPasswordModel`](../../../lib/core/userinfo/models/identity-user.model.ts) - + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the password changed. +- **checkUserHasAnyApplicationRole**(userId: `string`, applicationName: `string`, roleNames: `string[]`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Checks if a user has any application role. + - _userId:_ `string` - ID of the target user + - _applicationName:_ `string` - Name of the application + - _roleNames:_ `string[]` - List of role names to check for + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - True if the user has one or more of the roles, false otherwise +- **checkUserHasAnyClientAppRole**(userId: `string`, clientId: `string`, roleNames: `string[]`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Checks whether a user has any of the client app roles. + - _userId:_ `string` - ID of the target user + - _clientId:_ `string` - ID of the client app + - _roleNames:_ `string[]` - List of role names to check for + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - True if the user has one or more of the roles, false otherwise +- **checkUserHasApplicationAccess**(userId: `string`, applicationName: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Checks if a user has access to an application. + - _userId:_ `string` - ID of the user + - _applicationName:_ `string` - Name of the application + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - True if the user has access, false otherwise +- **checkUserHasClientApp**(userId: `string`, clientId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Checks whether user has access to a client app. + - _userId:_ `string` - ID of the target user + - _clientId:_ `string` - ID of the client app + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - True if the user has access, false otherwise +- **checkUserHasRole**(userId: `string`, roleNames: `string[]`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Checks if a user has one of the roles from a list. + - _userId:_ `string` - ID of the target user + - _roleNames:_ `string[]` - Array of roles to check for + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - True if the user has one of the roles, false otherwise +- **createUser**(newUser: [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Creates new user. + - _newUser:_ [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts) - Object containing the new user details. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the user created. +- **deleteUser**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Deletes User. + - _userId:_ `string` - Id of the user. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the user deleted. +- **findUserByEmail**(email: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on email input. + - _email:_ `string` - Search query string + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users +- **findUserById**(id: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on id input. + - _id:_ `string` - Search query string + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - users object +- **findUserByUsername**(username: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on username input. + - _username:_ `string` - Search query string + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users +- **findUsersByName**(search: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on search input. + - _search:_ `string` - Search query string + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users +- **getAssignedRoles**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>`
+ Gets assigned roles. + - _userId:_ `string` - Id of the user. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - Array of assigned roles information objects +- **getAvailableRoles**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>`
+ Gets available roles + - _userId:_ `string` - Id of the user. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - Array of available roles information objects +- **getClientIdByApplicationName**(applicationName: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Gets the client ID for an application. + - _applicationName:_ `string` - Name of the application + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Client ID string +- **getClientRoles**(userId: `string`, clientId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Get client roles of a user for a particular client. + - _userId:_ `string` - ID of the target user + - _clientId:_ `string` - ID of the client app + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of client roles +- **getCurrentUserInfo**(): [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)
+ Gets the name and other basic details of the current user. + - **Returns** [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts) - The user's details +- **getEffectiveRoles**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>`
+ Gets effective roles. + - _userId:_ `string` - Id of the user. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - Array of composite roles information objects +- **getInvolvedGroups**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`[]>`
+ Gets involved groups. + - _userId:_ `string` - Id of the user. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityGroupModel`](../../../lib/core/userinfo/models/identity-group.model.ts)`[]>` - Array of involved groups information objects. +- **getTotalUsersCount**(): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Gets users total count. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Number of users count. +- **getUserRoles**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>`
+ Gets a list of roles for a user. + - _userId:_ `string` - ID of the user + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - Array of role info objects +- **getUsers**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]>`
+ Gets details for all users. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]>` - Array of user info objects +- **getUsersByRolesWithCurrentUser**(roleNames: `string[]`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]>`
+ Gets an array of users (including the current user) who have any of the roles in the supplied list. + - _roleNames:_ `string[]` - List of role names to look for + - **Returns** [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]>` - Array of user info objects +- **getUsersByRolesWithoutCurrentUser**(roleNames: `string[]`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]>`
+ Gets an array of users (not including the current user) who have any of the roles in the supplied list. + - _roleNames:_ `string[]` - List of role names to look for + - **Returns** [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]>` - Array of user info objects +- **joinGroup**(joinGroupRequest: [`IdentityJoinGroupRequestModel`](../../../lib/core/userinfo/models/identity-user.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Joins group. + - _joinGroupRequest:_ [`IdentityJoinGroupRequestModel`](../../../lib/core/userinfo/models/identity-user.model.ts) - Details of join group request (IdentityJoinGroupRequestModel). + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the user joined the group. +- **leaveGroup**(userId: `any`, groupId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Leaves group. + - _userId:_ `any` - Id of the user. + - _groupId:_ `string` - Id of the group. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the user left the group. +- **queryUsers**(requestQuery: [`IdentityUserQueryCloudRequestModel`](../../../lib/core/userinfo/models/identity-user.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserQueryResponse`](../../../lib/core/userinfo/models/identity-user.model.ts)`>`
+ Gets details for all users. + - _requestQuery:_ [`IdentityUserQueryCloudRequestModel`](../../../lib/core/userinfo/models/identity-user.model.ts) - + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserQueryResponse`](../../../lib/core/userinfo/models/identity-user.model.ts)`>` - Array of user information objects. +- **removeRoles**(userId: `string`, removedRoles: [`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Removes assigned roles. + - _userId:_ `string` - Id of the user. + - _removedRoles:_ [`IdentityRoleModel`](../../../lib/core/userinfo/models/identity-role.model.ts)`[]` - + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the role removed. +- **updateUser**(userId: `string`, updatedUser: [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Updates user details. + - _userId:_ `string` - Id of the user. + - _updatedUser:_ [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts) - Object containing the user details. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - Empty response when the user updated. ## See also diff --git a/lib/core/mock/identity-user.service.mock.ts b/lib/core/mock/identity-user.service.mock.ts new file mode 100644 index 0000000000..6a40719bcc --- /dev/null +++ b/lib/core/mock/identity-user.service.mock.ts @@ -0,0 +1,180 @@ +/*! + * @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 { IdentityUserModel, IdentityJoinGroupRequestModel } from './../userinfo/models/identity-user.model'; +import { IdentityRoleModel } from './../userinfo/models/identity-role.model'; +import { IdentityGroupModel } from './../userinfo/models/identity-group.model'; + +export let mockIdentityUser1 = new IdentityUserModel( + { id: 'mock-user-id-1', username: 'userName1', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' } +); + +export let mockIdentityUser2 = new IdentityUserModel( + { id: 'mock-user-id-2', username: 'userName2', firstName: 'first-name-2', lastName: 'last-name-2', email: 'abcd@xyz.com'} +); + +export let mockIdentityUser3 = new IdentityUserModel( + { id: 'mock-user-id-3', username: 'userName3', firstName: 'first-name-3', lastName: 'last-name-3', email: 'abcde@xyz.com' } +); + +export let mockIdentityUser4 = new IdentityUserModel( + { id: 'mock-user-id-4', username: 'userName4', firstName: 'first-name-4', lastName: 'last-name-4', email: 'abcde@xyz.com' } +); + +export let mockIdentityUser5 = new IdentityUserModel( + { id: 'mock-user-id-5', username: 'userName5', firstName: 'first-name-5', lastName: 'last-name-5', email: 'abcde@xyz.com' } +); + +export let mockIdentityUsers = [ + mockIdentityUser1, + mockIdentityUser2, + mockIdentityUser3, + mockIdentityUser4, + mockIdentityUser5 +]; + +export let mockIdentityRole = new IdentityRoleModel({ id: 'id-1', name: 'MOCK-ADMIN-ROLE'}); + +export let mockAvailableRoles = [ + new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ADMIN-ROLE'}), + new IdentityRoleModel({ id: 'mock-role-id-2', name: 'MOCK-USER-ROLE'}), + new IdentityRoleModel({ id: 'mock-role-id-3', name: 'MOCK_MODELER-ROLE' }), + new IdentityRoleModel({ id: 'mock-role-id-5', name: 'MOCK-ROLE-2'}) +]; + +export let mockAssignedRoles = [ + new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ADMIN-ROLE'}), + new IdentityRoleModel({ id: 'mock-role-id-2', name: 'MOCK_MODELER-ROLE' }), + new IdentityRoleModel({ id: 'mock-role-id-3', name: 'MOCK-ROLE-1' }) +]; + +export let mockEffectiveRoles = [ + new IdentityRoleModel({id: 'mock-role-id-1', name: 'MOCK-ACTIVE-ADMIN-ROLE'}), + new IdentityRoleModel({id: 'mock-role-id-2', name: 'MOCK-ACTIVE-USER-ROLE'}), + new IdentityRoleModel({id: 'mock-role-id-3', name: 'MOCK-ROLE-1'}) +]; + +export let mockJoinGroupRequest = new IdentityJoinGroupRequestModel({userId: 'mock-hser-id', groupId: 'mock-group-id', realm: 'mock-realm-name'}); + +export let mockGroup1 = new IdentityGroupModel({ + id: 'mock-group-id-1', name: 'Mock Group 1', path: '/mock', subGroups: [] +}); + +export let mockGroup2 = new IdentityGroupModel({ + id: 'mock-group-id-2', name: 'Mock Group 2', path: '', subGroups: [] +}); + +export let mockGroups = [ + new IdentityGroupModel({ id: 'mock-group-id-1', name: 'Mock Group 1', path: '/mock', subGroups: [] }), + new IdentityGroupModel({ id: 'mock-group-id-2', name: 'Mock Group 2', path: '', subGroups: [] }) +]; + +export let queryUsersMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(mockIdentityUsers); + } + } +}; + +export let createUserMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; + +export let updateUserMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; + +export let deleteUserMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; + +export let getInvolvedGroupsMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(mockGroups); + } + } +}; + +export let joinGroupMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; + +export let leaveGroupMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; + +export let getAvailableRolesMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(mockAvailableRoles); + } + } +}; + +export let getAssignedRolesMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(mockAssignedRoles); + } + } +}; + +export let getEffectiveRolesMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(mockEffectiveRoles); + } + } +}; + +export let assignRolesMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; + +export let removeRolesMockApi = { + oauth2Auth: { + callCustomApi: () => { + return Promise.resolve(); + } + } +}; diff --git a/lib/core/userinfo/models/identity-group.model.ts b/lib/core/userinfo/models/identity-group.model.ts new file mode 100644 index 0000000000..bffe11335a --- /dev/null +++ b/lib/core/userinfo/models/identity-group.model.ts @@ -0,0 +1,38 @@ +/*! + * @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 IdentityGroupModel { + + id: string; + name: string; + path: string; + realmRoles: string[]; + clientRoles: any; + access: any; + attributes: any; + + constructor(obj?: any) { + if (obj) { + this.id = obj.id || null; + this.name = obj.name || null; + this.path = obj.path || null; + this.realmRoles = obj.realmRoles || null; + this.clientRoles = obj.clientRoles || null; + this.access = obj.access || null; + this.attributes = obj.attributes || null; + } + } +} diff --git a/lib/core/userinfo/models/identity-role.model.ts b/lib/core/userinfo/models/identity-role.model.ts index 1c2ac977eb..667d5fc8f2 100644 --- a/lib/core/userinfo/models/identity-role.model.ts +++ b/lib/core/userinfo/models/identity-role.model.ts @@ -15,14 +15,23 @@ * limitations under the License. */ export class IdentityRoleModel { - id: string; name: string; + description?: string; + clientRole?: boolean; + composite?: boolean; + containerId?: string; + scopeParamRequired?: boolean; constructor(obj?: any) { if (obj) { this.id = obj.id || null; this.name = obj.name || null; + this.description = obj.description || null; + this.clientRole = obj.clientRole || null; + this.composite = obj.composite || null; + this.containerId = obj.containerId || null; + this.scopeParamRequired = obj.scopeParamRequired || null; } } } diff --git a/lib/core/userinfo/models/identity-user.model.ts b/lib/core/userinfo/models/identity-user.model.ts index 16285413bd..9c3285ed6d 100644 --- a/lib/core/userinfo/models/identity-user.model.ts +++ b/lib/core/userinfo/models/identity-user.model.ts @@ -15,12 +15,17 @@ * limitations under the License. */ +import { Pagination } from '@alfresco/js-api'; + export class IdentityUserModel { id: string; firstName: string; lastName: string; email: string; username: string; + createdTimestamp?: any; + emailVerified?: boolean; + enabled?: boolean; constructor(obj?: any) { if (obj) { @@ -29,6 +34,58 @@ export class IdentityUserModel { this.lastName = obj.lastName || null; this.email = obj.email || null; this.username = obj.username || null; + this.createdTimestamp = obj.createdTimestamp || null; + this.emailVerified = obj.emailVerified || null; + this.enabled = obj.enabled || null; + } + } +} + +export class IdentityUserPasswordModel { + + type: string; + value: string; + temporary: boolean; + + constructor(obj?: any) { + if (obj) { + this.type = obj.type; + this.value = obj.value; + this.temporary = obj.temporary; + } + } +} + +export interface IdentityUserQueryResponse { + + entries: IdentityUserModel[]; + pagination: Pagination; +} + +export class IdentityUserQueryCloudRequestModel { + + first: number; + max: number; + + constructor(obj?: any) { + if (obj) { + this.first = obj.first; + this.max = obj.max; + } + } +} + +export class IdentityJoinGroupRequestModel { + + realm: string; + userId: string; + groupId: string; + + constructor(obj?: any) { + if (obj) { + this.realm = obj.realm; + this.userId = obj.userId; + this.groupId = obj.groupId; } } } diff --git a/lib/core/userinfo/public-api.ts b/lib/core/userinfo/public-api.ts index 9f0f2ebac9..708508f84f 100644 --- a/lib/core/userinfo/public-api.ts +++ b/lib/core/userinfo/public-api.ts @@ -23,5 +23,6 @@ export * from './models/bpm-user.model'; export * from './models/ecm-user.model'; export * from './models/identity-user.model'; export * from './models/identity-role.model'; +export * from './models/identity-group.model'; export * from './userinfo.module'; diff --git a/lib/core/userinfo/services/identity-user.service.spec.ts b/lib/core/userinfo/services/identity-user.service.spec.ts index 545ac498b2..48263a895e 100644 --- a/lib/core/userinfo/services/identity-user.service.spec.ts +++ b/lib/core/userinfo/services/identity-user.service.spec.ts @@ -18,21 +18,36 @@ import { TestBed } from '@angular/core/testing'; import { HttpErrorResponse } from '@angular/common/http'; import { throwError, of } from 'rxjs'; +import { + queryUsersMockApi, + createUserMockApi, + mockIdentityUser1, + updateUserMockApi, + mockIdentityUser2, + deleteUserMockApi, + getInvolvedGroupsMockApi, + joinGroupMockApi, + leaveGroupMockApi, + getAvailableRolesMockApi, + getAssignedRolesMockApi, + getEffectiveRolesMockApi, + assignRolesMockApi, + mockIdentityRole, + removeRolesMockApi, + mockIdentityUsers, + mockJoinGroupRequest +} from 'core/mock/identity-user.service.mock'; import { IdentityUserService } from '../services/identity-user.service'; import { setupTestBed } from '../../testing/setupTestBed'; import { CoreModule } from '../../core.module'; +import { AlfrescoApiService } from '../../services/alfresco-api.service'; import { mockToken } from './../../mock/jwt-helper.service.spec'; -import { IdentityUserModel } from '../models/identity-user.model'; +import { IdentityUserModel, IdentityUserQueryCloudRequestModel } from '../models/identity-user.model'; import { IdentityRoleModel } from '../models/identity-role.model'; +import { AlfrescoApiServiceMock } from '../../mock/alfresco-api.service.mock'; describe('IdentityUserService', () => { - const mockUsers = [ - { id: 'fake-id-1', username: 'first-name-1 last-name-1', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' }, - { id: 'fake-id-2', username: 'first-name-2 last-name-2', firstName: 'first-name-2', lastName: 'last-name-2', email: 'abcd@xyz.com'}, - { id: 'fake-id-3', username: 'first-name-3 last-name-3', firstName: 'first-name-3', lastName: 'last-name-3', email: 'abcde@xyz.com' } - ]; - const mockRoles = [ { id: 'id-1', name: 'MOCK-ADMIN-ROLE'}, { id: 'id-2', name: 'MOCK-USER-ROLE'}, @@ -42,15 +57,20 @@ describe('IdentityUserService', () => { ]; let service: IdentityUserService; + let alfrescoApiService: AlfrescoApiService; setupTestBed({ imports: [ CoreModule.forRoot() + ], + providers: [ + { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock } ] }); beforeEach(() => { service = TestBed.get(IdentityUserService); + alfrescoApiService = TestBed.get(AlfrescoApiService); }); beforeEach(() => { @@ -75,16 +95,16 @@ describe('IdentityUserService', () => { }); it('should fetch users ', (done) => { - spyOn(service, 'getUsers').and.returnValue(of(mockUsers)); + spyOn(service, 'getUsers').and.returnValue(of(mockIdentityUsers)); service.getUsers().subscribe( (res: IdentityUserModel[]) => { expect(res).toBeDefined(); - expect(res[0].id).toEqual('fake-id-1'); - expect(res[0].username).toEqual('first-name-1 last-name-1'); - expect(res[1].id).toEqual('fake-id-2'); - expect(res[1].username).toEqual('first-name-2 last-name-2'); - expect(res[2].id).toEqual('fake-id-3'); - expect(res[2].username).toEqual('first-name-3 last-name-3'); + expect(res[0].id).toEqual('mock-user-id-1'); + expect(res[0].username).toEqual('userName1'); + expect(res[1].id).toEqual('mock-user-id-2'); + expect(res[1].username).toEqual('userName2'); + expect(res[2].id).toEqual('mock-user-id-3'); + expect(res[2].username).toEqual('userName3'); done(); } ); @@ -147,18 +167,18 @@ describe('IdentityUserService', () => { }); it('should fetch users by roles', (done) => { - spyOn(service, 'getUsers').and.returnValue(of(mockUsers)); + spyOn(service, 'getUsers').and.returnValue(of(mockIdentityUsers)); spyOn(service, 'getUserRoles').and.returnValue(of(mockRoles)); service.getUsersByRolesWithCurrentUser([mockRoles[0].name]).then( (res: IdentityUserModel[]) => { expect(res).toBeDefined(); - expect(res[0].id).toEqual('fake-id-1'); - expect(res[0].username).toEqual('first-name-1 last-name-1'); - expect(res[1].id).toEqual('fake-id-2'); - expect(res[1].username).toEqual('first-name-2 last-name-2'); - expect(res[2].id).toEqual('fake-id-3'); - expect(res[2].username).toEqual('first-name-3 last-name-3'); + expect(res[0].id).toEqual('mock-user-id-1'); + expect(res[0].username).toEqual('userName1'); + expect(res[1].id).toEqual('mock-user-id-2'); + expect(res[1].username).toEqual('userName2'); + expect(res[2].id).toEqual('mock-user-id-3'); + expect(res[2].username).toEqual('userName3'); done(); } ); @@ -184,17 +204,17 @@ describe('IdentityUserService', () => { }); it('should fetch users by roles without current user', (done) => { - spyOn(service, 'getUsers').and.returnValue(of(mockUsers)); + spyOn(service, 'getUsers').and.returnValue(of(mockIdentityUsers)); spyOn(service, 'getUserRoles').and.returnValue(of(mockRoles)); - spyOn(service, 'getCurrentUserInfo').and.returnValue(mockUsers[0]); + spyOn(service, 'getCurrentUserInfo').and.returnValue(mockIdentityUsers[0]); service.getUsersByRolesWithoutCurrentUser([mockRoles[0].name]).then( (res: IdentityUserModel[]) => { expect(res).toBeDefined(); - expect(res[0].id).toEqual('fake-id-2'); - expect(res[0].username).toEqual('first-name-2 last-name-2'); - expect(res[1].id).toEqual('fake-id-3'); - expect(res[1].username).toEqual('first-name-3 last-name-3'); + expect(res[0].id).toEqual('mock-user-id-2'); + expect(res[0].username).toEqual('userName2'); + expect(res[1].id).toEqual('mock-user-id-3'); + expect(res[1].username).toEqual('userName3'); done(); } ); @@ -269,4 +289,402 @@ describe('IdentityUserService', () => { } ); }); + + it('should be able to query users based on query params (first & max params)', (done) => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(queryUsersMockApi); + service.queryUsers(new IdentityUserQueryCloudRequestModel({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-user-id-1'); + expect(res.entries[0].username).toBe('userName1'); + expect(res.entries[1].id).toBe('mock-user-id-2'); + expect(res.entries[1].username).toBe('userName2'); + expect(res.entries[2].id).toBe('mock-user-id-3'); + expect(res.entries[2].username).toBe('userName3'); + done(); + }); + }); + + it('Should not be able to query users if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'queryUsers').and.returnValue(throwError(errorResponse)); + + service.queryUsers(new IdentityUserQueryCloudRequestModel({first: 0, max: 5})) + .subscribe( + () => { + fail('expected an error, not users'); + }, + (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 user', (done) => { + const createCustomApiSpy = spyOn(alfrescoApiService, 'getInstance').and.returnValue(createUserMockApi); + service.createUser(mockIdentityUser1).subscribe((res) => { + expect(createCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to create user if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'createUser').and.returnValue(throwError(errorResponse)); + + service.createUser(mockIdentityUser1) + .subscribe( + () => { + fail('expected an error, not to create user'); + }, + (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 user', (done) => { + const updateCustomApiSpy = spyOn(alfrescoApiService, 'getInstance').and.returnValue(updateUserMockApi); + service.updateUser('mock-id-2', mockIdentityUser2).subscribe((res) => { + expect(updateCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to update user if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'updateUser').and.returnValue(throwError(errorResponse)); + + service.updateUser('mock-id-2', mockIdentityUser2) + .subscribe( + () => { + fail('expected an error, not to update user'); + }, + (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(alfrescoApiService, 'getInstance').and.returnValue(deleteUserMockApi); + service.deleteUser('mock-user-id').subscribe((res) => { + expect(deleteCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to delete user if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'deleteUser').and.returnValue(throwError(errorResponse)); + + service.deleteUser('mock-user-id') + .subscribe( + () => { + fail('expected an error, not to delete user'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should be able to fetch involved groups based on user id', (done) => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(getInvolvedGroupsMockApi); + service.getInvolvedGroups('mock-user-id').subscribe((res) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.length).toBe(2); + 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'); + done(); + }); + }); + + it('Should not be able to fetch involved groups if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'getInvolvedGroups').and.returnValue(throwError(errorResponse)); + + service.getInvolvedGroups('mock-user-id') + .subscribe( + () => { + fail('expected an error, not involved 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 join the group', (done) => { + const joinGroupCustomApiSpy = spyOn(alfrescoApiService, 'getInstance').and.returnValue(joinGroupMockApi); + service.joinGroup(mockJoinGroupRequest).subscribe((res) => { + expect(joinGroupCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to join group if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'joinGroup').and.returnValue(throwError(errorResponse)); + + service.joinGroup(mockJoinGroupRequest) + .subscribe( + () => { + fail('expected an error, not to join 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 leave the group', (done) => { + const leaveGroupCustomApiSpy = spyOn(alfrescoApiService, 'getInstance').and.returnValue(leaveGroupMockApi); + service.leaveGroup('mock-user-id', 'mock-group-id').subscribe((res) => { + expect(leaveGroupCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to leave group if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'leaveGroup').and.returnValue(throwError(errorResponse)); + + service.leaveGroup('mock-user-id', 'mock-group-id') + .subscribe( + () => { + fail('expected an error, not to leave 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 fetch available roles based on user id', (done) => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(getAvailableRolesMockApi); + service.getAvailableRoles('mock-user-id').subscribe((res) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.length).toBe(4); + expect(res[0].id).toBe('mock-role-id-1'); + expect(res[0].name).toBe('MOCK-ADMIN-ROLE'); + expect(res[1].id).toBe('mock-role-id-2'); + expect(res[1].name).toBe('MOCK-USER-ROLE'); + expect(res[2].id).toBe('mock-role-id-3'); + expect(res[2].name).toBe('MOCK_MODELER-ROLE'); + done(); + }); + }); + + it('Should not be able to fetch available roles based on user id if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'getAvailableRoles').and.returnValue(throwError(errorResponse)); + + service.getAvailableRoles('mock-user-id') + .subscribe( + () => { + fail('expected an error, not available roles'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should be able to fetch assigned roles based on user id', (done) => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(getAssignedRolesMockApi); + service.getAssignedRoles('mock-user-id').subscribe((res) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.length).toBe(3); + expect(res[0].id).toBe('mock-role-id-1'); + expect(res[0].name).toBe('MOCK-ADMIN-ROLE'); + expect(res[1].id).toBe('mock-role-id-2'); + expect(res[1].name).toBe('MOCK_MODELER-ROLE'); + expect(res[2].id).toBe('mock-role-id-3'); + expect(res[2].name).toBe('MOCK-ROLE-1'); + done(); + }); + }); + + it('Should not be able to fetch assigned roles based on user id if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'getAssignedRoles').and.returnValue(throwError(errorResponse)); + + service.getAssignedRoles('mock-user-id') + .subscribe( + () => { + fail('expected an error, not assigned roles'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should be able to fetch effective roles based on user id', (done) => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(getEffectiveRolesMockApi); + service.getEffectiveRoles('mock-user-id').subscribe((res) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.length).toBe(3); + expect(res[0].id).toBe('mock-role-id-1'); + expect(res[0].name).toBe('MOCK-ACTIVE-ADMIN-ROLE'); + expect(res[1].id).toBe('mock-role-id-2'); + expect(res[1].name).toBe('MOCK-ACTIVE-USER-ROLE'); + expect(res[2].id).toBe('mock-role-id-3'); + expect(res[2].name).toBe('MOCK-ROLE-1'); + done(); + }); + }); + + it('Should not be able to fetch effective roles based on user id if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'getEffectiveRoles').and.returnValue(throwError(errorResponse)); + + service.getEffectiveRoles('mock-user-id') + .subscribe( + () => { + fail('expected an error, not effective roles'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should be able to assign roles to the user', (done) => { + const assignRolesCustomApiSpy = spyOn(alfrescoApiService, 'getInstance').and.returnValue(assignRolesMockApi); + service.assignRoles('mock-user-id', [mockIdentityRole]).subscribe((res) => { + expect(assignRolesCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to assign roles to the user if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'assignRoles').and.returnValue(throwError(errorResponse)); + + service.assignRoles('mock-user-id', [mockIdentityRole]) + .subscribe( + () => { + fail('expected an error, not to assigen roles to the user'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); + + it('should be able to remove roles', (done) => { + const removeRolesCustomApiSpy = spyOn(alfrescoApiService, 'getInstance').and.returnValue(removeRolesMockApi); + service.removeRoles('mock-user-id', [mockIdentityRole]).subscribe((res) => { + expect(removeRolesCustomApiSpy).toHaveBeenCalled(); + done(); + }); + }); + + it('Should not able to remove roles if error occurred', (done) => { + const errorResponse = new HttpErrorResponse({ + error: 'Mock Error', + status: 404, statusText: 'Not Found' + }); + + spyOn(service, 'removeRoles').and.returnValue(throwError(errorResponse)); + + service.removeRoles('mock-user-id', [mockIdentityRole]) + .subscribe( + () => { + fail('expected an error, not to remove roles'); + }, + (error) => { + expect(error.status).toEqual(404); + expect(error.statusText).toEqual('Not Found'); + expect(error.error).toEqual('Mock Error'); + done(); + } + ); + }); }); diff --git a/lib/core/userinfo/services/identity-user.service.ts b/lib/core/userinfo/services/identity-user.service.ts index 5f0f6a31b0..a362219920 100644 --- a/lib/core/userinfo/services/identity-user.service.ts +++ b/lib/core/userinfo/services/identity-user.service.ts @@ -16,14 +16,22 @@ */ import { Injectable } from '@angular/core'; -import { Observable, from, of } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; +import { Observable, of, from, throwError } from 'rxjs'; +import { catchError, map, switchMap } from 'rxjs/operators'; -import { IdentityUserModel } from '../models/identity-user.model'; +import { + IdentityUserModel, + IdentityUserQueryResponse, + IdentityUserQueryCloudRequestModel, + IdentityUserPasswordModel, + IdentityJoinGroupRequestModel +} from '../models/identity-user.model'; import { JwtHelperService } from '../../services/jwt-helper.service'; +import { LogService } from '../../services/log.service'; import { AppConfigService } from '../../app-config/app-config.service'; import { AlfrescoApiService } from '../../services/alfresco-api.service'; import { IdentityRoleModel } from '../models/identity-role.model'; +import { IdentityGroupModel } from '../models/identity-group.model'; @Injectable({ providedIn: 'root' @@ -33,7 +41,8 @@ export class IdentityUserService { constructor( private jwtHelperService: JwtHelperService, private alfrescoApiService: AlfrescoApiService, - private appConfigService: AppConfigService) { } + private appConfigService: AppConfigService, + private logService: LogService) { } /** * Gets the name and other basic details of the current user. @@ -364,6 +373,300 @@ export class IdentityUserService { })); } + /** + * Gets details for all users. + * @returns Array of user information objects. + */ + queryUsers(requestQuery: IdentityUserQueryCloudRequestModel): Observable { + const url = this.buildUserUrl(); + const httpMethod = 'GET', pathParams = {}, + queryParams = { first: requestQuery.first, max: requestQuery.max }, bodyParam = {}, headerParams = {}, + formParams = {}, authNames = [], contentTypes = ['application/json']; + + return this.getTotalUsersCount().pipe( + switchMap((totalCount: any) => + from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( + url, httpMethod, pathParams, queryParams, + headerParams, formParams, bodyParam, authNames, + contentTypes, null, null, null) + ).pipe( + map((response: IdentityUserModel[]) => { + return { + entries: response, + pagination: { + skipCount: requestQuery.first, + maxItems: requestQuery.max, + count: totalCount, + hasMoreItems: false, + totalItems: totalCount + } + }; + }), + catchError((error) => this.handleError(error)) + )) + ); + } + + /** + * Gets users total count. + * @returns Number of users count. + */ + getTotalUsersCount(): Observable { + const url = this.buildUserUrl() + `/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 user. + * @param newUser Object containing the new user details. + * @returns Empty response when the user created. + */ + createUser(newUser: IdentityUserModel): Observable { + const url = this.buildUserUrl(); + const request = JSON.stringify(newUser); + const httpMethod = 'POST', 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)) + ); + } + + /** + * Updates user details. + * @param userId Id of the user. + * @param updatedUser Object containing the user details. + * @returns Empty response when the user updated. + */ + updateUser(userId: string, updatedUser: IdentityUserModel): Observable { + const url = this.buildUserUrl() + '/' + userId; + const request = JSON.stringify(updatedUser); + 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 User. + * @param userId Id of the user. + * @returns Empty response when the user deleted. + */ + deleteUser(userId: string): Observable { + const url = this.buildUserUrl() + '/' + userId; + 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)) + ); + } + + /** + * Changes user password. + * @param userId Id of the user. + * @param credentials Details of user Credentials. + * @returns Empty response when the password changed. + */ + changePassword(userId: string, newPassword: IdentityUserPasswordModel): Observable { + const url = this.buildUserUrl() + '/' + userId + '/reset-password'; + const request = JSON.stringify(newPassword); + 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)) + ); + } + + /** + * Gets involved groups. + * @param userId Id of the user. + * @returns Array of involved groups information objects. + */ + getInvolvedGroups(userId: string): Observable { + const url = this.buildUserUrl() + '/' + userId + '/groups/'; + const httpMethod = 'GET', pathParams = { id: userId}, + 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)) + ); + } + + /** + * Joins group. + * @param joinGroupRequest Details of join group request (IdentityJoinGroupRequestModel). + * @returns Empty response when the user joined the group. + */ + joinGroup(joinGroupRequest: IdentityJoinGroupRequestModel): Observable { + const url = this.buildUserUrl() + '/' + joinGroupRequest.userId + '/groups/' + joinGroupRequest.groupId; + const request = JSON.stringify(joinGroupRequest); + 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)) + ); + } + + /** + * Leaves group. + * @param userId Id of the user. + * @param groupId Id of the group. + * @returns Empty response when the user left the group. + */ + leaveGroup(userId: any, groupId: string): Observable { + const url = this.buildUserUrl() + '/' + userId + '/groups/' + 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)) + ); + } + + /** + * Gets available roles + * @param userId Id of the user. + * @returns Array of available roles information objects + */ + getAvailableRoles(userId: string): Observable { + const url = this.buildUserUrl() + '/' + userId + '/role-mappings/realm/available'; + 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)) + ); + } + + /** + * Gets assigned roles. + * @param userId Id of the user. + * @returns Array of assigned roles information objects + */ + getAssignedRoles(userId: string): Observable { + const url = this.buildUserUrl() + '/' + userId + '/role-mappings/realm'; + const httpMethod = 'GET', pathParams = { id: userId}, + 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)) + ); + } + + /** + * Gets effective roles. + * @param userId Id of the user. + * @returns Array of composite roles information objects + */ + getEffectiveRoles(userId: string): Observable { + const url = this.buildUserUrl() + '/' + userId + '/role-mappings/realm/composite'; + const httpMethod = 'GET', pathParams = { id: userId}, + 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)) + ); + } + + /** + * Assigns roles to the user. + * @param userId Id of the user. + * @param roles Array of roles. + * @returns Empty response when the role assigned. + */ + assignRoles(userId: string, roles: IdentityRoleModel[]): Observable { + const url = this.buildUserUrl() + '/' + userId + '/role-mappings/realm'; + const request = JSON.stringify(roles); + const httpMethod = 'POST', 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)) + ); + } + + /** + * Removes assigned roles. + * @param userId Id of the user. + * @param roles Array of roles. + * @returns Empty response when the role removed. + */ + removeRoles(userId: string, removedRoles: IdentityRoleModel[]): Observable { + const url = this.buildUserUrl() + '/' + userId + '/role-mappings/realm'; + const request = JSON.stringify(removedRoles); + const httpMethod = 'DELETE', 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)) + ); + } + private buildUserUrl(): any { return `${this.appConfigService.get('identityHost')}/users`; } @@ -380,4 +683,12 @@ export class IdentityUserService { return `${this.appConfigService.get('identityHost')}/clients`; } + /** + * Throw the error + * @param error + */ + private handleError(error: Response) { + this.logService.error(error); + return throwError(error || 'Server error'); + } } diff --git a/lib/process-services-cloud/src/lib/services/identity-user.service.ts b/lib/process-services-cloud/src/lib/services/identity-user.service.ts deleted file mode 100644 index 2fad48b9e9..0000000000 --- a/lib/process-services-cloud/src/lib/services/identity-user.service.ts +++ /dev/null @@ -1,60 +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 { throwError as observableThrowError, Observable, from } from 'rxjs'; -import { catchError } from 'rxjs/operators'; - -import { AppConfigService, LogService, AlfrescoApiService } from '@alfresco/adf-core'; - -@Injectable() -export class IdentityUserService { - - constructor( - private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, - private logService: LogService - ) { } - - /** - * Finds groups filtered by username. - * @param username Object containing the name filter string - * @returns List of users information - */ - findUsersByUsername(username: string): Observable { - const url = this.getUserApi(); - const httpMethod = 'GET', pathParams = {}, queryParams = { search: username }, 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)) - ); - } - - private getUserApi() { - return `${this.appConfigService.get('identityHost')}/users`; - } - - private handleError(error: any) { - this.logService.error(error); - return observableThrowError(error || 'Server error'); - } -} diff --git a/lib/process-services-cloud/src/lib/services/public-api.ts b/lib/process-services-cloud/src/lib/services/public-api.ts index ec1caf78ed..ec722bb702 100644 --- a/lib/process-services-cloud/src/lib/services/public-api.ts +++ b/lib/process-services-cloud/src/lib/services/public-api.ts @@ -15,5 +15,4 @@ * limitations under the License. */ -export * from './identity-user.service'; export * from './user-preference.cloud.service';