Skip to content

Commit 502f6c0

Browse files
Andrea Barbassoatarix83
authored andcommitted
Merged in task/dspace-cris-2023_02_x/DSC-2401 (pull request DSpace#3347)
[DSC-2401] add options to disable the standard login Approved-by: Giuseppe Digilio
2 parents 0b202e8 + 3945ea3 commit 502f6c0

7 files changed

Lines changed: 110 additions & 18 deletions

File tree

config/config.example.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ auth:
132132
# If the rest token expires in less than this amount of time, it will be refreshed automatically.
133133
# This is independent from the idle warning.
134134
timeLeftBeforeTokenRefresh: 120000 # 2 minutes
135+
# Standard login enabled
136+
disableStandardLogin: false
135137

136138
# Form settings
137139
form:

src/app/app-routing.module.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone
4545
import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-check-guard.guard';
4646
import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths';
4747
import { RedirectService } from './redirect/redirect.service';
48+
import { environment } from '../environments/environment';
4849
import {
4950
GenericAdministratorGuard
5051
} from './core/data/feature-authorization/feature-authorization-guard/generic-administrator-guard';
@@ -177,10 +178,20 @@ import {
177178
.then((m) => m.AdminModule),
178179
canActivate: [GenericAdministratorGuard, EndUserAgreementCurrentUserGuard]
179180
},
181+
{
182+
path: 'standard-login',
183+
loadChildren: () => import('./login-page/login-page.module').then((m) => m.LoginPageModule),
184+
data: {
185+
isBackDoor: true,
186+
},
187+
},
180188
{
181189
path: 'login',
182-
loadChildren: () => import('./login-page/login-page.module')
183-
.then((m) => m.LoginPageModule)
190+
loadChildren: () => import('./login-page/login-page.module').then((m) => m.LoginPageModule),
191+
data: {
192+
isBackDoor: false,
193+
},
194+
canMatch: [() => !environment.auth.disableStandardLogin],
184195
},
185196
{
186197
path: 'external-login/:token',

src/app/shared/log-in/log-in.component.spec.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { AuthorizationDataService } from '../../core/data/feature-authorization/
2323
import { of } from 'rxjs';
2424
import { ThemeService } from '../theme-support/theme.service';
2525
import { getMockThemeService } from '../mocks/theme-service.mock';
26+
import { AuthMethodType } from 'src/app/core/auth/models/auth.method-type';
2627

2728
describe('LogInComponent', () => {
2829

@@ -129,6 +130,59 @@ describe('LogInComponent', () => {
129130
expect(loginContainers.length).toBe(2);
130131

131132
});
133+
134+
it('returns only password method when backdoor is enabled', () => {
135+
const authMethods = [
136+
{ authMethodType: AuthMethodType.Password, position: 1 },
137+
{ authMethodType: AuthMethodType.Ip, position: 2 },
138+
{ authMethodType: AuthMethodType.Shibboleth, position: 3 },
139+
];
140+
const isBackdoor = true;
141+
component.excludedAuthMethod = undefined;
142+
const result = component.filterAndSortAuthMethods(authMethods, isBackdoor);
143+
expect(result).toEqual([{ authMethodType: AuthMethodType.Password, position: 1 }]);
144+
});
145+
146+
it('excludes password method when standard login is disabled', () => {
147+
const authMethods = [
148+
{ authMethodType: AuthMethodType.Password, position: 1 },
149+
{ authMethodType: AuthMethodType.Shibboleth, position: 2 },
150+
];
151+
component.excludedAuthMethod = undefined;
152+
const result = component.filterAndSortAuthMethods(authMethods, false, true);
153+
expect(result).toEqual([
154+
{ authMethodType: AuthMethodType.Shibboleth, position: 2 },
155+
]);
156+
});
157+
158+
it('excludes methods based on excludedAuthMethod input', () => {
159+
const authMethods = [
160+
{ authMethodType: AuthMethodType.Password, position: 1 },
161+
{ authMethodType: AuthMethodType.Ip, position: 2 },
162+
{ authMethodType: AuthMethodType.Shibboleth, position: 3 },
163+
];
164+
const isBackdoor = false;
165+
component.excludedAuthMethod = AuthMethodType.Ip;
166+
const result = component.filterAndSortAuthMethods(authMethods, isBackdoor);
167+
expect(result).toEqual([
168+
{ authMethodType: AuthMethodType.Password, position: 1 },
169+
{ authMethodType: AuthMethodType.Shibboleth, position: 3 },
170+
]);
171+
});
172+
173+
it('sorts methods by position', () => {
174+
const authMethods = [
175+
{ authMethodType: AuthMethodType.Password, position: 2 },
176+
{ authMethodType: AuthMethodType.Shibboleth, position: 1 },
177+
];
178+
const isBackdoor = false;
179+
component.excludedAuthMethod = undefined;
180+
const result = component.filterAndSortAuthMethods(authMethods, isBackdoor);
181+
expect(result).toEqual([
182+
{ authMethodType: AuthMethodType.Shibboleth, position: 1 },
183+
{ authMethodType: AuthMethodType.Password, position: 2 },
184+
]);
185+
});
132186
});
133187

134188
});

src/app/shared/log-in/log-in.component.ts

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core';
2-
import { Observable, Subscription, combineLatest } from 'rxjs';
32
import { filter, map, shareReplay } from 'rxjs/operators';
43
import { select, Store } from '@ngrx/store';
5-
import uniqBy from 'lodash/uniqBy';
6-
74
import { AuthMethod } from '../../core/auth/models/auth.method';
85
import {
96
getAuthenticationError,
@@ -19,6 +16,10 @@ import { rendersAuthMethodType } from './methods/log-in.methods-decorator';
1916
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
2017
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
2118
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
19+
import { ActivatedRoute } from '@angular/router';
20+
import uniqBy from 'lodash/uniqBy';
21+
import { environment } from '../../../environments/environment';
22+
import { combineLatestWith, Observable, Subscription } from 'rxjs';
2223

2324
@Component({
2425
selector: 'ds-log-in',
@@ -84,19 +85,20 @@ export class LogInComponent implements OnInit, OnDestroy {
8485

8586
constructor(private store: Store<CoreState>,
8687
private authService: AuthService,
88+
private route: ActivatedRoute,
8789
protected authorizationService: AuthorizationDataService
8890
) {
8991
}
9092

9193
ngOnInit(): void {
9294
this.authMethods = this.store.pipe(
9395
select(getAuthenticationMethods),
94-
map((methods: AuthMethod[]) => methods
95-
// ignore the given auth method if it should be excluded
96-
.filter((authMethod: AuthMethod) => authMethod.authMethodType !== this.excludedAuthMethod)
97-
.filter((authMethod: AuthMethod) => rendersAuthMethodType(authMethod.authMethodType) !== undefined)
98-
.sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position),
99-
),
96+
combineLatestWith(
97+
this.route.data.pipe(
98+
filter(routeData => !!routeData),
99+
map(data => data.isBackDoor),
100+
)),
101+
map(([methods, isBackdoor]) => this.filterAndSortAuthMethods(methods, isBackdoor, environment.auth.disableStandardLogin)),
100102
// ignore the ip authentication method when it's returned by the backend
101103
map((authMethods: AuthMethod[]) => uniqBy(authMethods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType'))
102104
);
@@ -117,12 +119,30 @@ export class LogInComponent implements OnInit, OnDestroy {
117119
this.canRegister$ = this.authorizationService.isAuthorized(FeatureID.EPersonRegistration);
118120

119121
this.canForgot$ = this.authorizationService.isAuthorized(FeatureID.EPersonForgotPassword).pipe(shareReplay(1));
120-
this.canShowDivider$ =
121-
combineLatest([this.canRegister$, this.canForgot$])
122-
.pipe(
123-
map(([canRegister, canForgot]) => canRegister || canForgot),
124-
filter(Boolean)
125-
);
122+
this.canShowDivider$ = this.canRegister$.pipe(
123+
combineLatestWith(this.canForgot$),
124+
map(([canRegister, canForgot]) => canRegister || canForgot),
125+
filter(Boolean)
126+
);
127+
}
128+
129+
filterAndSortAuthMethods(authMethods: AuthMethod[], isBackdoor: boolean, isStandardLoginDisabled = false): AuthMethod[] {
130+
return authMethods.filter((authMethod: AuthMethod) => {
131+
const methodComparison = (authM) => {
132+
if (isBackdoor) {
133+
return authM.authMethodType === AuthMethodType.Password;
134+
}
135+
if (isStandardLoginDisabled) {
136+
return authM.authMethodType !== AuthMethodType.Password;
137+
}
138+
return true;
139+
140+
};
141+
return methodComparison(authMethod) &&
142+
authMethod.authMethodType !== this.excludedAuthMethod &&
143+
rendersAuthMethodType(authMethod.authMethodType) !== undefined;
144+
},
145+
).sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position);
126146
}
127147

128148
getRegisterRoute() {

src/config/auth-config.interfaces.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@ export interface AuthConfig extends Config {
2020
// This is independent from the idle warning.
2121
timeLeftBeforeTokenRefresh: number;
2222
};
23+
24+
// Whether the standard login form should be enabled.
25+
disableStandardLogin?: boolean;
2326
}

src/config/default-app-config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ export class DefaultAppConfig implements AppConfig {
135135
// If the rest token expires in less than this amount of time, it will be refreshed automatically.
136136
// This is independent from the idle warning.
137137
timeLeftBeforeTokenRefresh: 2 * 60 * 1000 // 2 minutes
138-
}
138+
},
139+
disableStandardLogin: false, // Enable the standard login form
139140
};
140141

141142
// Form settings

src/environments/environment.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export const environment: BuildConfig = {
9797
// This is independent from the idle warning.
9898
timeLeftBeforeTokenRefresh: 20000, // 20 sec
9999
},
100+
disableStandardLogin: false,
100101
},
101102

102103
// Form settings

0 commit comments

Comments
 (0)