Ng16 migration (#10114)

* NG-16 - migration step 1

* NG16 - fixed the builds

* [MIGRATION] - Switching off no empty functions rule

* [MIGRATION] - Somehow the fix for the cli types got lost

* [MIGRATION] - Something happened on the way to heaven

* [MIGRATION] - Ok this is weird

* [MIGRATION] - Ok this is really weird

* [MIGRATION] - change selector for expanded expansion panel content

* [MIGRATION] - storybook chips related e2e fails fix, unit alignments

* [MIGRATION] - Ok this is really weird

* [MIGRATION] - Updating outdated packages

* [MIGRATION] - updated deps for process cloud

* [MIGRATION] - Rebased to latest

* [MIGRATION] - Fixed lint

* [MIGRATION] - Fixed package version

* Rebased with lastest changes

* [MIGRATION] - check to update the script

* [MIGRATION] - rebased after the move of AlfrescoApiService

* [MIGRATION] - fixed schematics build

* [MIGRATION] - the lesson is : do not change what is already working

* Rebased to latestp

* Fixes after CR (#10202)

* Fixed white background issue in sidenav after ng16 upgrade (#10207)

* [MIGRATION] fix header background color not being read from input prop

* Fixed build

* Rebased

* Fix package version after release

* Thanks apollo deps

* custom theme missing sidenav color

* fix filter subscript overlapping dropdown items

* [ACS-8749] View More tags button no longer shows when all tags are removed from a node (#10285)

* [ACS-8741] Sidenav text for Process and Task filters is now grey (#10284)

* AAE-26037 Moved permissions role selector styles to a dedicated file (#10297)

* Removed fallback and starting using simple token

* Removed fallback and starting using simple token

* Fixed related unit test

* Fixed related unit test

* Writing should use the same calss as reading

* Fixed unit tests for insights

* Fixed unit tests for insights

* Added fallback for JWT token

* Added fallback for JWT token

* Auto import fix

* Added fallback for injection

* Added fallback for injection

* Trying to fix JWT token issue

* Fixed unit tests

* Fixed unit tests

* Fixed style for collaborators

* fixed permission row height

* AAE-26163 Fix infinite loop when authentication error event occured (#10272)

* AAE-26163 Logout user after 3 login attempts failed, avoiding infinite loop when an authentication error occured, like when a user machine clock is significantly out of sync

* AAE-26163 Wait to discovery document to be loaded and user not authenticated to perform a ssoLogin, logout user if login fails after 3 attempts

* AAE-26163 Fix missed id_token_hint invoking logout when a login error occured due to a clock significantly out of sync

* AAE-26163 Add fake observable to unit test

* AAE-26163 Show oauth event logs if showDebugInformation is enabled, remove auth items if access token is not valid

* AAE-26163 Improve tryLogin error message

* AAE-26163 Check if token has expired to fix case when user access the application after the token is expired and with a clock significantly out of sync

* AAE-26163 Test logout when clock is out of sync

* AAE-26163 Create a service to check if local machine time is out of sync

* AAE-26163 Update oauthErrorEvent$ and combinedOAuthErrorsStream$ to return errors

* AAE-26163 Output error within combined oauth error event subscription

* AAE-26163 Fix lint problems

* AAE-26163 Logout user when token refresh error happens for the second time, if the token is not refreshed properly after first refresh error

* AAE-26163 Logout user once an oauth error event occur due to clock out of sync

* AAE-26163 Fix retry login error message if the OAuthErrorEvent doesn t return reason

* AAE-26163 Fix the issue where the logout API call is canceled by the authorize call when login fails due to clock synchronization problems, causing an infinite loop.

* remove console.log

* AAE-26163 Fix retry login error message if the OAuthErrorEvent reason is an empty object

* Updating dependencies

* Fixed subject complete to avoid calling a reset event when complete

---------

Co-authored-by: Wojciech Duda <69160975+wojd0@users.noreply.github.com>
Co-authored-by: dominikiwanekhyland <141320833+dominikiwanekhyland@users.noreply.github.com>
Co-authored-by: swapnil-verma-gl <92505353+swapnil-verma-gl@users.noreply.github.com>
Co-authored-by: Ehsan Rezaei <ehsan.rezaei@hyland.com>
Co-authored-by: Amedeo Lepore <amedeo.lepore@hyland.com>
This commit is contained in:
Vito Albano
2024-10-23 15:23:38 +01:00
committed by GitHub
parent 0a89d9be97
commit 41391a0bb9
91 changed files with 13720 additions and 13462 deletions

View File

@@ -28,6 +28,7 @@ import { EMPTY, of } from 'rxjs';
import { OidcAuthenticationService } from '../oidc/oidc-authentication.service';
import { NoopTranslateModule } from '../../testing/noop-translate.module';
describe('AuthGuardService ECM', () => {
let authGuard: Promise<boolean>;
let authService: AuthenticationService;

View File

@@ -21,6 +21,7 @@ import { AuthGuardSsoRoleService } from './auth-guard-sso-role.service';
import { JwtHelperService } from '../services/jwt-helper.service';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { NoopTranslateModule } from '../../testing/noop-translate.module';
import { AuthModule } from '../oidc/auth.module';
describe('Auth Guard SSO role service', () => {
let jwtHelperService: JwtHelperService;
@@ -29,7 +30,7 @@ describe('Auth Guard SSO role service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopTranslateModule, MatDialogModule]
imports: [NoopTranslateModule, MatDialogModule, AuthModule.forRoot({ useHash: true })]
});
localStorage.clear();
jwtHelperService = TestBed.inject(JwtHelperService);

View File

@@ -28,6 +28,7 @@ import { EMPTY, of } from 'rxjs';
import { MatDialogModule } from '@angular/material/dialog';
import { RouterTestingModule } from '@angular/router/testing';
import { NoopTranslateModule } from '../../testing/noop-translate.module';
import { NoopAuthModule } from '../../testing';
describe('AuthGuardService', () => {
let state: RouterStateSnapshot;
@@ -42,11 +43,10 @@ describe('AuthGuardService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopTranslateModule, MatDialogModule, RouterTestingModule],
imports: [NoopTranslateModule, MatDialogModule, RouterTestingModule, NoopAuthModule],
providers: [
AppConfigService,
StorageService,
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } },
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of(), init: () => {} } },
{
provide: OidcAuthenticationService,
useValue: {

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
import { APP_INITIALIZER, inject, ModuleWithProviders, NgModule, InjectionToken } from '@angular/core';
import { AUTH_CONFIG, OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
import { AuthenticationService } from '../services/authentication.service';
import { StorageService } from '../../common/services/storage.service';
import { AuthModuleConfig, AUTH_MODULE_CONFIG } from './auth-config';
import { authConfigFactory, AuthConfigService } from './auth-config.service';
import { AuthRoutingModule } from './auth-routing.module';
@@ -27,6 +26,12 @@ import { RedirectAuthService } from './redirect-auth.service';
import { AuthenticationConfirmationComponent } from './view/authentication-confirmation/authentication-confirmation.component';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { TokenInterceptor } from './token.interceptor';
import { StorageService } from '../../common/services/storage.service';
export const JWT_STORAGE_SERVICE = new InjectionToken<OAuthStorage>('JWT_STORAGE_SERVICE', {
providedIn: 'root',
factory: () => inject(StorageService)
});
/**
* Create a Login Factory function
@@ -38,11 +43,18 @@ export function loginFactory(redirectService: RedirectAuthService): () => Promis
return () => redirectService.init();
}
/**
* @returns current instance of OAuthStorage
*/
export function oauthStorageFactory(): OAuthStorage {
return inject(JWT_STORAGE_SERVICE);
}
@NgModule({
declarations: [AuthenticationConfirmationComponent],
imports: [AuthRoutingModule, OAuthModule.forRoot()],
providers: [
{ provide: OAuthStorage, useExisting: StorageService },
{ provide: OAuthStorage, useFactory: oauthStorageFactory },
{ provide: AuthenticationService },
{
provide: AUTH_CONFIG,

View File

@@ -35,6 +35,7 @@ import { IdentityRoleModel } from '../models/identity-role.model';
import { AdfHttpClient } from '../../../../api/src';
import { StorageService } from '../../common/services/storage.service';
import { NoopTranslateModule } from '../../testing/noop-translate.module';
import { OAuthStorage } from 'angular-oauth2-oidc';
describe('IdentityUserService', () => {
const mockRoles = [
@@ -53,7 +54,7 @@ describe('IdentityUserService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopTranslateModule],
providers: [StorageService, AdfHttpClient]
providers: [AdfHttpClient, { provide: OAuthStorage, useClass: StorageService }]
});
storageService = TestBed.inject(StorageService);
service = TestBed.inject(IdentityUserService);

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { JWT_STORAGE_SERVICE, JwtHelperService } from './jwt-helper.service';
import { JwtHelperService } from './jwt-helper.service';
import { mockToken } from '../mock/jwt-helper.service.spec';
import { TestBed } from '@angular/core/testing';
import { StorageService } from '../../common';
@@ -42,7 +42,7 @@ describe('JwtHelperService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [JwtHelperService, { provide: StorageService, useValue: mockStorage }]
providers: [JwtHelperService, { provide: OAuthStorage, useValue: mockStorage }]
});
jwtHelperService = TestBed.inject(JwtHelperService);
});
@@ -140,15 +140,11 @@ describe('JwtHelperService with custom storage service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
JwtHelperService,
{ provide: StorageService, useValue: mockStorage },
{ provide: JWT_STORAGE_SERVICE, useValue: mockCustomStorage }
]
providers: [JwtHelperService, { provide: StorageService, useValue: mockStorage }, { provide: OAuthStorage, useValue: mockCustomStorage }]
});
jwtHelperService = TestBed.inject(JwtHelperService);
defaultStorage = TestBed.inject(StorageService);
customStorage = TestBed.inject(JWT_STORAGE_SERVICE);
customStorage = TestBed.inject(OAuthStorage);
});
it('should use the custom storage service', () => {

View File

@@ -15,14 +15,8 @@
* limitations under the License.
*/
import { inject, Injectable, InjectionToken } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { OAuthStorage } from 'angular-oauth2-oidc';
import { StorageService } from '../../common/services/storage.service';
export const JWT_STORAGE_SERVICE = new InjectionToken<OAuthStorage>('JWT_STORAGE_SERVICE', {
providedIn: 'root',
factory: () => inject(StorageService)
});
@Injectable({
providedIn: 'root'
@@ -39,7 +33,7 @@ export class JwtHelperService {
static USER_PREFERRED_USERNAME = 'preferred_username';
static HXP_AUTHORIZATION = 'hxp_authorization';
private storageService: OAuthStorage = inject(JWT_STORAGE_SERVICE);
private storageService: OAuthStorage = inject(OAuthStorage)
/**
* Decodes a JSON web token into a JS object.

View File

@@ -20,6 +20,8 @@ import { UserAccessService } from './user-access.service';
import { JwtHelperService } from './jwt-helper.service';
import { AppConfigService } from '../../app-config';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AuthModule, JWT_STORAGE_SERVICE } from '../oidc/auth.module';
import { StorageService } from '../../common/services/storage.service';
describe('UserAccessService', () => {
let userAccessService: UserAccessService;
@@ -28,8 +30,8 @@ describe('UserAccessService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [UserAccessService]
imports: [HttpClientTestingModule, AuthModule.forRoot({ useHash: true })],
providers: [{ provide: JWT_STORAGE_SERVICE, useClass: StorageService }, UserAccessService]
});
userAccessService = TestBed.inject(UserAccessService);
jwtHelperService = TestBed.inject(JwtHelperService);

View File

@@ -1,6 +1,6 @@
<div class="adf-select-filter-input-container">
<mat-form-field>
<mat-form-field subscriptSizing="dynamic">
<input matInput
autocomplete="off"
(keydown)="handleKeydown($event)"

View File

@@ -53,7 +53,9 @@ export class ClipboardService {
this.document.execCommand('copy');
}
this.notify(message);
} catch {}
} catch {
/* empty */
}
}
}
@@ -76,7 +78,9 @@ export class ClipboardService {
document.execCommand('copy');
}
this.notify(message);
} catch {}
} catch {
/* empty */
}
}
private notify(message) {

View File

@@ -29,7 +29,7 @@ import { Subject } from 'rxjs';
providedIn: 'root'
})
export class LogService {
get currentLogLevel() {
get currentLogLevel(): number {
const configLevel: string = this.appConfig.get<string>(AppConfigValues.LOG_LEVEL);
if (configLevel) {
@@ -171,7 +171,7 @@ export class LogService {
* @param level Level name
* @returns Numeric log level
*/
getLogLevel(level: string): LogLevelsEnum {
getLogLevel(level: string): number {
const referencedLevel = logLevels.find((currentLevel: any) => currentLevel.name.toLocaleLowerCase() === level.toLocaleLowerCase());
return referencedLevel ? referencedLevel.level : 5;

View File

@@ -22,36 +22,38 @@ export interface FileInfo {
}
export class FileUtils {
static flatten(folder: any): Promise<FileInfo[]> {
const reader = folder.createReader();
const files: FileInfo[] = [];
return new Promise((resolve) => {
const iterations = [];
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
(function traverse() {
reader.readEntries((entries) => {
if (!entries.length) {
Promise.all(iterations).then(() => resolve(files));
} else {
iterations.push(Promise.all(entries.map((entry) => {
if (entry.isFile) {
return new Promise<void>((resolveFile) => {
entry.file((file: File) => {
files.push({
entry,
file,
relativeFolder: entry.fullPath.replace(/\/[^/]*$/, '')
iterations.push(
Promise.all(
entries.map((entry) => {
if (entry.isFile) {
return new Promise<void>((resolveFile) => {
entry.file((file: File) => {
files.push({
entry,
file,
relativeFolder: entry.fullPath.replace(/\/[^/]*$/, '')
});
resolveFile();
});
});
resolveFile();
});
});
} else {
return FileUtils.flatten(entry).then((result) => {
files.push(...result);
});
}
})));
} else {
return FileUtils.flatten(entry).then((result) => {
files.push(...result);
});
}
})
)
);
// Try calling traverse() again for the same dir, according to spec
traverse();
}

View File

@@ -26,7 +26,7 @@
<button
data-automation-id="adf-dynamic-chip-list-view-more-button"
mat-button
[hidden]="!limitChipsDisplayed"
[hidden]="chipsToDisplay.length === 0 || !limitChipsDisplayed"
[style.left.px]="viewMoreButtonLeftOffset"
[style.top.px]="viewMoreButtonTop"
class="adf-dynamic-chip-list-view-more-button"

View File

@@ -182,7 +182,7 @@ describe('DynamicChipListComponent', () => {
element.style.maxWidth = '309px';
});
afterEach(() =>{
afterEach(() => {
fixture.destroy();
});
@@ -317,5 +317,15 @@ describe('DynamicChipListComponent', () => {
fixture.detectChanges();
expect(viewMoreButton.hidden).toBeTrue();
}));
it('should not render View more button if there are no chips', fakeAsync(() => {
renderChips();
component.chips = [];
tick();
fixture.detectChanges();
expect(component.chipsToDisplay).toEqual([]);
expect(findViewMoreButton().hidden).toBeTrue();
}));
});
});

View File

@@ -2,7 +2,6 @@
adf-layout-header .adf-toolbar-container-row {
color: var(--theme-header-text-color);
background-color: var(--theme-primary-color);
position: relative;
padding: 0 24px;

View File

@@ -5,6 +5,13 @@ adf-layout-container {
width: 100%;
height: 100%;
overflow: hidden;
.adf-layout-container-sidenav {
overflow: hidden;
border-right: 1px solid var(--adf-theme-foreground-text-color-007);
background-color: var(--theme-background-color);
color: var(--adf-theme-foreground-text-color);
}
}
.adf-container-full-width {
@@ -26,13 +33,7 @@ adf-layout-container {
overflow: hidden;
}
.adf-layout-container-sidenav {
overflow: hidden;
border-right: 1px solid var(--adf-theme-foreground-text-color-007);
background-color: var(--theme-background-color);
}
/* stylelint-disable selector-class-pattern */
/* stylelint-disable selector-class-pattern, declaration-no-important */
#{$mat-sidenav-content},
#{$mat-drawer-transition} #{$mat-drawer-content} {
margin-left: 0 !important;

View File

@@ -1,6 +1,7 @@
<div (keyup)="onKeyPress($event)" tabindex="-1" role="button" class="adf-notification-history-container">
<button mat-button
[matMenuTriggerFor]="menu"
aria-hidden="false"
[attr.aria-label]="'NOTIFICATIONS.OPEN_HISTORY' | translate"
title="{{ 'NOTIFICATIONS.OPEN_HISTORY' | translate }}"
class="adf-notification-history-menu_button"

View File

@@ -166,9 +166,12 @@ export class SearchTextInputComponent implements OnInit, OnDestroy {
private toggleSearch = new Subject<any>();
private focusSubscription: Subscription;
private valueChange = new Subject<string>();
private toggleSubscription: Subscription;
toggle$ = this.toggleSearch.asObservable();
constructor(private userPreferencesService: UserPreferencesService) {
this.toggleSearch.pipe(debounceTime(200), takeUntil(this.onDestroy$)).subscribe(() => {
this.toggleSubscription = this.toggle$.pipe(debounceTime(200), takeUntil(this.onDestroy$)).subscribe(() => {
if (this.expandable) {
this.subscriptAnimationState = this.toggleAnimation();
if (this.subscriptAnimationState.value === 'inactive') {
@@ -302,6 +305,7 @@ export class SearchTextInputComponent implements OnInit, OnDestroy {
ngOnDestroy() {
if (this.toggleSearch) {
this.toggleSubscription.unsubscribe();
this.toggleSearch.complete();
this.toggleSearch = null;
}

View File

@@ -16,7 +16,7 @@
*/
import { APP_INITIALIZER, Injectable, NgModule } from '@angular/core';
import { AuthModule, RedirectAuthService } from '../auth';
import { AuthModule, JWT_STORAGE_SERVICE, RedirectAuthService } from '../auth';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppConfigService, StoragePrefixFactory } from '../app-config';
@@ -47,7 +47,8 @@ export class NoopRedirectAuthService extends RedirectAuthService {
useFactory: loadAppConfig,
deps: [AppConfigService, StorageService, AdfHttpClient, StoragePrefixFactory],
multi: true
}
},
{ provide: JWT_STORAGE_SERVICE, useClass: StorageService }
]
})
export class NoopAuthModule {}

View File

@@ -20,7 +20,7 @@ import { TranslateLoaderService } from './translate-loader.service';
import { TranslationService } from './translation.service';
import { TranslateModule } from '@ngx-translate/core';
import { CoreModule } from '../core.module';
import { AuthModule } from '../auth';
import { AuthModule } from '../auth/oidc/auth.module';
declare let jasmine: any;
@@ -30,14 +30,8 @@ describe('TranslateLoader', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
AuthModule.forRoot({ useHash: true }),
TranslateModule.forRoot(),
CoreModule.forRoot()
],
providers: [
TranslationService
]
imports: [AuthModule.forRoot({ useHash: true }), TranslateModule.forRoot(), CoreModule.forRoot()],
providers: [TranslationService]
});
translationService = TestBed.inject(TranslationService);
customLoader = translationService.translate.currentLoader as TranslateLoaderService;