148 lines
4.8 KiB
TypeScript
148 lines
4.8 KiB
TypeScript
import { inject, Inject, Injectable } from '@angular/core';
|
|
import { KeycloakService } from 'keycloak-angular';
|
|
import jwt_decode from 'jwt-decode';
|
|
import { ICreateUserRequest, IMyProfileUpdateRequest, IProfileUpdateRequest, IResetPasswordRequest, IUser, User } from '@red/domain';
|
|
import { BASE_HREF } from '../tokens';
|
|
import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs';
|
|
import { CacheApiService, EntitiesService, List, mapEach, QueryParam, RequiredParam, Validate } from '@iqser/common-ui';
|
|
import { tap } from 'rxjs/operators';
|
|
|
|
@Injectable({
|
|
providedIn: 'root',
|
|
})
|
|
export class UserService extends EntitiesService<IUser, User> {
|
|
readonly currentUser$: Observable<User>;
|
|
protected readonly _defaultModelPath = 'user';
|
|
protected readonly _entityClass = User;
|
|
readonly #currentUser$ = new BehaviorSubject<User>(null);
|
|
|
|
constructor(
|
|
@Inject(BASE_HREF) private readonly _baseHref: string,
|
|
private readonly _keycloakService: KeycloakService,
|
|
private readonly _cacheApiService: CacheApiService,
|
|
) {
|
|
super();
|
|
this.currentUser$ = this.#currentUser$.asObservable();
|
|
}
|
|
|
|
get currentUser(): User {
|
|
return this.#currentUser$.value;
|
|
}
|
|
|
|
get managerUsers(): User[] {
|
|
return this.all.filter(user => user.isManager);
|
|
}
|
|
|
|
get eligibleUsers(): User[] {
|
|
return this.all.filter(user => user.isUser || user.isManager);
|
|
}
|
|
|
|
async initialize(): Promise<void> {
|
|
console.log('[Redaction] Initializing users for: ', this.currentUser);
|
|
if (!this.currentUser) {
|
|
return;
|
|
}
|
|
|
|
if (this.currentUser.isUserAdmin || this.currentUser.isUser || this.currentUser.isAdmin) {
|
|
await firstValueFrom(this.loadAll());
|
|
}
|
|
}
|
|
|
|
logout() {
|
|
this._cacheApiService.wipeCaches().then();
|
|
this._keycloakService.logout().then();
|
|
}
|
|
|
|
loadAll() {
|
|
const all$ = this.currentUser.isUserAdmin ? this.getUsers() : this.getUsers(true);
|
|
|
|
return all$.pipe(
|
|
mapEach(user => new User(user, user.roles, user.userId)),
|
|
tap(users => this.setEntities(users)),
|
|
);
|
|
}
|
|
|
|
async loadCurrentUser(): Promise<User> {
|
|
const token = await this._keycloakService.getToken();
|
|
const decoded = jwt_decode(token);
|
|
const userId = (<{ sub: string }>decoded).sub;
|
|
|
|
const roles = this._keycloakService.getUserRoles(true).filter(role => role.startsWith('RED_'));
|
|
let profile;
|
|
try {
|
|
profile = await this._keycloakService.loadUserProfile(true);
|
|
} catch (e) {
|
|
await this._keycloakService.logout();
|
|
console.log(e);
|
|
}
|
|
|
|
const user = new User(profile, roles, userId);
|
|
this.replace(user);
|
|
|
|
this.#currentUser$.next(this.find(userId));
|
|
return user;
|
|
}
|
|
|
|
getNameForId(userId: string): string | undefined {
|
|
return this.find(userId)?.name;
|
|
}
|
|
|
|
hasAnyRole(requiredRoles: string[], user = this.currentUser): boolean {
|
|
if (requiredRoles?.length > 0) {
|
|
for (const role of requiredRoles) {
|
|
if (user.hasRole(role)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
getUsers(onlyRed = false, refreshCache = true): Observable<IUser[]> {
|
|
const url = onlyRed ? `${this._defaultModelPath}/red` : this._defaultModelPath;
|
|
return super.getAll(url, [{ key: 'refreshCache', value: refreshCache }]);
|
|
}
|
|
|
|
@Validate()
|
|
updateProfile(@RequiredParam() body: IProfileUpdateRequest, @RequiredParam() userId: string) {
|
|
return this._post<unknown>(body, `${this._defaultModelPath}/profile/${userId}`);
|
|
}
|
|
|
|
@Validate()
|
|
updateMyProfile(@RequiredParam() body: IMyProfileUpdateRequest) {
|
|
return this._post<unknown>(body, `${this._defaultModelPath}/my-profile`);
|
|
}
|
|
|
|
@Validate()
|
|
resetPassword(@RequiredParam() body: IResetPasswordRequest, @RequiredParam() userId: string) {
|
|
return this._post<unknown>(body, `${this._defaultModelPath}/${userId}/reset-password`);
|
|
}
|
|
|
|
@Validate()
|
|
create(@RequiredParam() body: ICreateUserRequest) {
|
|
return this._post(body);
|
|
}
|
|
|
|
delete(userIds: List) {
|
|
const queryParams = userIds.map<QueryParam>(userId => ({ key: 'userId', value: userId }));
|
|
return super.delete(userIds, this._defaultModelPath, queryParams);
|
|
}
|
|
|
|
find(id: string): User | undefined {
|
|
if (id?.toLowerCase() === 'system') {
|
|
return new User({ username: 'System' }, [], 'system');
|
|
}
|
|
if (!id) {
|
|
return undefined;
|
|
}
|
|
return super.find(id) || new User({ username: 'Deleted User' }, [], 'deleted');
|
|
}
|
|
}
|
|
|
|
export function getCurrentUser() {
|
|
return inject(UserService).currentUser;
|
|
}
|