mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-14 13:33:03 +00:00
Dynamic rendering of auth methods via decorator
This commit is contained in:
@@ -3,8 +3,7 @@
|
||||
<div>
|
||||
<img class="mb-4 login-logo" src="assets/images/dspace-logo.png">
|
||||
<h1 class="h3 mb-0 font-weight-normal">{{"login.form.header" | translate}}</h1>
|
||||
<!-- <ds-log-in></ds-log-in>-->
|
||||
<ds-log-in></ds-log-in>
|
||||
<ds-login-container></ds-login-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,30 +1,32 @@
|
||||
import {AuthMethodType} from '../../../shared/log-in/authMethods-type';
|
||||
|
||||
export class AuthMethodModel {
|
||||
authMethodName: string;
|
||||
location?: string;
|
||||
authMethodConstant: AuthMethodType
|
||||
authMethodType: AuthMethodType
|
||||
|
||||
constructor(authMethodName: string, location?: string) {
|
||||
this.authMethodName = authMethodName;
|
||||
this.location = location;
|
||||
switch (authMethodName) {
|
||||
case 'ip': {
|
||||
this.authMethodConstant = AuthMethodType.Ip;
|
||||
this.authMethodType = AuthMethodType.Ip;
|
||||
break;
|
||||
}
|
||||
case 'ldap': {
|
||||
this.authMethodConstant = AuthMethodType.Ldap;
|
||||
this.authMethodType = AuthMethodType.Ldap;
|
||||
break;
|
||||
}
|
||||
case 'shibboleth': {
|
||||
this.authMethodConstant = AuthMethodType.Shibboleth;
|
||||
this.authMethodType = AuthMethodType.Shibboleth;
|
||||
break;
|
||||
}
|
||||
case 'x509': {
|
||||
this.authMethodConstant = AuthMethodType.X509;
|
||||
this.authMethodType = AuthMethodType.X509;
|
||||
break;
|
||||
}
|
||||
case 'password': {
|
||||
this.authMethodConstant = AuthMethodType.Password;
|
||||
this.authMethodType = AuthMethodType.Password;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -34,11 +36,3 @@ export class AuthMethodModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export enum AuthMethodType {
|
||||
Password = 'password',
|
||||
Shibboleth = 'shibboleth',
|
||||
Ldap = 'ldap',
|
||||
Ip = 'ip',
|
||||
X509 = 'x509'
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<a href="#" id="dropdownLogin" (click)="$event.preventDefault()" ngbDropdownToggle class="px-1">{{ 'nav.login' | translate }}</a>
|
||||
<div id="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu aria-labelledby="dropdownLogin">
|
||||
<!-- <ds-log-in></ds-log-in>-->
|
||||
<ds-log-in></ds-log-in>
|
||||
<ds-login-container></ds-login-container>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
15
src/app/shared/log-in/authMethods-decorator.ts
Normal file
15
src/app/shared/log-in/authMethods-decorator.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { AuthMethodType } from './authMethods-type';
|
||||
|
||||
const authMethodsMap = new Map();
|
||||
export function renderAuthMethodFor(authMethodType: AuthMethodType) {
|
||||
return function decorator(objectElement: any) {
|
||||
if (!objectElement) {
|
||||
return;
|
||||
}
|
||||
authMethodsMap.set(authMethodType, objectElement);
|
||||
};
|
||||
}
|
||||
|
||||
export function rendersAuthMethodType(authMethodType: AuthMethodType) {
|
||||
return authMethodsMap.get(authMethodType);
|
||||
}
|
7
src/app/shared/log-in/authMethods-type.ts
Normal file
7
src/app/shared/log-in/authMethods-type.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export enum AuthMethodType {
|
||||
Password = 'password',
|
||||
Shibboleth = 'shibboleth',
|
||||
Ldap = 'ldap',
|
||||
Ip = 'ip',
|
||||
X509 = 'x509'
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
<div *ngFor="let authMethod of authMethodData | async">
|
||||
<ng-container *ngComponentOutlet="getAuthMethodContent(authMethod.authMethodType); injector: objectInjector;"></ng-container>
|
||||
</div>
|
@@ -0,0 +1,21 @@
|
||||
:host /deep/ .card {
|
||||
margin-bottom: $submission-sections-margin-bottom;
|
||||
overflow: unset;
|
||||
}
|
||||
|
||||
.section-focus {
|
||||
border-radius: $border-radius;
|
||||
box-shadow: $btn-focus-box-shadow;
|
||||
}
|
||||
|
||||
// TODO to remove the following when upgrading @ng-bootstrap
|
||||
:host /deep/ .card:first-of-type {
|
||||
border-bottom: $card-border-width solid $card-border-color !important;
|
||||
border-bottom-left-radius: $card-border-radius !important;
|
||||
border-bottom-right-radius: $card-border-radius !important;
|
||||
}
|
||||
|
||||
:host /deep/ .card-header button {
|
||||
box-shadow: none !important;
|
||||
width: 100%;
|
||||
}
|
60
src/app/shared/log-in/container/login-container.component.ts
Normal file
60
src/app/shared/log-in/container/login-container.component.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Component, Injector, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { rendersAuthMethodType } from '../authMethods-decorator';
|
||||
import { AuthMethodModel } from '../../../core/auth/models/auth-method.model';
|
||||
import { getAuthenticationMethods } from '../../../core/auth/selectors';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../../app.reducer';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AuthMethodType } from '../authMethods-type';
|
||||
|
||||
/**
|
||||
* This component represents a section that contains the submission license form.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-login-container',
|
||||
templateUrl: './login-container.component.html',
|
||||
styleUrls: ['./login-container.component.scss']
|
||||
})
|
||||
export class LoginContainerComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* The section data
|
||||
* @type {SectionDataObject}
|
||||
*/
|
||||
@Input() authMethodData: Observable<AuthMethodModel[]>;
|
||||
|
||||
/**
|
||||
* Injector to inject a section component with the @Input parameters
|
||||
* @type {Injector}
|
||||
*/
|
||||
public objectInjector: Injector;
|
||||
|
||||
/**
|
||||
* Initialize instance variables
|
||||
*
|
||||
* @param {Injector} injector
|
||||
*/
|
||||
constructor(private injector: Injector, private store: Store<AppState>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all instance variables
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.objectInjector = Injector.create({
|
||||
providers: [
|
||||
{provide: 'authMethodProvider', useFactory: () => (this.authMethodData), deps: []},
|
||||
],
|
||||
parent: this.injector
|
||||
});
|
||||
|
||||
this.authMethodData = this.store.select(getAuthenticationMethods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the correct component based on the authMethod's type
|
||||
*/
|
||||
getAuthMethodContent(authMethodType: AuthMethodType): string {
|
||||
return rendersAuthMethodType(authMethodType)
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
<br>
|
||||
<div *ngFor="let method of dynamicLoginMethods | async; let i = index" >
|
||||
|
||||
|
||||
<!-- <div class="dropdown-divider"></div>-->
|
||||
<br *ngIf="i >= 1">
|
||||
|
||||
|
||||
|
||||
<ng-container *ngComponentOutlet="method.component; injector: objectInjector;">
|
||||
</ng-container>
|
||||
</div>
|
@@ -1,84 +0,0 @@
|
||||
import {Component, Injector, OnDestroy, OnInit} from '@angular/core';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {DynamicShibbolethComponent} from './methods/shibboleth/dynamic-shibboleth.component';
|
||||
import {getAuthenticationMethods} from '../../core/auth/selectors';
|
||||
import {map} from 'rxjs/operators';
|
||||
import {AppState} from '../../app.reducer';
|
||||
import {Observable} from 'rxjs';
|
||||
import {AuthMethodType} from '../../core/auth/models/auth-method.model';
|
||||
import {DynamicLoginMethod} from './log-in.model';
|
||||
import {LogInPasswordComponent} from './methods/password/log-in-password.component';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-log-in',
|
||||
templateUrl: './log-in.component.html',
|
||||
styleUrls: ['./log-in.component.scss'],
|
||||
|
||||
})
|
||||
export class LogInComponent implements OnDestroy, OnInit {
|
||||
|
||||
public dynamicLoginMethods: Observable<DynamicLoginMethod[]>;
|
||||
/**
|
||||
* Injector to inject a section component with the @Input parameters
|
||||
* @type {Injector}
|
||||
*/
|
||||
public objectInjector: Injector;
|
||||
private shibbolethUrl: string;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Store<State>} store
|
||||
* @param {Injector} injector
|
||||
*/
|
||||
constructor(
|
||||
private store: Store<AppState>,
|
||||
private injector: Injector
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook that is called after data-bound properties of a directive are initialized.
|
||||
* @method ngOnInit
|
||||
*/
|
||||
public ngOnInit() {
|
||||
|
||||
this.objectInjector = Injector.create({
|
||||
providers: [
|
||||
{provide: 'shibbolethUrlProvider', useFactory: () => (this.shibbolethUrl), deps: []},
|
||||
// if other authentication methods need further data to work add a provider here e.g
|
||||
// {provide: 'otherDataProvider', useFactory: () => (this.otherData), deps: []},
|
||||
],
|
||||
parent: this.injector
|
||||
});
|
||||
|
||||
this.dynamicLoginMethods = this.store.select(getAuthenticationMethods).pipe(
|
||||
map(((authMethods) => authMethods.map((authMethod) => {
|
||||
switch (authMethod.authMethodConstant) {
|
||||
case AuthMethodType.Password:
|
||||
return new DynamicLoginMethod(authMethod.authMethodName, LogInPasswordComponent)
|
||||
break;
|
||||
case AuthMethodType.Shibboleth:
|
||||
this.shibbolethUrl = authMethod.location;
|
||||
// this.shibbolethUrl = 'https://fis.tiss.tuwien.ac.at/Shibboleth.sso/Login?target=https://fis.tiss.tuwien.ac.at/shibboleth';
|
||||
return new DynamicLoginMethod(authMethod.authMethodName, DynamicShibbolethComponent, authMethod.location)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook that is called when a directive, pipe or service is destroyed.
|
||||
* @method ngOnDestroy
|
||||
*/
|
||||
public ngOnDestroy() {
|
||||
// console.log('ngOnDestroy() in LogInContainerComponent was called');
|
||||
}
|
||||
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
export class DynamicLoginMethod {
|
||||
label: string;
|
||||
component: any;
|
||||
location?: string;
|
||||
|
||||
constructor(label, component, location?) {
|
||||
this.label = label;
|
||||
this.component = component;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
@@ -20,6 +20,8 @@ import {CoreState} from '../../../../core/core.reducers';
|
||||
import {isNotEmpty} from '../../../empty.util';
|
||||
import {fadeOut} from '../../../animations/fade';
|
||||
import {AuthService} from '../../../../core/auth/auth.service';
|
||||
import { AuthMethodType } from '../../authMethods-type';
|
||||
import { renderAuthMethodFor } from '../../authMethods-decorator';
|
||||
|
||||
/**
|
||||
* /users/sign-in
|
||||
@@ -31,6 +33,7 @@ import {AuthService} from '../../../../core/auth/auth.service';
|
||||
styleUrls: ['./log-in-password.component.scss'],
|
||||
animations: [fadeOut]
|
||||
})
|
||||
@renderAuthMethodFor(AuthMethodType.Password)
|
||||
export class LogInPasswordComponent implements OnDestroy, OnInit {
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,7 @@
|
||||
|
||||
import {Component, Inject, Input, OnInit} from '@angular/core';
|
||||
import { renderAuthMethodFor } from '../../authMethods-decorator';
|
||||
import { AuthMethodType } from '../../authMethods-type';
|
||||
import { AuthMethodModel } from '../../../../core/auth/models/auth-method.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-shibboleth',
|
||||
@@ -7,11 +9,17 @@ import {Component, Inject, Input, OnInit} from '@angular/core';
|
||||
styleUrls: ['./dynamic-shibboleth.component.scss'],
|
||||
|
||||
})
|
||||
export class DynamicShibbolethComponent {
|
||||
@renderAuthMethodFor(AuthMethodType.Shibboleth)
|
||||
export class DynamicShibbolethComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
constructor(@Inject('shibbolethUrlProvider') public injectedShibbolethUrl: string) {
|
||||
constructor(@Inject('authMethodProvider') public injectedObject: AuthMethodModel) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log('injectedObject', this.injectedObject)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -138,8 +138,9 @@ import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component
|
||||
import { ClaimedTaskActionsReturnToPoolComponent } from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component';
|
||||
import { ItemDetailPreviewFieldComponent } from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component';
|
||||
import {DynamicShibbolethComponent} from './log-in/methods/shibboleth/dynamic-shibboleth.component';
|
||||
import {LogInComponent} from './log-in/log-in.component';
|
||||
// import {LogInComponent} from './log-in/log-in.component';
|
||||
import {LogInPasswordComponent} from './log-in/methods/password/log-in-password.component';
|
||||
import { LoginContainerComponent } from './log-in/container/login-container.component';
|
||||
|
||||
const MODULES = [
|
||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||
@@ -212,7 +213,7 @@ const COMPONENTS = [
|
||||
FormComponent,
|
||||
LangSwitchComponent,
|
||||
LoadingComponent,
|
||||
LogInComponent,
|
||||
// LogInComponent,
|
||||
LogOutComponent,
|
||||
NumberPickerComponent,
|
||||
ObjectListComponent,
|
||||
@@ -260,9 +261,10 @@ const COMPONENTS = [
|
||||
TypedItemSearchResultListElementComponent,
|
||||
ItemTypeSwitcherComponent,
|
||||
BrowseByComponent,
|
||||
LogInComponent,
|
||||
// LogInComponent,
|
||||
DynamicShibbolethComponent,
|
||||
LogInPasswordComponent
|
||||
LogInPasswordComponent,
|
||||
LoginContainerComponent
|
||||
];
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
|
Reference in New Issue
Block a user