diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts
index ecb53a6cd..57c95f918 100644
--- a/apps/red-ui/src/app/app.module.ts
+++ b/apps/red-ui/src/app/app.module.ts
@@ -9,7 +9,7 @@ import { ApiPathInterceptor } from '@utils/api-path-interceptor';
import { MissingTranslationHandler, TranslateCompiler, TranslateLoader, TranslateModule } from '@ngx-translate/core';
import {
BASE_HREF,
- BaseConfigService,
+ BaseUserService,
CachingModule,
CommonUiModule,
HELP_DOCS,
@@ -24,7 +24,6 @@ import {
import { ToastrModule } from 'ngx-toastr';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '@environments/environment';
-import { AuthModule } from './modules/auth/auth.module';
import { AuthErrorComponent } from '@components/auth-error/auth-error.component';
import { NotificationsComponent } from '@components/notifications/notifications.component';
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
@@ -60,6 +59,7 @@ import { PdfViewerModule } from './modules/pdf-viewer/pdf-viewer.module';
import { LicenseService } from '@services/license.service';
import { TenantIdInterceptor } from '@utils/tenant-id-interceptor';
import { UI_CACHES } from '@utils/constants';
+import { AuthModule } from './modules/auth/auth.module';
export function httpLoaderFactory(httpClient: HttpClient, configService: ConfigService): PruningTranslationLoader {
return new PruningTranslationLoader(httpClient, '/assets/i18n/', `.json?version=${configService.values.FRONTEND_APP_VERSION}`);
@@ -78,14 +78,19 @@ export const appModuleFactory = (config: AppConfig) => {
SharedModule,
FileUploadDownloadModule,
HttpClientModule,
- AuthModule,
AppRoutingModule,
MonacoEditorModule,
IqserHelpModeModule,
CommonUiModule.forRoot({
existingUserPreferenceService: UserPreferenceService,
- configServiceFactory: () => new BaseConfigService(config),
+ configService: ConfigService,
+ configServiceFactory: () => new ConfigService(config),
}),
+ AuthModule,
+ // AuthModule.forRoot({
+ // existingUserService: UserService,
+ // existingRoleGuard: RedRoleGuard,
+ // }),
CachingModule.forRoot(UI_CACHES),
PdfViewerModule,
ToastrModule.forRoot({
@@ -155,6 +160,10 @@ export const appModuleFactory = (config: AppConfig) => {
provide: ErrorHandler,
useClass: GlobalErrorHandler,
},
+ {
+ provide: BaseUserService,
+ useExisting: UserService,
+ },
{
provide: HTTP_INTERCEPTORS,
multi: true,
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts
index 311bc4b13..3b329464a 100644
--- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts
+++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts
@@ -1,10 +1,10 @@
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { AdminDialogService } from '../../../services/admin-dialog.service';
-import { BaseFormComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
+import { BaseFormComponent, IconButtonTypes, IProfileUpdateRequest, LoadingService, Toaster } from '@iqser/common-ui';
import { rolesTranslations } from '@translations/roles-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
-import { IProfileUpdateRequest, User } from '@red/domain';
+import { User } from '@red/domain';
import { UserService } from '@services/user.service';
import { HttpStatusCode } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
@@ -53,7 +53,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
...prev,
[role]: [
{
- value: this.user && this.user.hasRole(role),
+ value: this.user && this.user.has(role),
disabled: this.shouldBeDisabled(role),
},
],
diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html
index 09310f37b..ae0c959fd 100644
--- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html
+++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html
@@ -52,7 +52,7 @@
diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts
index a0a3a9882..4a83f45f0 100644
--- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts
+++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts
@@ -109,7 +109,7 @@ export class UserListingScreenComponent extends ListingComponent
implement
async toggleActive(user: User) {
this._loadingService.start();
- const requestBody = { ...user, roles: user.isActive ? [] : ['RED_USER'] };
+ const requestBody = { ...user, roles: user.hasAnyRole ? [] : ['RED_USER'] };
await firstValueFrom(this._userService.updateProfile(requestBody, user.id));
await this.#loadData();
}
diff --git a/apps/red-ui/src/app/modules/archive/services/config.service.ts b/apps/red-ui/src/app/modules/archive/services/config.service.ts
index 17ef28130..7d6c3bf93 100644
--- a/apps/red-ui/src/app/modules/archive/services/config.service.ts
+++ b/apps/red-ui/src/app/modules/archive/services/config.service.ts
@@ -43,7 +43,7 @@ export class ConfigService {
userId =>
new NestedFilter({
id: userId,
- label: this._userService.getNameForId(userId),
+ label: this._userService.getName(userId),
}),
);
diff --git a/apps/red-ui/src/app/modules/auth/auth.module.ts b/apps/red-ui/src/app/modules/auth/auth.module.ts
index f1529e645..de2840206 100644
--- a/apps/red-ui/src/app/modules/auth/auth.module.ts
+++ b/apps/red-ui/src/app/modules/auth/auth.module.ts
@@ -5,7 +5,6 @@ import { HttpClientModule } from '@angular/common/http';
import { KeycloakAngularModule, KeycloakOptions, KeycloakService } from 'keycloak-angular';
import { ConfigService } from '@services/config.service';
import { BASE_HREF } from '@iqser/common-ui';
-import { firstValueFrom } from 'rxjs';
function getKeycloakOptions(configService: ConfigService, baseUrl: string) {
let url: string = configService.values.OAUTH_URL;
@@ -37,11 +36,9 @@ function configureAutomaticRedirectToLoginScreen(keyCloakService: KeycloakServic
export function keycloakInitializer(keycloakService: KeycloakService, configService: ConfigService, baseUrl: string): () => Promise {
return () =>
- firstValueFrom(configService.loadLocalConfig()).then(() =>
- keycloakService
- .init(getKeycloakOptions(configService, baseUrl))
- .then(() => configureAutomaticRedirectToLoginScreen(keycloakService)),
- );
+ keycloakService
+ .init(getKeycloakOptions(configService, baseUrl))
+ .then(() => configureAutomaticRedirectToLoginScreen(keycloakService));
}
@NgModule({
diff --git a/apps/red-ui/src/app/modules/auth/red-role.guard.ts b/apps/red-ui/src/app/modules/auth/red-role.guard.ts
index e9f33c587..25a9bab19 100644
--- a/apps/red-ui/src/app/modules/auth/red-role.guard.ts
+++ b/apps/red-ui/src/app/modules/auth/red-role.guard.ts
@@ -1,71 +1,51 @@
-import { Injectable } from '@angular/core';
-import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
+import { inject, Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { UserService } from '@services/user.service';
-import { LoadingService } from '@iqser/common-ui';
-import { Observable } from 'rxjs';
+import { RoleGuard } from '@iqser/common-ui';
@Injectable({
providedIn: 'root',
})
-export class RedRoleGuard implements CanActivate {
- constructor(
- protected readonly _router: Router,
- private readonly _loadingService: LoadingService,
- private readonly _userService: UserService,
- ) {}
+export class RedRoleGuard extends RoleGuard {
+ protected readonly _userService = inject(UserService);
- canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
- return new Observable(obs => {
- if (!this._userService.currentUser.hasAnyREDRoles) {
- this._router.navigate(['/auth-error']);
- this._loadingService.stop();
- obs.next(false);
- obs.complete();
- return;
+ async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {
+ const currentUser = this._userService.currentUser;
+
+ if (!currentUser.hasAnyREDRoles) {
+ await this._router.navigate(['/auth-error']);
+ this._loadingService.stop();
+ return false;
+ }
+
+ // we have at least 1 RED Role -> if it's not user he must be an admin
+ if (currentUser.isUserAdmin && !currentUser.isAdmin && state.url.includes('admin') && !state.url.includes('users')) {
+ await this._router.navigate(['/main/admin/users']);
+ return false;
+ }
+
+ if (
+ currentUser.isUserAdmin &&
+ !currentUser.isAdmin &&
+ !currentUser.isUser &&
+ !(state.url.startsWith('/main/admin/users') || state.url.startsWith('/main/my-profile'))
+ ) {
+ await this._router.navigate(['/main/admin/users']);
+ return false;
+ }
+
+ if (route.data.requiredRoles) {
+ if (currentUser.hasAny(route.data.requiredRoles)) {
+ return true;
}
- // we have at least 1 RED Role -> if it's not user he must be admin
-
- if (
- this._userService.currentUser.isUserAdmin &&
- !this._userService.currentUser.isAdmin &&
- state.url.includes('admin') &&
- !state.url.includes('users')
- ) {
- this._router.navigate(['/main/admin/users']);
- obs.next(false);
- obs.complete();
- return;
- }
-
- if (
- this._userService.currentUser.isUserAdmin &&
- !this._userService.currentUser.isAdmin &&
- !this._userService.currentUser.isUser &&
- !(state.url.startsWith('/main/admin/users') || state.url.startsWith('/main/my-profile'))
- ) {
- this._router.navigate(['/main/admin/users']);
- obs.next(false);
- obs.complete();
- return;
- }
-
- if (route.data.requiredRoles) {
- if (this._userService.hasAnyRole(route.data.requiredRoles)) {
- obs.next(true);
- obs.complete();
- } else {
- if (!this._userService.currentUser.isUser) {
- this._router.navigate(['/main/admin']);
- } else {
- this._router.navigate(['/']);
- }
- obs.next(false);
- obs.complete();
- }
+ if (!currentUser.isUser) {
+ await this._router.navigate(['/main/admin']);
} else {
- obs.next(true);
- obs.complete();
+ await this._router.navigate(['/']);
}
- });
+ return false;
+ }
+
+ return true;
}
}
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts
index 9ee3d253a..c3a30c1e7 100644
--- a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts
+++ b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts
@@ -65,7 +65,7 @@ export class DossierDetailsComponent {
const dossierRequest: IDossierRequest = { ...dossier, ownerId: owner.id };
await firstValueFrom(this._dossiersService.createOrUpdate(dossierRequest));
- const ownerName = this._userService.getNameForId(owner.id);
+ const ownerName = this._userService.getName(owner.id);
const dossierName = dossier.dossierName;
this._toaster.info(_('assignment.owner'), { params: { ownerName, dossierName } });
}
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts
index e5970d6f1..1efc8b4d0 100644
--- a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts
+++ b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts
@@ -68,7 +68,7 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
const fileName = this.dossier.dossierName + '.export.csv';
const mapper = (file?: File) => ({
...file,
- assignee: this._userService.getNameForId(file.assignee) || '-',
+ assignee: this._userService.getName(file.assignee) || '-',
primaryAttribute: this._primaryFileAttributeService.getPrimaryFileAttributeValue(file, this.dossier.dossierTemplateId),
});
const fileFields = [
diff --git a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts
index 253daad6b..2c9753ba6 100644
--- a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts
+++ b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts
@@ -284,7 +284,7 @@ export class ConfigService {
peopleFilters.push(
new NestedFilter({
id: userId,
- label: this._userService.getNameForId(userId),
+ label: this._userService.getName(userId),
}),
);
});
diff --git a/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts b/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts
index fd79b73b6..71d9024ef 100644
--- a/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts
+++ b/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts
@@ -142,7 +142,7 @@ export class ConfigService {
userId =>
new NestedFilter({
id: userId,
- label: this._userService.getNameForId(userId),
+ label: this._userService.getName(userId),
}),
);
diff --git a/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts b/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts
index ee4db7c40..c28bbbc97 100644
--- a/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts
+++ b/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts
@@ -97,7 +97,7 @@ export class UserManagementComponent {
async assignReviewer(file: File, user: User | string) {
const assigneeId = typeof user === 'string' ? user : user?.id;
- const reviewerName = this.userService.getNameForId(assigneeId);
+ const reviewerName = this.userService.getName(assigneeId);
const { dossierId, filename } = file;
this.loadingService.start();
diff --git a/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts b/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts
index c6091a4e6..42e6c84a0 100644
--- a/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts
+++ b/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts
@@ -196,7 +196,7 @@ export class SearchScreenComponent extends ListingComponent imp
const assignee = this._routeAssignee;
const assigneeToFilter = (userId: string) => {
const checked = assignee === userId;
- return new NestedFilter({ id: userId, label: this._userService.getNameForId(userId), checked });
+ return new NestedFilter({ id: userId, label: this._userService.getName(userId), checked });
};
const assigneeFilter: IFilterGroup = {
slug: 'assignee',
diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts
index 138b56f2c..86658c4a9 100644
--- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts
+++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts
@@ -1,4 +1,4 @@
-import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core';
+import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { UserService } from '@services/user.service';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Dossier, IDossierRequest } from '@red/domain';
@@ -135,7 +135,7 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
setMembersSelectOptions(value = this.searchQuery): void {
this.membersSelectOptions = this.userService.eligibleUsers
- .filter(user => this.userService.getNameForId(user.id).toLowerCase().includes(value.toLowerCase()))
+ .filter(user => this.userService.getName(user.id).toLowerCase().includes(value.toLowerCase()))
.filter(user => this.selectedOwnerId !== user.id)
.map(user => user.id);
}
diff --git a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts
index 6c5ca2331..fdce00d6e 100644
--- a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts
+++ b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts
@@ -39,7 +39,7 @@ export class InitialsAvatarComponent implements OnInit, OnChanges {
}
get disabled(): boolean {
- return this._user && !this._isSystemUser && !this._user.isActive;
+ return this._user && !this._isSystemUser && !this._user.hasAnyRole;
}
get isCurrentUser(): boolean {
diff --git a/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts b/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts
index fd4c06bb3..b89bb5058 100644
--- a/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts
+++ b/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts
@@ -54,6 +54,6 @@ export class NamePipe implements PipeTransform {
if (!user) {
return undefined;
}
- return typeof user === 'string' ? this._userService.getNameForId(user) : user.name;
+ return typeof user === 'string' ? this._userService.getName(user) : user.name;
}
}
diff --git a/apps/red-ui/src/app/services/config.service.ts b/apps/red-ui/src/app/services/config.service.ts
index d4b568ce6..1441ea740 100644
--- a/apps/red-ui/src/app/services/config.service.ts
+++ b/apps/red-ui/src/app/services/config.service.ts
@@ -1,55 +1,6 @@
import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
-import { Title } from '@angular/platform-browser';
-import packageInfo from '../../../../../package.json';
-import envConfig from '../../assets/config/config.json';
-import { CacheApiService, wipeAllCaches } from '@iqser/common-ui';
-import { Observable } from 'rxjs';
-import { tap } from 'rxjs/operators';
+import { BaseConfigService } from '@iqser/common-ui';
import { AppConfig } from '@red/domain';
-const version = packageInfo.version;
-
-@Injectable({
- providedIn: 'root',
-})
-export class ConfigService {
- constructor(
- private readonly _httpClient: HttpClient,
- private readonly _cacheApiService: CacheApiService,
- private readonly _titleService: Title,
- ) {
- this._checkFrontendVersion();
- }
-
- private _values: AppConfig = { ...envConfig, FRONTEND_APP_VERSION: version } as const;
-
- get values() {
- return this._values;
- }
-
- loadLocalConfig(): Observable {
- return this._httpClient.get('/assets/config/config.json').pipe(
- tap(config => {
- console.log('[REDACTION] Started with local config: ', config);
- this._values = config;
- }),
- );
- }
-
- updateDisplayName(name: string): void {
- this._values = { ...this._values, APP_NAME: name } as const;
- this._titleService.setTitle(this._values.APP_NAME || 'RedactManager');
- }
-
- private _checkFrontendVersion(): void {
- this._cacheApiService.getCachedValue('FRONTEND_APP_VERSION').then(async lastVersion => {
- console.log('[REDACTION] Last app version: ', lastVersion, ' current version ', version);
- if (lastVersion !== version) {
- console.warn('[REDACTION] Version-mismatch - wiping caches!');
- await wipeAllCaches();
- }
- await this._cacheApiService.cacheValue('FRONTEND_APP_VERSION', version);
- });
- }
-}
+@Injectable()
+export class ConfigService extends BaseConfigService {}
diff --git a/apps/red-ui/src/app/services/entity-services/trash.service.ts b/apps/red-ui/src/app/services/entity-services/trash.service.ts
index f2379985a..d795b8806 100644
--- a/apps/red-ui/src/app/services/entity-services/trash.service.ts
+++ b/apps/red-ui/src/app/services/entity-services/trash.service.ts
@@ -71,7 +71,7 @@ export class TrashService extends EntitiesService {
this._systemPreferencesService.values.softDeleteCleanupTime,
this._permissionsService.canRestoreDossier(dossier),
this._permissionsService.canHardDeleteDossier(dossier),
- this._userService.getNameForId(dossier.ownerId),
+ this._userService.getName(dossier.ownerId),
),
),
switchMap(dossiers => this._dossierStatsService.getFor(dossiers.map(d => d.id)).pipe(map(() => dossiers))),
@@ -81,7 +81,7 @@ export class TrashService extends EntitiesService {
getFiles(dossierIds = this._activeDossiersService.all.map(d => d.id)): Observable {
return this._post>(dossierIds, 'status/softdeleted').pipe(
map(res => flatMap(Object.values(res))),
- mapEach(file => new File(file, this._userService.getNameForId(file.assignee))),
+ mapEach(file => new File(file, this._userService.getName(file.assignee))),
mapEach(file => {
const dossier = this._activeDossiersService.find(file.dossierId);
return new TrashFile(
@@ -90,7 +90,7 @@ export class TrashService extends EntitiesService {
this._systemPreferencesService.values.softDeleteCleanupTime,
this._permissionsService.canRestoreFile(file, dossier),
this._permissionsService.canHardDeleteFile(file, dossier),
- this._userService.getNameForId(file.assignee),
+ this._userService.getName(file.assignee),
dossier.dossierName,
);
}),
diff --git a/apps/red-ui/src/app/services/files/files.service.ts b/apps/red-ui/src/app/services/files/files.service.ts
index e00ab4c92..323ccee30 100644
--- a/apps/red-ui/src/app/services/files/files.service.ts
+++ b/apps/red-ui/src/app/services/files/files.service.ts
@@ -27,7 +27,7 @@ export class FilesService extends EntitiesService {
/** Reload dossier files + stats. */
loadAll(dossierId: string) {
const files$ = this.getFor(dossierId).pipe(
- mapEach(file => new File(file, this._userService.getNameForId(file.assignee))),
+ mapEach(file => new File(file, this._userService.getName(file.assignee))),
tap(() => this._logger.info('[FILE] Loaded')),
);
const loadStats$ = files$.pipe(switchMap(files => this._dossierStatsService.getFor([dossierId]).pipe(map(() => files))));
@@ -36,7 +36,7 @@ export class FilesService extends EntitiesService {
reload(dossierId: string, file: File): Observable {
return super._getOne([dossierId, file.id]).pipe(
- map(_file => new File(_file, this._userService.getNameForId(_file.assignee))),
+ map(_file => new File(_file, this._userService.getName(_file.assignee))),
switchMap(_file => this._dossierStatsService.getFor([dossierId]).pipe(map(() => _file))),
map(_file => this._filesMapService.replace([_file])),
tap(() => this._logger.info('[FILE] Reloaded')),
diff --git a/apps/red-ui/src/app/services/notifications.service.ts b/apps/red-ui/src/app/services/notifications.service.ts
index bea947d0d..922a256b6 100644
--- a/apps/red-ui/src/app/services/notifications.service.ts
+++ b/apps/red-ui/src/app/services/notifications.service.ts
@@ -102,6 +102,6 @@ export class NotificationsService extends EntitiesService {
- readonly currentUser$: Observable;
+export class UserService extends BaseUserService {
protected readonly _defaultModelPath = 'user';
protected readonly _entityClass = User;
- readonly #currentUser$ = new BehaviorSubject(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);
@@ -36,109 +17,18 @@ export class UserService extends EntitiesService {
return this.all.filter(user => user.isUser || user.isManager);
}
- async initialize(): Promise {
- 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 {
- 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);
+ if (this.currentUser.isUserAdmin || this.currentUser.isUser || this.currentUser.isAdmin) {
+ return super.loadAll();
}
-
- 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;
+ getAll() {
+ const url = this.currentUser.isUserAdmin ? this._defaultModelPath : `${this._defaultModelPath}/red`;
+ return super.getAll(url);
}
- 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 {
- 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(body, `${this._defaultModelPath}/profile/${userId}`);
- }
-
- @Validate()
- updateMyProfile(@RequiredParam() body: IMyProfileUpdateRequest) {
- return this._post(body, `${this._defaultModelPath}/my-profile`);
- }
-
- @Validate()
- resetPassword(@RequiredParam() body: IResetPasswordRequest, @RequiredParam() userId: string) {
- return this._post(body, `${this._defaultModelPath}/${userId}/reset-password`);
- }
-
- @Validate()
- create(@RequiredParam() body: ICreateUserRequest) {
- return this._post(body);
- }
-
- delete(userIds: List) {
- const queryParams = userIds.map(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');
- }
+ protected readonly _rolesFilter = (role: string) => role.startsWith('RED_');
}
export function getCurrentUser() {
diff --git a/apps/red-ui/src/app/utils/configuration.initializer.ts b/apps/red-ui/src/app/utils/configuration.initializer.ts
index 202206cfd..3e409c8c3 100644
--- a/apps/red-ui/src/app/utils/configuration.initializer.ts
+++ b/apps/red-ui/src/app/utils/configuration.initializer.ts
@@ -1,7 +1,7 @@
-import { catchError, filter, mergeMap, switchMap, take, tap } from 'rxjs/operators';
+import { catchError, filter, mergeMap, switchMap, tap } from 'rxjs/operators';
import { ConfigService } from '@services/config.service';
import { Title } from '@angular/platform-browser';
-import { firstValueFrom, from, map, of, throwError } from 'rxjs';
+import { firstValueFrom, map, of, throwError } from 'rxjs';
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
import { GeneralSettingsService } from '@services/general-settings.service';
import { LanguageService } from '@iqser/common-ui';
@@ -35,10 +35,10 @@ export function configurationInitializer(
const setup = keycloakService.keycloakEvents$.pipe(
filter(event => event.type === KeycloakEventType.OnReady),
map(() => featuresService.loadConfig()),
- switchMap(() => from(keycloakService.isLoggedIn())),
- switchMap(loggedIn => (!loggedIn ? throwError('Not Logged In') : of({}))),
- switchMap(() => from(userService.loadCurrentUser())),
- switchMap(user => (!user.hasAnyREDRoles ? throwError('Not user has no red roles') : of({}))),
+ switchMap(() => keycloakService.isLoggedIn()),
+ switchMap(loggedIn => (!loggedIn ? throwError(() => 'Not Logged In') : of({}))),
+ switchMap(() => userService.initialize()),
+ switchMap(() => (!userService.currentUser.hasAnyREDRoles ? throwError(() => 'Not user has no red roles') : of({}))),
mergeMap(() => generalSettingsService.getGeneralConfigurations()),
tap(configuration => configService.updateDisplayName(configuration.displayName)),
switchMap(() => systemPreferencesService.loadPreferences()),
@@ -52,9 +52,7 @@ export function configurationInitializer(
lastDossierTemplateRedirect(baseHref.replace('/', ''), userPreferenceService);
}),
switchMap(() => languageService.setInitialLanguage()),
- tap(() => userService.initialize()),
switchMap(() => licenseService.loadLicense()),
- take(1),
);
return () => firstValueFrom(setup);
}
diff --git a/apps/red-ui/src/app/utils/filter-utils.ts b/apps/red-ui/src/app/utils/filter-utils.ts
index 9ab679689..a766e99c0 100644
--- a/apps/red-ui/src/app/utils/filter-utils.ts
+++ b/apps/red-ui/src/app/utils/filter-utils.ts
@@ -83,7 +83,7 @@ export const dossierStateChecker = (dw: Dossier, filter: INestedFilter) =>
export const dossierApproverChecker = (dw: Dossier, filter: INestedFilter) => dw.approverIds.includes(filter.id);
export const userTypeFilters: { [key in UserType]: (user: User) => boolean } = {
- INACTIVE: (user: User) => !user.isActive,
+ INACTIVE: (user: User) => !user.hasAnyRole,
REGULAR: (user: User) => user.roles.length === 1 && user.roles[0] === 'RED_USER',
RED_MANAGER: (user: User) => user.isManager && !user.isAdmin,
MANAGER_ADMIN: (user: User) => user.isManager && user.isAdmin,
diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json
index 8e7d077a8..0c71adeeb 100644
--- a/apps/red-ui/src/assets/config/config.json
+++ b/apps/red-ui/src/assets/config/config.json
@@ -1,7 +1,7 @@
{
"ADMIN_CONTACT_NAME": null,
"ADMIN_CONTACT_URL": null,
- "API_URL": "https://dev-05.iqser.cloud/redaction-gateway-v1",
+ "API_URL": "https://dev-04.iqser.cloud/redaction-gateway-v1",
"APP_NAME": "RedactManager",
"AUTO_READ_TIME": 3,
"BACKEND_APP_VERSION": "4.4.40",
@@ -11,7 +11,7 @@
"MAX_RETRIES_ON_SERVER_ERROR": 3,
"OAUTH_CLIENT_ID": "redaction",
"OAUTH_IDP_HINT": null,
- "OAUTH_URL": "https://dev-05.iqser.cloud/auth/realms/redaction",
+ "OAUTH_URL": "https://dev-04.iqser.cloud/auth/realms/redaction",
"RECENT_PERIOD_IN_HOURS": 24,
"SELECTION_MODE": "structural",
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview"
diff --git a/libs/red-domain/src/lib/users/create-user.request.ts b/libs/red-domain/src/lib/users/create-user.request.ts
deleted file mode 100644
index 8faaea329..000000000
--- a/libs/red-domain/src/lib/users/create-user.request.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { List } from '@iqser/common-ui';
-
-export interface ICreateUserRequest {
- /**
- * Email of user.
- */
- email?: string;
- /**
- * First name of user.
- */
- firstName?: string;
- /**
- * Last name of user.
- */
- lastName?: string;
- /**
- * The list of RED_* roles.
- */
- roles?: List;
-}
diff --git a/libs/red-domain/src/lib/users/index.ts b/libs/red-domain/src/lib/users/index.ts
index 1425c58fe..b66d5cb35 100644
--- a/libs/red-domain/src/lib/users/index.ts
+++ b/libs/red-domain/src/lib/users/index.ts
@@ -1,8 +1,3 @@
export * from './user.model';
-export * from './user';
-export * from './my-profile-update.request';
-export * from './profile-update.request';
export * from './profile';
export * from './types';
-export * from './create-user.request';
-export * from './reset-password.request';
diff --git a/libs/red-domain/src/lib/users/my-profile-update.request.ts b/libs/red-domain/src/lib/users/my-profile-update.request.ts
deleted file mode 100644
index e29d1d09f..000000000
--- a/libs/red-domain/src/lib/users/my-profile-update.request.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export interface IMyProfileUpdateRequest {
- /**
- * Email of user.
- */
- email?: string;
- /**
- * First name of user.
- */
- firstName?: string;
- /**
- * Last name of user.
- */
- lastName?: string;
-}
diff --git a/libs/red-domain/src/lib/users/profile-update.request.ts b/libs/red-domain/src/lib/users/profile-update.request.ts
deleted file mode 100644
index 778db3489..000000000
--- a/libs/red-domain/src/lib/users/profile-update.request.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { IMyProfileUpdateRequest } from './my-profile-update.request';
-import { List } from '@iqser/common-ui';
-
-export interface IProfileUpdateRequest extends IMyProfileUpdateRequest {
- /**
- * Roles.
- */
- roles?: List;
-}
diff --git a/libs/red-domain/src/lib/users/reset-password.request.ts b/libs/red-domain/src/lib/users/reset-password.request.ts
deleted file mode 100644
index 1222768c1..000000000
--- a/libs/red-domain/src/lib/users/reset-password.request.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface IResetPasswordRequest {
- password?: string;
- temporary?: boolean;
-}
diff --git a/libs/red-domain/src/lib/users/user.model.ts b/libs/red-domain/src/lib/users/user.model.ts
index e4c322bd1..d60bec90e 100644
--- a/libs/red-domain/src/lib/users/user.model.ts
+++ b/libs/red-domain/src/lib/users/user.model.ts
@@ -1,32 +1,14 @@
-import { IListable, List } from '@iqser/common-ui';
+import { IIqserUser, IqserUser, List } from '@iqser/common-ui';
import { KeycloakProfile } from 'keycloak-js';
-import { IUser } from './user';
-export class User implements IUser, IListable {
- readonly email?: string;
- readonly username?: string;
- readonly firstName?: string;
- readonly lastName?: string;
- readonly name?: string;
- readonly searchKey: string;
-
- readonly isActive = this.roles.length > 0;
- readonly isManager = this.hasRole('RED_MANAGER');
- readonly isUserAdmin = this.hasRole('RED_USER_ADMIN');
- readonly isUser = this.hasRole('RED_USER');
- readonly isAdmin = this.hasRole('RED_ADMIN');
+export class User extends IqserUser {
+ readonly isManager = this.has('RED_MANAGER');
+ readonly isUserAdmin = this.has('RED_USER_ADMIN');
+ readonly isUser = this.has('RED_USER');
+ readonly isAdmin = this.has('RED_ADMIN');
readonly hasAnyREDRoles = this.isUser || this.isManager || this.isAdmin || this.isUserAdmin;
- constructor(user: KeycloakProfile | IUser, readonly roles: List, readonly id: string) {
- this.email = user.email;
- this.username = user.username || this.email;
- this.firstName = user.firstName;
- this.lastName = user.lastName;
- this.name = this.firstName && this.lastName ? `${this.firstName} ${this.lastName}` : this.username;
- this.searchKey = `${this.name || '-'}${this.username || '-'}${this.email || ''}`;
- }
-
- hasRole(role: string): boolean {
- return this.roles.indexOf(role) >= 0;
+ constructor(user: KeycloakProfile | IIqserUser, readonly roles: List, readonly userId: string) {
+ super(user, roles, userId);
}
}
diff --git a/libs/red-domain/src/lib/users/user.ts b/libs/red-domain/src/lib/users/user.ts
deleted file mode 100644
index 310383a93..000000000
--- a/libs/red-domain/src/lib/users/user.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Object containing information of user and roles.
- */
-import { IProfileUpdateRequest } from './profile-update.request';
-
-export interface IUser extends IProfileUpdateRequest {
- /**
- * Id of user.
- */
- readonly userId?: string;
- /**
- * Username for login.
- */
- readonly username?: string;
-}