diff --git a/src/app/core/auth/auth-methods.service.spec.ts b/src/app/core/auth/auth-methods.service.spec.ts new file mode 100644 index 0000000000..a0acdc1b16 --- /dev/null +++ b/src/app/core/auth/auth-methods.service.spec.ts @@ -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; + 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(); + 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(); + + + 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); + }); + }); + }); +}); diff --git a/src/app/core/auth/auth-methods.service.ts b/src/app/core/auth/auth-methods.service.ts new file mode 100644 index 0000000000..ad1f2358e0 --- /dev/null +++ b/src/app/core/auth/auth-methods.service.ts @@ -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) { + } + + /** + * 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, + excludedAuthMethod?: AuthMethodType, + ): Observable { + 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')), + ); + } +} diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 3f51499421..e761eb83ae 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -11,7 +11,6 @@ import { } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { CookieAttributes } from 'js-cookie'; -import uniqBy from 'lodash/uniqBy'; import { Observable, of as observableOf, @@ -39,7 +38,6 @@ import { isNotNull, isNotUndefined, } from '../../shared/empty.util'; -import { rendersAuthMethodType } from '../../shared/log-in/methods/log-in.methods-decorator'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { followLink } from '../../shared/utils/follow-link-config.model'; @@ -76,7 +74,6 @@ import { } from './auth.actions'; import { AuthRequestService } from './auth-request.service'; import { AuthMethod } from './models/auth.method'; -import { AuthMethodType } from './models/auth.method-type'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo, @@ -84,7 +81,6 @@ import { } from './models/auth-token-info.model'; import { getAuthenticatedUserId, - getAuthenticationMethods, getAuthenticationToken, getExternalAuthCookieStatus, getRedirectUrl, @@ -283,7 +279,7 @@ export class AuthService { if (status.hasSucceeded) { return status.payload.specialGroups; } else { - return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(),[])); + return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); } }), ); @@ -591,7 +587,7 @@ export class AuthService { * @param location - The location. * @returns The external server redirect URL. */ - getExternalServerRedirectUrl(origin: string, redirectRoute: string, location: string): string { + getExternalServerRedirectUrl(origin: string, redirectRoute: string, location: string): string { const correctRedirectUrl = new URLCombiner(origin, redirectRoute).toString(); let externalServerUrl = location; @@ -693,19 +689,4 @@ export class AuthService { this.store.dispatch(new UnsetUserAsIdleAction()); } } - - public getAuthMethods(excludedAuthMethod?: AuthMethodType): Observable { - 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')), - ); - } - } diff --git a/src/app/external-log-in/external-log-in/external-log-in.component.html b/src/app/external-log-in/external-log-in/external-log-in.component.html index cdcc89e6d9..90b03d55fb 100644 --- a/src/app/external-log-in/external-log-in/external-log-in.component.html +++ b/src/app/external-log-in/external-log-in/external-log-in.component.html @@ -22,7 +22,7 @@

{{ 'external-login.component.or' | translate }}

-
diff --git a/src/app/external-log-in/external-log-in/external-log-in.component.spec.ts b/src/app/external-log-in/external-log-in/external-log-in.component.spec.ts index fa4668b524..d57aebd0d7 100644 --- a/src/app/external-log-in/external-log-in/external-log-in.component.spec.ts +++ b/src/app/external-log-in/external-log-in/external-log-in.component.spec.ts @@ -8,16 +8,24 @@ import { FormBuilder } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { StoreModule } from '@ngrx/store'; +import { provideMockStore } from '@ngrx/store/testing'; import { TranslateModule, TranslateService, } from '@ngx-translate/core'; 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 { 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 { MetadataValue } from '../../core/shared/metadata.models'; 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 { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe'; import { ConfirmEmailComponent } from '../email-confirmation/confirm-email/confirm-email.component'; @@ -28,6 +36,22 @@ describe('ExternalLogInComponent', () => { let component: ExternalLogInComponent; let fixture: ComponentFixture; let modalService: NgbModal = jasmine.createSpyObj('modalService', ['open']); + let authServiceStub: jasmine.SpyObj; + let authMethodsServiceStub: jasmine.SpyObj; + 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 = { id: '3', @@ -55,14 +79,26 @@ describe('ExternalLogInComponent', () => { onDefaultLangChange: new EventEmitter(), }; - beforeEach(() => - TestBed.configureTestingModule({ - imports: [CommonModule, TranslateModule.forRoot({}), BrowserOnlyPipe, ExternalLogInComponent, OrcidConfirmationComponent, BrowserAnimationsModule], + beforeEach(async () => { + authServiceStub = jasmine.createSpyObj('AuthService', ['getAuthenticationMethods']); + authMethodsServiceStub = jasmine.createSpyObj('AuthMethodsService', ['getAuthMethods']); + + await TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot({}), + BrowserOnlyPipe, + ExternalLogInComponent, + OrcidConfirmationComponent, + BrowserAnimationsModule, + StoreModule.forRoot(authReducer, storeModuleConfig), + ], providers: [ { provide: TranslateService, useValue: translateServiceStub }, { provide: AuthService, useValue: new AuthServiceMock() }, { provide: NgbModal, useValue: modalService }, FormBuilder, + provideMockStore({ initialState }), ], }) .overrideComponent(ExternalLogInComponent, { @@ -70,23 +106,31 @@ describe('ExternalLogInComponent', () => { imports: [ConfirmEmailComponent], }, }) - .compileComponents(), - ); - + .compileComponents(); + }); beforeEach(() => { fixture = TestBed.createComponent(ExternalLogInComponent); component = fixture.componentInstance; component.registrationData = Object.assign(new Registration(), registrationDataMock); component.registrationType = registrationDataMock.registrationType; + + let mockAuthMethods = new Map(); + 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(); }); it('should create', () => { + fixture.detectChanges(); expect(component).toBeTruthy(); }); beforeEach(() => { component.registrationData = Object.assign(new Registration(), registrationDataMock, { email: 'user@institution.edu' }); + fixture.detectChanges(); }); @@ -103,8 +147,11 @@ describe('ExternalLogInComponent', () => { }); it('should display login modal when connect to existing account button is clicked', () => { - const button = fixture.nativeElement.querySelector('button.btn-primary'); - button.click(); + const button = fixture.debugElement.query(By.css('[data-test="open-modal"]')); + + expect(button).not.toBeNull('Connect to existing account button should be in the DOM'); + + button.nativeElement.click(); expect(modalService.open).toHaveBeenCalled(); }); diff --git a/src/app/external-log-in/external-log-in/external-log-in.component.ts b/src/app/external-log-in/external-log-in/external-log-in.component.ts index 0639ac94a5..63eb6414b1 100644 --- a/src/app/external-log-in/external-log-in/external-log-in.component.ts +++ b/src/app/external-log-in/external-log-in/external-log-in.component.ts @@ -22,6 +22,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; 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 { AuthRegistrationType } from '../../core/auth/models/auth.registration-type'; import { Registration } from '../../core/shared/registration.model'; @@ -31,6 +32,7 @@ import { hasValue, isEmpty, } 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 { ExternalLoginTypeComponent, @@ -78,6 +80,11 @@ export class ExternalLogInComponent implements OnInit, OnDestroy { * @memberof ExternalLogInComponent */ @Input() token: string; + /** + * The authMethods taken from the configuration + * @memberof ExternalLogInComponent + */ + @Input() authMethods: Map; /** * The information text to be displayed, * 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 modalService: NgbModal, private authService: AuthService, + private authMethodsService: AuthMethodsService, ) { } @@ -128,11 +136,14 @@ export class ExternalLogInComponent implements OnInit, OnDestroy { parent: this.injector, }); 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.generateInformationTextWhenEmail(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)); } /** diff --git a/src/app/external-log-in/guards/registration-token.guard.spec.ts b/src/app/external-log-in/guards/registration-token.guard.spec.ts index 147026f6e0..eb9add5965 100644 --- a/src/app/external-log-in/guards/registration-token.guard.spec.ts +++ b/src/app/external-log-in/guards/registration-token.guard.spec.ts @@ -23,7 +23,7 @@ import { } from '../../shared/remote-data.utils'; import { registrationTokenGuard } from './registration-token-guard'; -fdescribe('RegistrationTokenGuard', +describe('RegistrationTokenGuard', () => { const route = new RouterMock(); const registrationWithGroups = Object.assign(new Registration(), diff --git a/src/app/external-login-page/external-login-page.component.html b/src/app/external-login-page/external-login-page.component.html index 2c5d9bf10e..a001775a77 100644 --- a/src/app/external-login-page/external-login-page.component.html +++ b/src/app/external-login-page/external-login-page.component.html @@ -1,6 +1,10 @@
@if (registrationData$ | async; as registrationData) { - + } @if (hasErrors) { diff --git a/src/app/external-login-page/external-login-page.component.ts b/src/app/external-login-page/external-login-page.component.ts index 1da424091f..8e7ec24c55 100644 --- a/src/app/external-login-page/external-login-page.component.ts +++ b/src/app/external-login-page/external-login-page.component.ts @@ -12,12 +12,15 @@ import { tap, } from 'rxjs'; +import { AuthMethodType } from '../core/auth/models/auth.method-type'; import { RemoteData } from '../core/data/remote-data'; import { Registration } from '../core/shared/registration.model'; import { ExternalLogInComponent } from '../external-log-in/external-log-in/external-log-in.component'; import { AlertComponent } from '../shared/alert/alert.component'; import { AlertType } from '../shared/alert/alert-type'; 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({ templateUrl: './external-login-page.component.html', @@ -53,11 +56,14 @@ export class ExternalLoginPageComponent implements OnInit { */ public hasErrors = false; + public authMethods: Map; + constructor( private arouter: ActivatedRoute, ) { this.token = this.arouter.snapshot.params.token; this.hasErrors = hasNoValue(this.arouter.snapshot.params.token); + this.authMethods = AUTH_METHOD_FOR_DECORATOR_MAP; } ngOnInit(): void { diff --git a/src/app/shared/log-in/container/log-in-container.component.ts b/src/app/shared/log-in/container/log-in-container.component.ts index bf06f4f07c..ab95fb4745 100644 --- a/src/app/shared/log-in/container/log-in-container.component.ts +++ b/src/app/shared/log-in/container/log-in-container.component.ts @@ -7,10 +7,9 @@ import { } from '@angular/core'; import { AuthMethod } from '../../../core/auth/models/auth.method'; -import { - AuthMethodTypeComponent, - rendersAuthMethodType, -} from '../methods/log-in.methods-decorator'; +import { AuthMethodTypeComponent } from '../methods/auth-methods.type'; +import { AUTH_METHOD_FOR_DECORATOR_MAP } from '../methods/log-in.methods-decorator'; +import { rendersAuthMethodType } from '../methods/log-in.methods-decorator.utils'; /** * 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 */ getAuthMethodContent(): AuthMethodTypeComponent { - return rendersAuthMethodType(this.authMethod.authMethodType); + return rendersAuthMethodType(AUTH_METHOD_FOR_DECORATOR_MAP, this.authMethod.authMethodType); } } diff --git a/src/app/shared/log-in/log-in.component.ts b/src/app/shared/log-in/log-in.component.ts index 58d7a11feb..bfcb1f3198 100644 --- a/src/app/shared/log-in/log-in.component.ts +++ b/src/app/shared/log-in/log-in.component.ts @@ -12,6 +12,7 @@ import { import { Observable } from 'rxjs'; 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 { @@ -23,6 +24,7 @@ import { CoreState } from '../../core/core-state.model'; import { hasValue } from '../empty.util'; import { ThemedLoadingComponent } from '../loading/themed-loading.component'; import { LogInContainerComponent } from './container/log-in-container.component'; +import { AUTH_METHOD_FOR_DECORATOR_MAP } from './methods/log-in.methods-decorator'; @Component({ selector: 'ds-base-log-in', @@ -69,11 +71,12 @@ export class LogInComponent implements OnInit { constructor(private store: Store, private authService: AuthService, + private authMethodsService: AuthMethodsService, ) { } ngOnInit(): void { - this.authMethods = this.authService.getAuthMethods(this.excludedAuthMethod); + this.authMethods = this.authMethodsService.getAuthMethods(AUTH_METHOD_FOR_DECORATOR_MAP, this.excludedAuthMethod); // set loading this.loading = this.store.pipe(select(isAuthenticationLoading)); diff --git a/src/app/shared/log-in/methods/auth-methods.type.ts b/src/app/shared/log-in/methods/auth-methods.type.ts new file mode 100644 index 0000000000..5b68f0b2e6 --- /dev/null +++ b/src/app/shared/log-in/methods/auth-methods.type.ts @@ -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; diff --git a/src/app/shared/log-in/methods/log-in.methods-decorator.ts b/src/app/shared/log-in/methods/log-in.methods-decorator.ts index e714d03e3e..e17fff856a 100644 --- a/src/app/shared/log-in/methods/log-in.methods-decorator.ts +++ b/src/app/shared/log-in/methods/log-in.methods-decorator.ts @@ -1,11 +1,8 @@ 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 { LogInPasswordComponent } from './password/log-in-password.component'; -export type AuthMethodTypeComponent = - typeof LogInPasswordComponent | - typeof LogInExternalProviderComponent; - export const AUTH_METHOD_FOR_DECORATOR_MAP = new Map([ [AuthMethodType.Password, LogInPasswordComponent], [AuthMethodType.Shibboleth, LogInExternalProviderComponent], @@ -25,7 +22,3 @@ export function renderAuthMethodFor(authMethodType: AuthMethodType) { AUTH_METHOD_FOR_DECORATOR_MAP.set(authMethodType, objectElement); }; } - -export function rendersAuthMethodType(authMethodType: AuthMethodType) { - return AUTH_METHOD_FOR_DECORATOR_MAP.get(authMethodType); -} diff --git a/src/app/shared/log-in/methods/log-in.methods-decorator.utils.ts b/src/app/shared/log-in/methods/log-in.methods-decorator.utils.ts new file mode 100644 index 0000000000..32c639e985 --- /dev/null +++ b/src/app/shared/log-in/methods/log-in.methods-decorator.utils.ts @@ -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: AuthMethodType, +) { + return authMethods.get(authMethodType); +} diff --git a/src/app/shared/log-in/methods/password/log-in-password.component.ts b/src/app/shared/log-in/methods/password/log-in-password.component.ts index d7d772633d..d075294fbb 100644 --- a/src/app/shared/log-in/methods/password/log-in-password.component.ts +++ b/src/app/shared/log-in/methods/password/log-in-password.component.ts @@ -165,11 +165,11 @@ export class LogInPasswordComponent implements OnInit { shareReplay({ refCount: false, bufferSize: 1 }), ); this.canShowDivider$ = - combineLatest([this.canRegister$, this.canForgot$]) - .pipe( - map(([canRegister, canForgot]) => canRegister || canForgot), - filter(Boolean), - ); + combineLatest([this.canRegister$, this.canForgot$]) + .pipe( + map(([canRegister, canForgot]) => canRegister || canForgot), + filter(Boolean), + ); } getRegisterRoute() {