mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Fix display order of authentication methods
This commit is contained in:
@@ -152,12 +152,12 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
|
|
||||||
let authMethodModel: AuthMethod;
|
let authMethodModel: AuthMethod;
|
||||||
if (splittedRealm.length === 1) {
|
if (splittedRealm.length === 1) {
|
||||||
authMethodModel = new AuthMethod(methodName);
|
authMethodModel = new AuthMethod(methodName, Number(j));
|
||||||
authMethodModels.push(authMethodModel);
|
authMethodModels.push(authMethodModel);
|
||||||
} else if (splittedRealm.length > 1) {
|
} else if (splittedRealm.length > 1) {
|
||||||
let location = splittedRealm[1];
|
let location = splittedRealm[1];
|
||||||
location = this.parseLocation(location);
|
location = this.parseLocation(location);
|
||||||
authMethodModel = new AuthMethod(methodName, location);
|
authMethodModel = new AuthMethod(methodName, Number(j), location);
|
||||||
authMethodModels.push(authMethodModel);
|
authMethodModels.push(authMethodModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
// make sure the email + password login component gets rendered first
|
// make sure the email + password login component gets rendered first
|
||||||
authMethodModels = this.sortAuthMethods(authMethodModels);
|
authMethodModels = this.sortAuthMethods(authMethodModels);
|
||||||
} else {
|
} else {
|
||||||
authMethodModels.push(new AuthMethod(AuthMethodType.Password));
|
authMethodModels.push(new AuthMethod(AuthMethodType.Password, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return authMethodModels;
|
return authMethodModels;
|
||||||
|
@@ -575,9 +575,9 @@ describe('authReducer', () => {
|
|||||||
authMethods: [],
|
authMethods: [],
|
||||||
idle: false
|
idle: false
|
||||||
};
|
};
|
||||||
const authMethods = [
|
const authMethods: AuthMethod[] = [
|
||||||
new AuthMethod(AuthMethodType.Password),
|
new AuthMethod(AuthMethodType.Password, 0),
|
||||||
new AuthMethod(AuthMethodType.Shibboleth, 'location')
|
new AuthMethod(AuthMethodType.Shibboleth, 1, 'location'),
|
||||||
];
|
];
|
||||||
const action = new RetrieveAuthMethodsSuccessAction(authMethods);
|
const action = new RetrieveAuthMethodsSuccessAction(authMethods);
|
||||||
const newState = authReducer(initialState, action);
|
const newState = authReducer(initialState, action);
|
||||||
@@ -609,7 +609,7 @@ describe('authReducer', () => {
|
|||||||
loaded: false,
|
loaded: false,
|
||||||
blocking: false,
|
blocking: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
authMethods: [new AuthMethod(AuthMethodType.Password)],
|
authMethods: [new AuthMethod(AuthMethodType.Password, 0)],
|
||||||
idle: false
|
idle: false
|
||||||
};
|
};
|
||||||
expect(newState).toEqual(state);
|
expect(newState).toEqual(state);
|
||||||
|
@@ -228,7 +228,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
|
|||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
loading: false,
|
loading: false,
|
||||||
blocking: false,
|
blocking: false,
|
||||||
authMethods: [new AuthMethod(AuthMethodType.Password)]
|
authMethods: [new AuthMethod(AuthMethodType.Password, 0)]
|
||||||
});
|
});
|
||||||
|
|
||||||
case AuthActionTypes.SET_REDIRECT_URL:
|
case AuthActionTypes.SET_REDIRECT_URL:
|
||||||
|
@@ -2,11 +2,12 @@ import { AuthMethodType } from './auth.method-type';
|
|||||||
|
|
||||||
export class AuthMethod {
|
export class AuthMethod {
|
||||||
authMethodType: AuthMethodType;
|
authMethodType: AuthMethodType;
|
||||||
|
position: number;
|
||||||
location?: string;
|
location?: string;
|
||||||
|
|
||||||
// isStandalonePage? = true;
|
constructor(authMethodName: string, position: number, location?: string) {
|
||||||
|
this.position = position;
|
||||||
|
|
||||||
constructor(authMethodName: string, location?: string) {
|
|
||||||
switch (authMethodName) {
|
switch (authMethodName) {
|
||||||
case 'ip': {
|
case 'ip': {
|
||||||
this.authMethodType = AuthMethodType.Ip;
|
this.authMethodType = AuthMethodType.Ip;
|
||||||
|
@@ -13,13 +13,17 @@ import { AuthMethod } from '../../../core/auth/models/auth.method';
|
|||||||
import { AuthServiceStub } from '../../testing/auth-service.stub';
|
import { AuthServiceStub } from '../../testing/auth-service.stub';
|
||||||
import { createTestComponent } from '../../testing/utils.test';
|
import { createTestComponent } from '../../testing/utils.test';
|
||||||
import { HardRedirectService } from '../../../core/services/hard-redirect.service';
|
import { HardRedirectService } from '../../../core/services/hard-redirect.service';
|
||||||
|
import { AuthMethodType } from '../../../core/auth/models/auth.method-type';
|
||||||
|
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { AuthorizationDataServiceStub } from '../../testing/authorization-service.stub';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
describe('LogInContainerComponent', () => {
|
describe('LogInContainerComponent', () => {
|
||||||
|
|
||||||
let component: LogInContainerComponent;
|
let component: LogInContainerComponent;
|
||||||
let fixture: ComponentFixture<LogInContainerComponent>;
|
let fixture: ComponentFixture<LogInContainerComponent>;
|
||||||
|
|
||||||
const authMethod = new AuthMethod('password');
|
const authMethod = new AuthMethod(AuthMethodType.Password, 0);
|
||||||
|
|
||||||
let hardRedirectService: HardRedirectService;
|
let hardRedirectService: HardRedirectService;
|
||||||
|
|
||||||
@@ -35,13 +39,15 @@ describe('LogInContainerComponent', () => {
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
StoreModule.forRoot(authReducer),
|
StoreModule.forRoot(authReducer),
|
||||||
SharedModule,
|
SharedModule,
|
||||||
TranslateModule.forRoot()
|
TranslateModule.forRoot(),
|
||||||
|
RouterTestingModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
TestComponent
|
TestComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AuthService, useClass: AuthServiceStub },
|
{ provide: AuthService, useClass: AuthServiceStub },
|
||||||
|
{ provide: AuthorizationDataService, useClass: AuthorizationDataServiceStub },
|
||||||
{ provide: HardRedirectService, useValue: hardRedirectService },
|
{ provide: HardRedirectService, useValue: hardRedirectService },
|
||||||
LogInContainerComponent
|
LogInContainerComponent
|
||||||
],
|
],
|
||||||
@@ -113,6 +119,6 @@ describe('LogInContainerComponent', () => {
|
|||||||
class TestComponent {
|
class TestComponent {
|
||||||
|
|
||||||
isStandalonePage = true;
|
isStandalonePage = true;
|
||||||
authMethod = new AuthMethod('password');
|
authMethod = new AuthMethod(AuthMethodType.Password, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,11 @@
|
|||||||
<ds-themed-loading *ngIf="(loading | async) || (isAuthenticated | async)" class="m-5"></ds-themed-loading>
|
<ds-themed-loading *ngIf="(loading | async) || (isAuthenticated | async)" class="m-5"></ds-themed-loading>
|
||||||
<div *ngIf="!(loading | async) && !(isAuthenticated | async)" class="px-4 py-3 login-container">
|
<div *ngIf="!(loading | async) && !(isAuthenticated | async)" class="px-4 py-3 login-container">
|
||||||
<ng-container *ngFor="let authMethod of (authMethods | async); let i = index">
|
<ng-container *ngFor="let authMethod of getOrderedAuthMethods(authMethods | async); let last = last">
|
||||||
<div *ngIf="i === 1" class="text-center mt-2">
|
<div [class.d-none]="contentRef.innerText.trim().length === 0">
|
||||||
<span class="align-middle">{{"login.form.or-divider" | translate}}</span>
|
<div #contentRef>
|
||||||
|
<ds-log-in-container [authMethod]="authMethod" [isStandalonePage]="isStandalonePage"></ds-log-in-container>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!last" class="dropdown-divider my-2"></div>
|
||||||
</div>
|
</div>
|
||||||
<ds-log-in-container [authMethod]="authMethod" [isStandalonePage]="isStandalonePage"></ds-log-in-container>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" *ngIf="canRegister$ | async" [routerLink]="[getRegisterRoute()]" [attr.data-test]="'register' | dsBrowserOnly">{{"login.form.new-user" | translate}}</a>
|
|
||||||
<a class="dropdown-item" [routerLink]="[getForgotRoute()]" [attr.data-test]="'forgot' | dsBrowserOnly">{{"login.form.forgot-password" | translate}}</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -50,7 +50,7 @@ describe('LogInComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// refine the test module by declaring the test component
|
// refine the test module by declaring the test component
|
||||||
TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
import { AuthMethod } from '../../core/auth/models/auth.method';
|
import { AuthMethod } from '../../core/auth/models/auth.method';
|
||||||
@@ -8,11 +8,8 @@ import {
|
|||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
isAuthenticationLoading
|
isAuthenticationLoading
|
||||||
} from '../../core/auth/selectors';
|
} from '../../core/auth/selectors';
|
||||||
import { getForgotPasswordRoute, getRegisterRoute } from '../../app-routing-paths';
|
|
||||||
import { hasValue } from '../empty.util';
|
import { hasValue } from '../empty.util';
|
||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
|
||||||
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
|
|
||||||
import { CoreState } from '../../core/core-state.model';
|
import { CoreState } from '../../core/core-state.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +19,8 @@ import { CoreState } from '../../core/core-state.model';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-log-in',
|
selector: 'ds-log-in',
|
||||||
templateUrl: './log-in.component.html',
|
templateUrl: './log-in.component.html',
|
||||||
styleUrls: ['./log-in.component.scss']
|
styleUrls: ['./log-in.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class LogInComponent implements OnInit {
|
export class LogInComponent implements OnInit {
|
||||||
|
|
||||||
@@ -50,14 +48,9 @@ export class LogInComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public loading: Observable<boolean>;
|
public loading: Observable<boolean>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the current user (or anonymous) is authorized to register an account
|
|
||||||
*/
|
|
||||||
canRegister$: Observable<boolean>;
|
|
||||||
|
|
||||||
constructor(private store: Store<CoreState>,
|
constructor(private store: Store<CoreState>,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private authorizationService: AuthorizationDataService) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@@ -78,15 +71,18 @@ export class LogInComponent implements OnInit {
|
|||||||
this.authService.clearRedirectUrl();
|
this.authService.clearRedirectUrl();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.canRegister$ = this.authorizationService.isAuthorized(FeatureID.EPersonRegistration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getRegisterRoute() {
|
/**
|
||||||
return getRegisterRoute();
|
* Returns an ordered list of {@link AuthMethod}s based on their position.
|
||||||
}
|
*
|
||||||
|
* @param authMethods The {@link AuthMethod}s to sort
|
||||||
getForgotRoute() {
|
*/
|
||||||
return getForgotPasswordRoute();
|
getOrderedAuthMethods(authMethods: AuthMethod[] | null): AuthMethod[] {
|
||||||
|
if (hasValue(authMethods)) {
|
||||||
|
return [...authMethods].sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
<button class="btn btn-lg btn-primary btn-block mt-2 text-white" (click)="redirectToOidc()">
|
<button class="btn btn-lg btn-primary btn-block text-white" (click)="redirectToOidc()">
|
||||||
<i class="fas fa-sign-in-alt"></i> {{"login.form.oidc" | translate}}
|
<i class="fas fa-sign-in-alt"></i> {{"login.form.oidc" | translate}}
|
||||||
</button>
|
</button>
|
@@ -3,11 +3,8 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { Store, StoreModule } from '@ngrx/store';
|
import { StoreModule } from '@ngrx/store';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { EPerson } from '../../../../core/eperson/models/eperson.model';
|
|
||||||
import { EPersonMock } from '../../../testing/eperson.mock';
|
|
||||||
import { authReducer } from '../../../../core/auth/auth.reducer';
|
import { authReducer } from '../../../../core/auth/auth.reducer';
|
||||||
import { AuthService } from '../../../../core/auth/auth.service';
|
import { AuthService } from '../../../../core/auth/auth.service';
|
||||||
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
||||||
@@ -20,23 +17,22 @@ import { RouterStub } from '../../../testing/router.stub';
|
|||||||
import { ActivatedRouteStub } from '../../../testing/active-router.stub';
|
import { ActivatedRouteStub } from '../../../testing/active-router.stub';
|
||||||
import { NativeWindowMockFactory } from '../../../mocks/mock-native-window-ref';
|
import { NativeWindowMockFactory } from '../../../mocks/mock-native-window-ref';
|
||||||
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
||||||
|
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { AuthorizationDataServiceStub } from '../../../testing/authorization-service.stub';
|
||||||
|
|
||||||
|
|
||||||
describe('LogInOidcComponent', () => {
|
describe('LogInOidcComponent', () => {
|
||||||
|
|
||||||
let component: LogInOidcComponent;
|
let component: LogInOidcComponent;
|
||||||
let fixture: ComponentFixture<LogInOidcComponent>;
|
let fixture: ComponentFixture<LogInOidcComponent>;
|
||||||
let page: Page;
|
|
||||||
let user: EPerson;
|
|
||||||
let componentAsAny: any;
|
let componentAsAny: any;
|
||||||
let setHrefSpy;
|
let setHrefSpy;
|
||||||
let oidcBaseUrl;
|
let oidcBaseUrl: string;
|
||||||
let location;
|
let location: string;
|
||||||
let initialState: any;
|
let initialState: any;
|
||||||
let hardRedirectService: HardRedirectService;
|
let hardRedirectService: HardRedirectService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
user = EPersonMock;
|
|
||||||
oidcBaseUrl = 'dspace-rest.test/oidc?redirectUrl=';
|
oidcBaseUrl = 'dspace-rest.test/oidc?redirectUrl=';
|
||||||
location = oidcBaseUrl + 'http://dspace-angular.test/home';
|
location = oidcBaseUrl + 'http://dspace-angular.test/home';
|
||||||
|
|
||||||
@@ -60,7 +56,7 @@ describe('LogInOidcComponent', () => {
|
|||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
// refine the test module by declaring the test component
|
// refine the test module by declaring the test component
|
||||||
TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
||||||
TranslateModule.forRoot()
|
TranslateModule.forRoot()
|
||||||
@@ -70,7 +66,8 @@ describe('LogInOidcComponent', () => {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AuthService, useClass: AuthServiceStub },
|
{ provide: AuthService, useClass: AuthServiceStub },
|
||||||
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Oidc, location) },
|
{ provide: AuthorizationDataService, useClass: AuthorizationDataServiceStub },
|
||||||
|
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Oidc, 0, location) },
|
||||||
{ provide: 'isStandalonePage', useValue: true },
|
{ provide: 'isStandalonePage', useValue: true },
|
||||||
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
@@ -95,7 +92,6 @@ describe('LogInOidcComponent', () => {
|
|||||||
componentAsAny = component;
|
componentAsAny = component;
|
||||||
|
|
||||||
// create page
|
// create page
|
||||||
page = new Page(component, fixture);
|
|
||||||
setHrefSpy = spyOnProperty(componentAsAny._window.nativeWindow.location, 'href', 'set').and.callThrough();
|
setHrefSpy = spyOnProperty(componentAsAny._window.nativeWindow.location, 'href', 'set').and.callThrough();
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -131,25 +127,3 @@ describe('LogInOidcComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* I represent the DOM elements and attach spies.
|
|
||||||
*
|
|
||||||
* @class Page
|
|
||||||
*/
|
|
||||||
class Page {
|
|
||||||
|
|
||||||
public emailInput: HTMLInputElement;
|
|
||||||
public navigateSpy: jasmine.Spy;
|
|
||||||
public passwordInput: HTMLInputElement;
|
|
||||||
|
|
||||||
constructor(private component: LogInOidcComponent, private fixture: ComponentFixture<LogInOidcComponent>) {
|
|
||||||
// use injector to get services
|
|
||||||
const injector = fixture.debugElement.injector;
|
|
||||||
const store = injector.get(Store);
|
|
||||||
|
|
||||||
// add spies
|
|
||||||
this.navigateSpy = spyOn(store, 'dispatch');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
<button class="btn btn-lg btn-primary btn-block mt-2 text-white" (click)="redirectToOrcid()">
|
<button class="btn btn-lg btn-primary btn-block text-white" (click)="redirectToOrcid()">
|
||||||
<i class="fas fa-sign-in-alt"></i> {{"login.form.orcid" | translate}}
|
<i class="fas fa-sign-in-alt"></i> {{"login.form.orcid" | translate}}
|
||||||
</button>
|
</button>
|
@@ -3,11 +3,8 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { Store, StoreModule } from '@ngrx/store';
|
import { StoreModule } from '@ngrx/store';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { EPerson } from '../../../../core/eperson/models/eperson.model';
|
|
||||||
import { EPersonMock } from '../../../testing/eperson.mock';
|
|
||||||
import { authReducer } from '../../../../core/auth/auth.reducer';
|
import { authReducer } from '../../../../core/auth/auth.reducer';
|
||||||
import { AuthService } from '../../../../core/auth/auth.service';
|
import { AuthService } from '../../../../core/auth/auth.service';
|
||||||
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
||||||
@@ -26,17 +23,14 @@ describe('LogInOrcidComponent', () => {
|
|||||||
|
|
||||||
let component: LogInOrcidComponent;
|
let component: LogInOrcidComponent;
|
||||||
let fixture: ComponentFixture<LogInOrcidComponent>;
|
let fixture: ComponentFixture<LogInOrcidComponent>;
|
||||||
let page: Page;
|
|
||||||
let user: EPerson;
|
|
||||||
let componentAsAny: any;
|
let componentAsAny: any;
|
||||||
let setHrefSpy;
|
let setHrefSpy;
|
||||||
let orcidBaseUrl;
|
let orcidBaseUrl: string;
|
||||||
let location;
|
let location: string;
|
||||||
let initialState: any;
|
let initialState: any;
|
||||||
let hardRedirectService: HardRedirectService;
|
let hardRedirectService: HardRedirectService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
user = EPersonMock;
|
|
||||||
orcidBaseUrl = 'dspace-rest.test/orcid?redirectUrl=';
|
orcidBaseUrl = 'dspace-rest.test/orcid?redirectUrl=';
|
||||||
location = orcidBaseUrl + 'http://dspace-angular.test/home';
|
location = orcidBaseUrl + 'http://dspace-angular.test/home';
|
||||||
|
|
||||||
@@ -60,7 +54,7 @@ describe('LogInOrcidComponent', () => {
|
|||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
// refine the test module by declaring the test component
|
// refine the test module by declaring the test component
|
||||||
TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
||||||
TranslateModule.forRoot()
|
TranslateModule.forRoot()
|
||||||
@@ -70,7 +64,7 @@ describe('LogInOrcidComponent', () => {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AuthService, useClass: AuthServiceStub },
|
{ provide: AuthService, useClass: AuthServiceStub },
|
||||||
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Orcid, location) },
|
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Orcid, 0, location) },
|
||||||
{ provide: 'isStandalonePage', useValue: true },
|
{ provide: 'isStandalonePage', useValue: true },
|
||||||
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
@@ -95,7 +89,6 @@ describe('LogInOrcidComponent', () => {
|
|||||||
componentAsAny = component;
|
componentAsAny = component;
|
||||||
|
|
||||||
// create page
|
// create page
|
||||||
page = new Page(component, fixture);
|
|
||||||
setHrefSpy = spyOnProperty(componentAsAny._window.nativeWindow.location, 'href', 'set').and.callThrough();
|
setHrefSpy = spyOnProperty(componentAsAny._window.nativeWindow.location, 'href', 'set').and.callThrough();
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -131,25 +124,3 @@ describe('LogInOrcidComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* I represent the DOM elements and attach spies.
|
|
||||||
*
|
|
||||||
* @class Page
|
|
||||||
*/
|
|
||||||
class Page {
|
|
||||||
|
|
||||||
public emailInput: HTMLInputElement;
|
|
||||||
public navigateSpy: jasmine.Spy;
|
|
||||||
public passwordInput: HTMLInputElement;
|
|
||||||
|
|
||||||
constructor(private component: LogInOrcidComponent, private fixture: ComponentFixture<LogInOrcidComponent>) {
|
|
||||||
// use injector to get services
|
|
||||||
const injector = fixture.debugElement.injector;
|
|
||||||
const store = injector.get(Store);
|
|
||||||
|
|
||||||
// add spies
|
|
||||||
this.navigateSpy = spyOn(store, 'dispatch');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@@ -28,3 +28,12 @@
|
|||||||
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit" [attr.data-test]="'login-button' | dsBrowserOnly"
|
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit" [attr.data-test]="'login-button' | dsBrowserOnly"
|
||||||
[disabled]="!form.valid"><i class="fas fa-sign-in-alt"></i> {{"login.form.submit" | translate}}</button>
|
[disabled]="!form.valid"><i class="fas fa-sign-in-alt"></i> {{"login.form.submit" | translate}}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<div class="mt-2">
|
||||||
|
<a class="dropdown-item" *ngIf="canRegister$ | async" [routerLink]="[getRegisterRoute()]" [attr.data-test]="'register' | dsBrowserOnly">
|
||||||
|
{{ 'login.form.new-user' | translate }}
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-item" [routerLink]="[getForgotRoute()]" [attr.data-test]="'forgot' | dsBrowserOnly">
|
||||||
|
{{ 'login.form.forgot-password' | translate }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@@ -11,3 +11,7 @@
|
|||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
white-space: normal;
|
||||||
|
padding: .25rem .75rem;
|
||||||
|
}
|
||||||
|
@@ -8,8 +8,6 @@ import { Store, StoreModule } from '@ngrx/store';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { LogInPasswordComponent } from './log-in-password.component';
|
import { LogInPasswordComponent } from './log-in-password.component';
|
||||||
import { EPerson } from '../../../../core/eperson/models/eperson.model';
|
|
||||||
import { EPersonMock } from '../../../testing/eperson.mock';
|
|
||||||
import { authReducer } from '../../../../core/auth/auth.reducer';
|
import { authReducer } from '../../../../core/auth/auth.reducer';
|
||||||
import { AuthService } from '../../../../core/auth/auth.service';
|
import { AuthService } from '../../../../core/auth/auth.service';
|
||||||
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
||||||
@@ -18,19 +16,18 @@ 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 { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
||||||
import { BrowserOnlyMockPipe } from '../../../testing/browser-only-mock.pipe';
|
import { BrowserOnlyMockPipe } from '../../../testing/browser-only-mock.pipe';
|
||||||
|
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { AuthorizationDataServiceStub } from '../../../testing/authorization-service.stub';
|
||||||
|
|
||||||
describe('LogInPasswordComponent', () => {
|
describe('LogInPasswordComponent', () => {
|
||||||
|
|
||||||
let component: LogInPasswordComponent;
|
let component: LogInPasswordComponent;
|
||||||
let fixture: ComponentFixture<LogInPasswordComponent>;
|
let fixture: ComponentFixture<LogInPasswordComponent>;
|
||||||
let page: Page;
|
let page: Page;
|
||||||
let user: EPerson;
|
|
||||||
let initialState: any;
|
let initialState: any;
|
||||||
let hardRedirectService: HardRedirectService;
|
let hardRedirectService: HardRedirectService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
user = EPersonMock;
|
|
||||||
|
|
||||||
hardRedirectService = jasmine.createSpyObj('hardRedirectService', {
|
hardRedirectService = jasmine.createSpyObj('hardRedirectService', {
|
||||||
getCurrentRoute: {}
|
getCurrentRoute: {}
|
||||||
});
|
});
|
||||||
@@ -50,7 +47,7 @@ describe('LogInPasswordComponent', () => {
|
|||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
// refine the test module by declaring the test component
|
// refine the test module by declaring the test component
|
||||||
TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@@ -63,7 +60,8 @@ describe('LogInPasswordComponent', () => {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AuthService, useClass: AuthServiceStub },
|
{ provide: AuthService, useClass: AuthServiceStub },
|
||||||
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Password) },
|
{ provide: AuthorizationDataService, useClass: AuthorizationDataServiceStub },
|
||||||
|
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Password, 0) },
|
||||||
{ provide: 'isStandalonePage', useValue: true },
|
{ provide: 'isStandalonePage', useValue: true },
|
||||||
{ provide: HardRedirectService, useValue: hardRedirectService },
|
{ provide: HardRedirectService, useValue: hardRedirectService },
|
||||||
provideMockStore({ initialState }),
|
provideMockStore({ initialState }),
|
||||||
@@ -76,7 +74,7 @@ describe('LogInPasswordComponent', () => {
|
|||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
// create component and test fixture
|
// create component and test fixture
|
||||||
fixture = TestBed.createComponent(LogInPasswordComponent);
|
fixture = TestBed.createComponent(LogInPasswordComponent);
|
||||||
|
|
||||||
@@ -87,10 +85,8 @@ describe('LogInPasswordComponent', () => {
|
|||||||
page = new Page(component, fixture);
|
page = new Page(component, fixture);
|
||||||
|
|
||||||
// verify the fixture is stable (no pending tasks)
|
// verify the fixture is stable (no pending tasks)
|
||||||
fixture.whenStable().then(() => {
|
await fixture.whenStable();
|
||||||
page.addPageElements();
|
page.addPageElements();
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a FormGroup comprised of FormControls', () => {
|
it('should create a FormGroup comprised of FormControls', () => {
|
||||||
|
@@ -15,6 +15,9 @@ import { AuthMethod } from '../../../../core/auth/models/auth.method';
|
|||||||
import { AuthService } from '../../../../core/auth/auth.service';
|
import { AuthService } from '../../../../core/auth/auth.service';
|
||||||
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
||||||
import { CoreState } from '../../../../core/core-state.model';
|
import { CoreState } from '../../../../core/core-state.model';
|
||||||
|
import { getForgotPasswordRoute, getRegisterRoute } from '../../../../app-routing-paths';
|
||||||
|
import { FeatureID } from '../../../../core/data/feature-authorization/feature-id';
|
||||||
|
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /users/sign-in
|
* /users/sign-in
|
||||||
@@ -66,21 +69,18 @@ export class LogInPasswordComponent implements OnInit {
|
|||||||
public form: FormGroup;
|
public form: FormGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* Whether the current user (or anonymous) is authorized to register an account
|
||||||
* @param {AuthMethod} injectedAuthMethodModel
|
|
||||||
* @param {boolean} isStandalonePage
|
|
||||||
* @param {AuthService} authService
|
|
||||||
* @param {HardRedirectService} hardRedirectService
|
|
||||||
* @param {FormBuilder} formBuilder
|
|
||||||
* @param {Store<State>} store
|
|
||||||
*/
|
*/
|
||||||
|
public canRegister$: Observable<boolean>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod,
|
@Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod,
|
||||||
@Inject('isStandalonePage') public isStandalonePage: boolean,
|
@Inject('isStandalonePage') public isStandalonePage: boolean,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private hardRedirectService: HardRedirectService,
|
private hardRedirectService: HardRedirectService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private store: Store<CoreState>
|
protected store: Store<CoreState>,
|
||||||
|
protected authorizationService: AuthorizationDataService,
|
||||||
) {
|
) {
|
||||||
this.authMethod = injectedAuthMethodModel;
|
this.authMethod = injectedAuthMethodModel;
|
||||||
}
|
}
|
||||||
@@ -115,6 +115,15 @@ export class LogInPasswordComponent implements OnInit {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.canRegister$ = this.authorizationService.isAuthorized(FeatureID.EPersonRegistration);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRegisterRoute() {
|
||||||
|
return getRegisterRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
getForgotRoute() {
|
||||||
|
return getForgotPasswordRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
<button class="btn btn-lg btn-primary btn-block mt-2 text-white" (click)="redirectToShibboleth()">
|
<button class="btn btn-lg btn-primary btn-block text-white" (click)="redirectToShibboleth()">
|
||||||
<i class="fas fa-sign-in-alt"></i> {{"login.form.shibboleth" | translate}}
|
<i class="fas fa-sign-in-alt"></i> {{"login.form.shibboleth" | translate}}
|
||||||
</button>
|
</button>
|
||||||
|
@@ -3,11 +3,8 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { Store, StoreModule } from '@ngrx/store';
|
import { StoreModule } from '@ngrx/store';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { EPerson } from '../../../../core/eperson/models/eperson.model';
|
|
||||||
import { EPersonMock } from '../../../testing/eperson.mock';
|
|
||||||
import { authReducer } from '../../../../core/auth/auth.reducer';
|
import { authReducer } from '../../../../core/auth/auth.reducer';
|
||||||
import { AuthService } from '../../../../core/auth/auth.service';
|
import { AuthService } from '../../../../core/auth/auth.service';
|
||||||
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
import { AuthServiceStub } from '../../../testing/auth-service.stub';
|
||||||
@@ -26,17 +23,14 @@ describe('LogInShibbolethComponent', () => {
|
|||||||
|
|
||||||
let component: LogInShibbolethComponent;
|
let component: LogInShibbolethComponent;
|
||||||
let fixture: ComponentFixture<LogInShibbolethComponent>;
|
let fixture: ComponentFixture<LogInShibbolethComponent>;
|
||||||
let page: Page;
|
|
||||||
let user: EPerson;
|
|
||||||
let componentAsAny: any;
|
let componentAsAny: any;
|
||||||
let setHrefSpy;
|
let setHrefSpy;
|
||||||
let shibbolethBaseUrl;
|
let shibbolethBaseUrl: string;
|
||||||
let location;
|
let location: string;
|
||||||
let initialState: any;
|
let initialState: any;
|
||||||
let hardRedirectService: HardRedirectService;
|
let hardRedirectService: HardRedirectService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
user = EPersonMock;
|
|
||||||
shibbolethBaseUrl = 'dspace-rest.test/shibboleth?redirectUrl=';
|
shibbolethBaseUrl = 'dspace-rest.test/shibboleth?redirectUrl=';
|
||||||
location = shibbolethBaseUrl + 'http://dspace-angular.test/home';
|
location = shibbolethBaseUrl + 'http://dspace-angular.test/home';
|
||||||
|
|
||||||
@@ -60,7 +54,7 @@ describe('LogInShibbolethComponent', () => {
|
|||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
// refine the test module by declaring the test component
|
// refine the test module by declaring the test component
|
||||||
TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
||||||
TranslateModule.forRoot()
|
TranslateModule.forRoot()
|
||||||
@@ -70,7 +64,7 @@ describe('LogInShibbolethComponent', () => {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AuthService, useClass: AuthServiceStub },
|
{ provide: AuthService, useClass: AuthServiceStub },
|
||||||
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Shibboleth, location) },
|
{ provide: 'authMethodProvider', useValue: new AuthMethod(AuthMethodType.Shibboleth, 0, location) },
|
||||||
{ provide: 'isStandalonePage', useValue: true },
|
{ provide: 'isStandalonePage', useValue: true },
|
||||||
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
@@ -95,7 +89,6 @@ describe('LogInShibbolethComponent', () => {
|
|||||||
componentAsAny = component;
|
componentAsAny = component;
|
||||||
|
|
||||||
// create page
|
// create page
|
||||||
page = new Page(component, fixture);
|
|
||||||
setHrefSpy = spyOnProperty(componentAsAny._window.nativeWindow.location, 'href', 'set').and.callThrough();
|
setHrefSpy = spyOnProperty(componentAsAny._window.nativeWindow.location, 'href', 'set').and.callThrough();
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -131,25 +124,3 @@ describe('LogInShibbolethComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* I represent the DOM elements and attach spies.
|
|
||||||
*
|
|
||||||
* @class Page
|
|
||||||
*/
|
|
||||||
class Page {
|
|
||||||
|
|
||||||
public emailInput: HTMLInputElement;
|
|
||||||
public navigateSpy: jasmine.Spy;
|
|
||||||
public passwordInput: HTMLInputElement;
|
|
||||||
|
|
||||||
constructor(private component: LogInShibbolethComponent, private fixture: ComponentFixture<LogInShibbolethComponent>) {
|
|
||||||
// use injector to get services
|
|
||||||
const injector = fixture.debugElement.injector;
|
|
||||||
const store = injector.get(Store);
|
|
||||||
|
|
||||||
// add spies
|
|
||||||
this.navigateSpy = spyOn(store, 'dispatch');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@@ -6,10 +6,11 @@ import { EPerson } from '../../core/eperson/models/eperson.model';
|
|||||||
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
||||||
import { AuthMethod } from '../../core/auth/models/auth.method';
|
import { AuthMethod } from '../../core/auth/models/auth.method';
|
||||||
import { hasValue } from '../empty.util';
|
import { hasValue } from '../empty.util';
|
||||||
|
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||||
|
|
||||||
export const authMethodsMock = [
|
export const authMethodsMock: AuthMethod[] = [
|
||||||
new AuthMethod('password'),
|
new AuthMethod(AuthMethodType.Password, 0),
|
||||||
new AuthMethod('shibboleth', 'dspace.test/shibboleth')
|
new AuthMethod(AuthMethodType.Shibboleth, 1, 'dspace.test/shibboleth'),
|
||||||
];
|
];
|
||||||
|
|
||||||
export class AuthServiceStub {
|
export class AuthServiceStub {
|
||||||
|
@@ -2560,8 +2560,6 @@
|
|||||||
|
|
||||||
"login.form.new-user": "New user? Click here to register.",
|
"login.form.new-user": "New user? Click here to register.",
|
||||||
|
|
||||||
"login.form.or-divider": "or",
|
|
||||||
|
|
||||||
"login.form.oidc": "Log in with OIDC",
|
"login.form.oidc": "Log in with OIDC",
|
||||||
|
|
||||||
"login.form.orcid": "Log in with ORCID",
|
"login.form.orcid": "Log in with ORCID",
|
||||||
|
Reference in New Issue
Block a user