[CST-15074] Fixes cyclic dependency issue

This commit is contained in:
Vincenzo Mecca
2025-03-23 22:33:27 +01:00
parent c1b951b18c
commit 1316540765
15 changed files with 302 additions and 53 deletions

View File

@@ -0,0 +1,133 @@
import { TestBed } from '@angular/core/testing';
import {
Store,
StoreModule,
} from '@ngrx/store';
import {
MockStore,
provideMockStore,
} from '@ngrx/store/testing';
import { storeModuleConfig } from '../../app.reducer';
import { AuthMethodTypeComponent } from '../../shared/log-in/methods/auth-methods.type';
import { authReducer } from './auth.reducer';
import { AuthMethodsService } from './auth-methods.service';
import { AuthMethod } from './models/auth.method';
import { AuthMethodType } from './models/auth.method-type';
describe('AuthMethodsService', () => {
let service: AuthMethodsService;
let store: MockStore;
let mockAuthMethods: Map<AuthMethodType, AuthMethodTypeComponent>;
let mockAuthMethodsArray: AuthMethod[] = [
{ id: 'password', authMethodType: AuthMethodType.Password, position: 2 } as AuthMethod,
{ id: 'shibboleth', authMethodType: AuthMethodType.Shibboleth, position: 1 } as AuthMethod,
{ id: 'oidc', authMethodType: AuthMethodType.Oidc, position: 3 } as AuthMethod,
{ id: 'ip', authMethodType: AuthMethodType.Ip, position: 4 } as AuthMethod,
];
const initialState = {
core: {
auth: {
authMethods: mockAuthMethodsArray,
},
},
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot(authReducer, storeModuleConfig),
],
providers: [
AuthMethodsService,
provideMockStore({ initialState }),
],
});
service = TestBed.inject(AuthMethodsService);
store = TestBed.inject(Store) as MockStore;
// Setup mock auth methods map
mockAuthMethods = new Map<AuthMethodType, AuthMethodTypeComponent>();
mockAuthMethods.set(AuthMethodType.Password, {} as AuthMethodTypeComponent);
mockAuthMethods.set(AuthMethodType.Shibboleth, {} as AuthMethodTypeComponent);
mockAuthMethods.set(AuthMethodType.Oidc, {} as AuthMethodTypeComponent);
mockAuthMethods.set(AuthMethodType.Ip, {} as AuthMethodTypeComponent);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('getAuthMethods', () => {
it('should return auth methods sorted by position', () => {
// Expected result after sorting and filtering IP auth
const expected = [
{ id: 'shibboleth', authMethodType: AuthMethodType.Shibboleth, position: 1 },
{ id: 'password', authMethodType: AuthMethodType.Password, position: 2 },
{ id: 'oidc', authMethodType: AuthMethodType.Oidc, position: 3 },
];
service.getAuthMethods(mockAuthMethods).subscribe(result => {
expect(result.length).toBe(3);
expect(result).toEqual(expected);
});
});
it('should exclude specified auth method type', () => {
// Expected result after excluding Password auth and filtering IP auth
const expected = [
{ id: 'shibboleth', authMethodType: AuthMethodType.Shibboleth, position: 1 },
{ id: 'oidc', authMethodType: AuthMethodType.Oidc, position: 3 },
];
service.getAuthMethods(mockAuthMethods, AuthMethodType.Password).subscribe(result => {
expect(result.length).toBe(2);
expect(result).toEqual(expected);
});
});
it('should always filter out IP authentication method', () => {
// Add IP auth to the mock methods map
mockAuthMethods.set(AuthMethodType.Ip, {} as AuthMethodTypeComponent);
service.getAuthMethods(mockAuthMethods).subscribe(result => {
expect(result.length).toBe(3);
expect(result.find(method => method.authMethodType === AuthMethodType.Ip)).toBeUndefined();
});
});
it('should handle empty auth methods array', () => {
const authMethods = new Map<AuthMethodType, AuthMethodTypeComponent>();
service.getAuthMethods(authMethods).subscribe(result => {
expect(result.length).toBe(0);
expect(result).toEqual([]);
});
});
it('should handle duplicate auth method types and keep only unique ones', () => {
// Arrange
const duplicateMethodsArray = [
...mockAuthMethodsArray,
{ id: 'password2', authMethodType: AuthMethodType.Password, position: 5 } as AuthMethod,
];
service.getAuthMethods(mockAuthMethods).subscribe(result => {
expect(result.length).toBe(3);
// Check that we only have one Password auth method
const passwordMethods = result.filter(method => method.authMethodType === AuthMethodType.Password);
expect(passwordMethods.length).toBe(1);
});
});
});
});

View File

@@ -0,0 +1,51 @@
import { Injectable } from '@angular/core';
import {
select,
Store,
} from '@ngrx/store';
import uniqBy from 'lodash/uniqBy';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AppState } from '../../app.reducer';
import { AuthMethodTypeComponent } from '../../shared/log-in/methods/auth-methods.type';
import { rendersAuthMethodType } from '../../shared/log-in/methods/log-in.methods-decorator.utils';
import { AuthMethod } from './models/auth.method';
import { AuthMethodType } from './models/auth.method-type';
import { getAuthenticationMethods } from './selectors';
@Injectable({
providedIn: 'root',
})
/**
* Service responsible for managing and filtering authentication methods.
* Provides methods to retrieve and process authentication methods from the application store.
*/
export class AuthMethodsService {
constructor(protected store: Store<AppState>) {
}
/**
* Retrieves and processes authentication methods from the store.
*
* @param authMethods A map of authentication method types to their corresponding components
* @param excludedAuthMethod Optional authentication method type to exclude from the results
* @returns An Observable of filtered and sorted authentication methods
*/
public getAuthMethods(
authMethods: Map<AuthMethodType, AuthMethodTypeComponent>,
excludedAuthMethod?: AuthMethodType,
): Observable<AuthMethod[]> {
return this.store.pipe(
select(getAuthenticationMethods),
map((methods: AuthMethod[]) => methods
// ignore the given auth method if it should be excluded
.filter((authMethod: AuthMethod) => excludedAuthMethod == null || authMethod.authMethodType !== excludedAuthMethod)
.filter((authMethod: AuthMethod) => rendersAuthMethodType(authMethods, authMethod.authMethodType) !== undefined)
.sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position),
),
// ignore the ip authentication method when it's returned by the backend
map((methods: AuthMethod[]) => uniqBy(methods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType')),
);
}
}

View File

@@ -11,7 +11,6 @@ import {
} from '@ngrx/store'; } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { CookieAttributes } from 'js-cookie'; import { CookieAttributes } from 'js-cookie';
import uniqBy from 'lodash/uniqBy';
import { import {
Observable, Observable,
of as observableOf, of as observableOf,
@@ -39,7 +38,6 @@ import {
isNotNull, isNotNull,
isNotUndefined, isNotUndefined,
} from '../../shared/empty.util'; } from '../../shared/empty.util';
import { rendersAuthMethodType } from '../../shared/log-in/methods/log-in.methods-decorator';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
import { followLink } from '../../shared/utils/follow-link-config.model'; import { followLink } from '../../shared/utils/follow-link-config.model';
@@ -76,7 +74,6 @@ import {
} from './auth.actions'; } from './auth.actions';
import { AuthRequestService } from './auth-request.service'; import { AuthRequestService } from './auth-request.service';
import { AuthMethod } from './models/auth.method'; import { AuthMethod } from './models/auth.method';
import { AuthMethodType } from './models/auth.method-type';
import { AuthStatus } from './models/auth-status.model'; import { AuthStatus } from './models/auth-status.model';
import { import {
AuthTokenInfo, AuthTokenInfo,
@@ -84,7 +81,6 @@ import {
} from './models/auth-token-info.model'; } from './models/auth-token-info.model';
import { import {
getAuthenticatedUserId, getAuthenticatedUserId,
getAuthenticationMethods,
getAuthenticationToken, getAuthenticationToken,
getExternalAuthCookieStatus, getExternalAuthCookieStatus,
getRedirectUrl, getRedirectUrl,
@@ -693,19 +689,4 @@ export class AuthService {
this.store.dispatch(new UnsetUserAsIdleAction()); this.store.dispatch(new UnsetUserAsIdleAction());
} }
} }
public getAuthMethods(excludedAuthMethod?: AuthMethodType): Observable<AuthMethod[]> {
return this.store.pipe(
select(getAuthenticationMethods),
map((methods: AuthMethod[]) => methods
// ignore the given auth method if it should be excluded
.filter((authMethod: AuthMethod) => excludedAuthMethod == null || authMethod.authMethodType !== excludedAuthMethod)
.filter((authMethod: AuthMethod) => rendersAuthMethodType(authMethod.authMethodType) !== undefined)
.sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position),
),
// ignore the ip authentication method when it's returned by the backend
map((authMethods: AuthMethod[]) => uniqBy(authMethods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType')),
);
}
} }

View File

@@ -22,7 +22,7 @@
<h4 class="mt-2">{{ 'external-login.component.or' | translate }}</h4> <h4 class="mt-2">{{ 'external-login.component.or' | translate }}</h4>
</div> </div>
<div class="col d-flex justify-content-center align-items-center"> <div class="col d-flex justify-content-center align-items-center">
<button class="btn block btn-lg btn-primary" (click)="openLoginModal(loginModal)"> <button data-test="open-modal" class="btn block btn-lg btn-primary" (click)="openLoginModal(loginModal)">
{{ 'external-login.connect-to-existing-account.label' | translate }} {{ 'external-login.connect-to-existing-account.label' | translate }}
</button> </button>
</div> </div>

View File

@@ -8,16 +8,24 @@ import { FormBuilder } from '@angular/forms';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { StoreModule } from '@ngrx/store';
import { provideMockStore } from '@ngrx/store/testing';
import { import {
TranslateModule, TranslateModule,
TranslateService, TranslateService,
} from '@ngx-translate/core'; } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { storeModuleConfig } from '../../app.reducer';
import { authReducer } from '../../core/auth/auth.reducer';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';
import { AuthMethodsService } from '../../core/auth/auth-methods.service';
import { AuthMethod } from '../../core/auth/models/auth.method';
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type'; import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
import { MetadataValue } from '../../core/shared/metadata.models'; import { MetadataValue } from '../../core/shared/metadata.models';
import { Registration } from '../../core/shared/registration.model'; import { Registration } from '../../core/shared/registration.model';
import { AuthMethodTypeComponent } from '../../shared/log-in/methods/auth-methods.type';
import { AuthServiceMock } from '../../shared/mocks/auth.service.mock'; import { AuthServiceMock } from '../../shared/mocks/auth.service.mock';
import { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe'; import { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe';
import { ConfirmEmailComponent } from '../email-confirmation/confirm-email/confirm-email.component'; import { ConfirmEmailComponent } from '../email-confirmation/confirm-email/confirm-email.component';
@@ -28,6 +36,22 @@ describe('ExternalLogInComponent', () => {
let component: ExternalLogInComponent; let component: ExternalLogInComponent;
let fixture: ComponentFixture<ExternalLogInComponent>; let fixture: ComponentFixture<ExternalLogInComponent>;
let modalService: NgbModal = jasmine.createSpyObj('modalService', ['open']); let modalService: NgbModal = jasmine.createSpyObj('modalService', ['open']);
let authServiceStub: jasmine.SpyObj<AuthService>;
let authMethodsServiceStub: jasmine.SpyObj<AuthMethodsService>;
let mockAuthMethodsArray: AuthMethod[] = [
{ id: 'password', authMethodType: AuthMethodType.Password, position: 2 } as AuthMethod,
{ id: 'shibboleth', authMethodType: AuthMethodType.Shibboleth, position: 1 } as AuthMethod,
{ id: 'oidc', authMethodType: AuthMethodType.Oidc, position: 3 } as AuthMethod,
{ id: 'ip', authMethodType: AuthMethodType.Ip, position: 4 } as AuthMethod,
];
const initialState = {
core: {
auth: {
authMethods: mockAuthMethodsArray,
},
},
};
const registrationDataMock = { const registrationDataMock = {
id: '3', id: '3',
@@ -55,14 +79,26 @@ describe('ExternalLogInComponent', () => {
onDefaultLangChange: new EventEmitter(), onDefaultLangChange: new EventEmitter(),
}; };
beforeEach(() => beforeEach(async () => {
TestBed.configureTestingModule({ authServiceStub = jasmine.createSpyObj('AuthService', ['getAuthenticationMethods']);
imports: [CommonModule, TranslateModule.forRoot({}), BrowserOnlyPipe, ExternalLogInComponent, OrcidConfirmationComponent, BrowserAnimationsModule], authMethodsServiceStub = jasmine.createSpyObj('AuthMethodsService', ['getAuthMethods']);
await TestBed.configureTestingModule({
imports: [
CommonModule,
TranslateModule.forRoot({}),
BrowserOnlyPipe,
ExternalLogInComponent,
OrcidConfirmationComponent,
BrowserAnimationsModule,
StoreModule.forRoot(authReducer, storeModuleConfig),
],
providers: [ providers: [
{ provide: TranslateService, useValue: translateServiceStub }, { provide: TranslateService, useValue: translateServiceStub },
{ provide: AuthService, useValue: new AuthServiceMock() }, { provide: AuthService, useValue: new AuthServiceMock() },
{ provide: NgbModal, useValue: modalService }, { provide: NgbModal, useValue: modalService },
FormBuilder, FormBuilder,
provideMockStore({ initialState }),
], ],
}) })
.overrideComponent(ExternalLogInComponent, { .overrideComponent(ExternalLogInComponent, {
@@ -70,23 +106,31 @@ describe('ExternalLogInComponent', () => {
imports: [ConfirmEmailComponent], imports: [ConfirmEmailComponent],
}, },
}) })
.compileComponents(), .compileComponents();
); });
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ExternalLogInComponent); fixture = TestBed.createComponent(ExternalLogInComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
component.registrationData = Object.assign(new Registration(), registrationDataMock); component.registrationData = Object.assign(new Registration(), registrationDataMock);
component.registrationType = registrationDataMock.registrationType; component.registrationType = registrationDataMock.registrationType;
let mockAuthMethods = new Map<AuthMethodType, AuthMethodTypeComponent>();
mockAuthMethods.set(AuthMethodType.Password, {} as AuthMethodTypeComponent);
mockAuthMethods.set(AuthMethodType.Shibboleth, {} as AuthMethodTypeComponent);
mockAuthMethods.set(AuthMethodType.Oidc, {} as AuthMethodTypeComponent);
mockAuthMethods.set(AuthMethodType.Ip, {} as AuthMethodTypeComponent);
component.authMethods = mockAuthMethods;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
fixture.detectChanges();
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
beforeEach(() => { beforeEach(() => {
component.registrationData = Object.assign(new Registration(), registrationDataMock, { email: 'user@institution.edu' }); component.registrationData = Object.assign(new Registration(), registrationDataMock, { email: 'user@institution.edu' });
fixture.detectChanges(); fixture.detectChanges();
}); });
@@ -103,8 +147,11 @@ describe('ExternalLogInComponent', () => {
}); });
it('should display login modal when connect to existing account button is clicked', () => { it('should display login modal when connect to existing account button is clicked', () => {
const button = fixture.nativeElement.querySelector('button.btn-primary'); const button = fixture.debugElement.query(By.css('[data-test="open-modal"]'));
button.click();
expect(button).not.toBeNull('Connect to existing account button should be in the DOM');
button.nativeElement.click();
expect(modalService.open).toHaveBeenCalled(); expect(modalService.open).toHaveBeenCalled();
}); });

View File

@@ -22,6 +22,7 @@ import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';
import { AuthMethodsService } from '../../core/auth/auth-methods.service';
import { AuthMethodType } from '../../core/auth/models/auth.method-type'; import { AuthMethodType } from '../../core/auth/models/auth.method-type';
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type'; import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
import { Registration } from '../../core/shared/registration.model'; import { Registration } from '../../core/shared/registration.model';
@@ -31,6 +32,7 @@ import {
hasValue, hasValue,
isEmpty, isEmpty,
} from '../../shared/empty.util'; } from '../../shared/empty.util';
import { AuthMethodTypeComponent } from '../../shared/log-in/methods/auth-methods.type';
import { ThemedLogInComponent } from '../../shared/log-in/themed-log-in.component'; import { ThemedLogInComponent } from '../../shared/log-in/themed-log-in.component';
import { import {
ExternalLoginTypeComponent, ExternalLoginTypeComponent,
@@ -78,6 +80,11 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
* @memberof ExternalLogInComponent * @memberof ExternalLogInComponent
*/ */
@Input() token: string; @Input() token: string;
/**
* The authMethods taken from the configuration
* @memberof ExternalLogInComponent
*/
@Input() authMethods: Map<AuthMethodType, AuthMethodTypeComponent>;
/** /**
* The information text to be displayed, * The information text to be displayed,
* depending on the registration type and the presence of an email * depending on the registration type and the presence of an email
@@ -109,6 +116,7 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
private translate: TranslateService, private translate: TranslateService,
private modalService: NgbModal, private modalService: NgbModal,
private authService: AuthService, private authService: AuthService,
private authMethodsService: AuthMethodsService,
) { ) {
} }
@@ -128,11 +136,14 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
parent: this.injector, parent: this.injector,
}); });
this.registrationType = this.registrationData?.registrationType ?? null; this.registrationType = this.registrationData?.registrationType ?? null;
this.relatedAuthMethod = isEmpty(this.registrationType) ? null : this.registrationType.replace('VALIDATION_', '').toLocaleLowerCase() as AuthMethodType; this.relatedAuthMethod = isEmpty(this.registrationType) ? null :
this.registrationType.replace('VALIDATION_', '').toLocaleLowerCase() as AuthMethodType;
this.informationText = hasValue(this.registrationData?.email) this.informationText = hasValue(this.registrationData?.email)
? this.generateInformationTextWhenEmail(this.registrationType) ? this.generateInformationTextWhenEmail(this.registrationType)
: this.generateInformationTextWhenNOEmail(this.registrationType); : this.generateInformationTextWhenNOEmail(this.registrationType);
this.hasAuthMethodTypes = this.authService.getAuthMethods(this.relatedAuthMethod).pipe(map(methods => methods.length > 0)); this.hasAuthMethodTypes =
this.authMethodsService.getAuthMethods(this.authMethods, this.relatedAuthMethod)
.pipe(map(methods => methods.length > 0));
} }
/** /**

View File

@@ -23,7 +23,7 @@ import {
} from '../../shared/remote-data.utils'; } from '../../shared/remote-data.utils';
import { registrationTokenGuard } from './registration-token-guard'; import { registrationTokenGuard } from './registration-token-guard';
fdescribe('RegistrationTokenGuard', describe('RegistrationTokenGuard',
() => { () => {
const route = new RouterMock(); const route = new RouterMock();
const registrationWithGroups = Object.assign(new Registration(), const registrationWithGroups = Object.assign(new Registration(),

View File

@@ -1,6 +1,10 @@
<div class="container"> <div class="container">
@if (registrationData$ | async; as registrationData) { @if (registrationData$ | async; as registrationData) {
<ds-external-log-in [registrationData]="registrationData" [token]="token"></ds-external-log-in> <ds-external-log-in
[authMethods]="authMethods"
[registrationData]="registrationData"
[token]="token"
></ds-external-log-in>
} }
@if (hasErrors) { @if (hasErrors) {

View File

@@ -12,12 +12,15 @@ import {
tap, tap,
} from 'rxjs'; } from 'rxjs';
import { AuthMethodType } from '../core/auth/models/auth.method-type';
import { RemoteData } from '../core/data/remote-data'; import { RemoteData } from '../core/data/remote-data';
import { Registration } from '../core/shared/registration.model'; import { Registration } from '../core/shared/registration.model';
import { ExternalLogInComponent } from '../external-log-in/external-log-in/external-log-in.component'; import { ExternalLogInComponent } from '../external-log-in/external-log-in/external-log-in.component';
import { AlertComponent } from '../shared/alert/alert.component'; import { AlertComponent } from '../shared/alert/alert.component';
import { AlertType } from '../shared/alert/alert-type'; import { AlertType } from '../shared/alert/alert-type';
import { hasNoValue } from '../shared/empty.util'; import { hasNoValue } from '../shared/empty.util';
import { AuthMethodTypeComponent } from '../shared/log-in/methods/auth-methods.type';
import { AUTH_METHOD_FOR_DECORATOR_MAP } from '../shared/log-in/methods/log-in.methods-decorator';
@Component({ @Component({
templateUrl: './external-login-page.component.html', templateUrl: './external-login-page.component.html',
@@ -53,11 +56,14 @@ export class ExternalLoginPageComponent implements OnInit {
*/ */
public hasErrors = false; public hasErrors = false;
public authMethods: Map<AuthMethodType, AuthMethodTypeComponent>;
constructor( constructor(
private arouter: ActivatedRoute, private arouter: ActivatedRoute,
) { ) {
this.token = this.arouter.snapshot.params.token; this.token = this.arouter.snapshot.params.token;
this.hasErrors = hasNoValue(this.arouter.snapshot.params.token); this.hasErrors = hasNoValue(this.arouter.snapshot.params.token);
this.authMethods = AUTH_METHOD_FOR_DECORATOR_MAP;
} }
ngOnInit(): void { ngOnInit(): void {

View File

@@ -7,10 +7,9 @@ import {
} from '@angular/core'; } from '@angular/core';
import { AuthMethod } from '../../../core/auth/models/auth.method'; import { AuthMethod } from '../../../core/auth/models/auth.method';
import { import { AuthMethodTypeComponent } from '../methods/auth-methods.type';
AuthMethodTypeComponent, import { AUTH_METHOD_FOR_DECORATOR_MAP } from '../methods/log-in.methods-decorator';
rendersAuthMethodType, import { rendersAuthMethodType } from '../methods/log-in.methods-decorator.utils';
} from '../methods/log-in.methods-decorator';
/** /**
* This component represents a component container for log-in methods available. * This component represents a component container for log-in methods available.
@@ -60,7 +59,7 @@ export class LogInContainerComponent implements OnInit {
* Find the correct component based on the AuthMethod's type * Find the correct component based on the AuthMethod's type
*/ */
getAuthMethodContent(): AuthMethodTypeComponent { getAuthMethodContent(): AuthMethodTypeComponent {
return rendersAuthMethodType(this.authMethod.authMethodType); return rendersAuthMethodType(AUTH_METHOD_FOR_DECORATOR_MAP, this.authMethod.authMethodType);
} }
} }

View File

@@ -12,6 +12,7 @@ import {
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';
import { AuthMethodsService } from '../../core/auth/auth-methods.service';
import { AuthMethod } from '../../core/auth/models/auth.method'; import { AuthMethod } from '../../core/auth/models/auth.method';
import { AuthMethodType } from '../../core/auth/models/auth.method-type'; import { AuthMethodType } from '../../core/auth/models/auth.method-type';
import { import {
@@ -23,6 +24,7 @@ import { CoreState } from '../../core/core-state.model';
import { hasValue } from '../empty.util'; import { hasValue } from '../empty.util';
import { ThemedLoadingComponent } from '../loading/themed-loading.component'; import { ThemedLoadingComponent } from '../loading/themed-loading.component';
import { LogInContainerComponent } from './container/log-in-container.component'; import { LogInContainerComponent } from './container/log-in-container.component';
import { AUTH_METHOD_FOR_DECORATOR_MAP } from './methods/log-in.methods-decorator';
@Component({ @Component({
selector: 'ds-base-log-in', selector: 'ds-base-log-in',
@@ -69,11 +71,12 @@ export class LogInComponent implements OnInit {
constructor(private store: Store<CoreState>, constructor(private store: Store<CoreState>,
private authService: AuthService, private authService: AuthService,
private authMethodsService: AuthMethodsService,
) { ) {
} }
ngOnInit(): void { ngOnInit(): void {
this.authMethods = this.authService.getAuthMethods(this.excludedAuthMethod); this.authMethods = this.authMethodsService.getAuthMethods(AUTH_METHOD_FOR_DECORATOR_MAP, this.excludedAuthMethod);
// set loading // set loading
this.loading = this.store.pipe(select(isAuthenticationLoading)); this.loading = this.store.pipe(select(isAuthenticationLoading));

View File

@@ -0,0 +1,6 @@
import { LogInExternalProviderComponent } from './log-in-external-provider/log-in-external-provider.component';
import { LogInPasswordComponent } from './password/log-in-password.component';
export type AuthMethodTypeComponent =
typeof LogInPasswordComponent |
typeof LogInExternalProviderComponent;

View File

@@ -1,11 +1,8 @@
import { AuthMethodType } from '../../../core/auth/models/auth.method-type'; import { AuthMethodType } from '../../../core/auth/models/auth.method-type';
import { AuthMethodTypeComponent } from './auth-methods.type';
import { LogInExternalProviderComponent } from './log-in-external-provider/log-in-external-provider.component'; import { LogInExternalProviderComponent } from './log-in-external-provider/log-in-external-provider.component';
import { LogInPasswordComponent } from './password/log-in-password.component'; import { LogInPasswordComponent } from './password/log-in-password.component';
export type AuthMethodTypeComponent =
typeof LogInPasswordComponent |
typeof LogInExternalProviderComponent;
export const AUTH_METHOD_FOR_DECORATOR_MAP = new Map<AuthMethodType, AuthMethodTypeComponent>([ export const AUTH_METHOD_FOR_DECORATOR_MAP = new Map<AuthMethodType, AuthMethodTypeComponent>([
[AuthMethodType.Password, LogInPasswordComponent], [AuthMethodType.Password, LogInPasswordComponent],
[AuthMethodType.Shibboleth, LogInExternalProviderComponent], [AuthMethodType.Shibboleth, LogInExternalProviderComponent],
@@ -25,7 +22,3 @@ export function renderAuthMethodFor(authMethodType: AuthMethodType) {
AUTH_METHOD_FOR_DECORATOR_MAP.set(authMethodType, objectElement); AUTH_METHOD_FOR_DECORATOR_MAP.set(authMethodType, objectElement);
}; };
} }
export function rendersAuthMethodType(authMethodType: AuthMethodType) {
return AUTH_METHOD_FOR_DECORATOR_MAP.get(authMethodType);
}

View File

@@ -0,0 +1,15 @@
import { AuthMethodType } from '../../../core/auth/models/auth.method-type';
import { AuthMethodTypeComponent } from './auth-methods.type';
/**
* Retrieves the authentication method component for a specific authentication method type.
* @param authMethods A map of authentication method types to their corresponding components
* @param authMethodType The specific authentication method type to retrieve
* @returns The component associated with the given authentication method type, or undefined if not found
*/
export function rendersAuthMethodType(
authMethods: Map<AuthMethodType, AuthMethodTypeComponent>,
authMethodType: AuthMethodType,
) {
return authMethods.get(authMethodType);
}