src/app/core/user/user-admin-service/user-admin.service.ts
Admin functionalities to manage users in an authentication server like Keycloak.
No results matching.
Properties |
|
Methods |
|
| Static Readonly ACCOUNT_MANAGER_ROLE |
Type : string
|
Default value : "account_manager"
|
|
Users with this role can create and update other accounts. |
| canManageAccounts |
canManageAccounts()
|
|
Whether the current user has the role required to manage accounts (e.g. list, create, update or delete accounts) on the authentication server.
Returns :
boolean
|
| Abstract createRole | ||||||
createRole(role: Pick<Role, "name" | "description">)
|
||||||
|
Create a new realm role in the authentication server
Parameters :
Returns :
Observable<void>
Throws :
|
| Abstract createUser | ||||||||||||||||
createUser(userEntityId: string, email: string, roles: Role[])
|
||||||||||||||||
|
Create a user account with the given name and email
Parameters :
Returns :
Observable<UserAccount>
The user account created
Throws :
|
| Abstract deleteRole | ||||||
deleteRole(roleName: string)
|
||||||
|
Delete a realm role from the authentication server. Users currently having the role lose it.
Parameters :
Returns :
Observable<void>
|
| Abstract deleteUser | ||||||||
deleteUser(userEntityId: string)
|
||||||||
|
Delete a user with the given id
Parameters :
Returns :
Observable<{ userDeleted: boolean }>
|
| Abstract getAllRoles |
getAllRoles()
|
|
Get all available roles of the server
Returns :
Observable<Role[]>
|
| Abstract getAllUsers |
getAllUsers()
|
|
Get all users registered in the authentication server (Keycloak) for this realm
Returns :
Observable<UserAccount[]>
An array of all user accounts with their details, including only non-technical roles |
| Abstract getUser | ||||||||
getUser(userEntityId: string)
|
||||||||
|
Get the user account details of the user linked to the given entity.
Parameters :
Returns :
Observable<UserAccount>
The user account details or
Throws :
|
| Abstract resendInvitation | ||||||||
resendInvitation(userAccountId: string)
|
||||||||
|
Re-send the account invitation email (e.g. if the original link expired)
Parameters :
Returns :
Observable<void>
|
| Abstract updateRole | |||||||||
updateRole(roleName: string, update: Pick<Role, "description">)
|
|||||||||
|
Update the description of an existing realm role
Parameters :
Returns :
Observable<void>
|
| Abstract updateUser | ||||||||||||
updateUser(userAccountId: string, updatedUser: Partial<UserAccount>)
|
||||||||||||
|
Update the user with the given id
Parameters :
Returns :
Observable<{ userUpdated: boolean }>
|
import { inject } from "@angular/core";
import { Observable } from "rxjs";
import { Role, UserAccount } from "./user-account";
import { SessionSubject } from "../../session/auth/session-info";
/**
* Admin functionalities to manage users in an authentication server like Keycloak.
*/
export abstract class UserAdminService {
/**
* Users with this role can create and update other accounts.
*/
static readonly ACCOUNT_MANAGER_ROLE = "account_manager";
private readonly sessionInfo = inject(SessionSubject, { optional: true });
/**
* Whether the current user has the role required to manage accounts
* (e.g. list, create, update or delete accounts) on the authentication server.
*/
canManageAccounts(): boolean {
return (
this.sessionInfo?.value?.roles?.includes(
UserAdminService.ACCOUNT_MANAGER_ROLE,
) ?? false
);
}
/**
* Get the user account details of the user linked to the given entity.
* @param userEntityId The entity id of the "profile" linked with the account
* @returns The user account details or `null` of no user is found
* @throws {@link UserAdminApiError} if an error occurs (but not if no user is found)
*/
abstract getUser(userEntityId: string): Observable<UserAccount>;
/**
* Create a user account with the given name and email
* @param userEntityId The entity id of the "profile" linked with the account
* @param email
* @param roles
* @returns The user account created
* @throws {@link UserAdminApiError} status=409 if email already exists
*/
abstract createUser(
userEntityId: string,
email: string,
roles: Role[],
): Observable<UserAccount>;
/**
* Update the user with the given id
* @param userAccountId The user account id of the authentication server (not the profile entity id)
* @param updatedUser see {@link https://www.keycloak.org/docs-api/19.0.2/rest-api/index.html#_userrepresentation}
*/
abstract updateUser(
userAccountId: string,
updatedUser: Partial<UserAccount>,
): Observable<{ userUpdated: boolean }>;
/**
* Delete a user with the given id
* @param userEntityId The entity id of the "profile" linked with the account
*/
abstract deleteUser(
userEntityId: string,
): Observable<{ userDeleted: boolean }>;
/**
* Re-send the account invitation email (e.g. if the original link expired)
* @param userAccountId The user account id of the authentication server (not the profile entity id)
*/
abstract resendInvitation(userAccountId: string): Observable<void>;
/**
* Get all available roles of the server
*/
abstract getAllRoles(): Observable<Role[]>;
/**
* Create a new realm role in the authentication server
* @throws {@link UserAdminApiError} status=409 if the role already exists
*/
abstract createRole(
role: Pick<Role, "name" | "description">,
): Observable<void>;
/**
* Update the description of an existing realm role
*/
abstract updateRole(
roleName: string,
update: Pick<Role, "description">,
): Observable<void>;
/**
* Delete a realm role from the authentication server.
* Users currently having the role lose it.
*/
abstract deleteRole(roleName: string): Observable<void>;
/**
* Get all users registered in the authentication server (Keycloak) for this realm
* @returns An array of all user accounts with their details, including only non-technical roles
*/
abstract getAllUsers(): Observable<UserAccount[]>;
}
export class UserAdminApiError extends Error {
/**
* The HTTP status code of the error.
* - 404: Not Found (e.g. user not found)
* - 409: Conflict (e.g. email already exists)
* - 500: Internal Server Error
*/
status: number;
constructor(status: number, message?: string) {
super(message);
this.name = "UserAdminApiError";
// Set the prototype explicitly to maintain the correct prototype chain (see https://medium.com/@Nelsonalfonso/understanding-custom-errors-in-typescript-a-complete-guide-f47a1df9354c)
Object.setPrototypeOf(this, UserAdminApiError.prototype);
this.status = status;
if (!message) {
this.message = this.generateDefaultMessage(status);
}
}
private generateDefaultMessage(status: number) {
switch (status) {
case 403:
return $localize`:User API error:You do not have permission to manage user accounts.`;
case 404:
return $localize`:User API error:The entry does not exist.`;
case 409:
return $localize`:User API error:The email address is already in use. Only one account is allowed per email address.`;
case 500:
return $localize`:User API error:There was an internal error at the user management server. Please try again later or reach out to your technical support team.`;
default:
return `Unexpected error with status code ${status}`;
}
}
}