ecm user check and code refactorization

This commit is contained in:
SheenaMalhotra182
2023-05-04 15:34:26 +05:30
committed by Sheena Malhotra
parent 07f44dde89
commit 26fbcca7a2
14 changed files with 240 additions and 222 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
"bpmHost": "{protocol}//{hostname}{:port}", "bpmHost": "{protocol}//{hostname}{:port}",
"identityHost": "{protocol}//{hostname}{:port}/auth/admin/realms/alfresco", "identityHost": "{protocol}//{hostname}{:port}/auth/admin/realms/alfresco",
"loginRoute": "login", "loginRoute": "login",
"providers": "ALL", "providers": "ECM",
"contextRootBpm": "activiti-app", "contextRootBpm": "activiti-app",
"authType": "BASIC", "authType": "BASIC",
"locale": "en", "locale": "en",
@@ -28,6 +28,15 @@
{{ 'LOGIN.SHOW_REMEMBERME'| translate }} {{ 'LOGIN.SHOW_REMEMBERME'| translate }}
</mat-slide-toggle> </mat-slide-toggle>
</p> </p>
<p class="app-toggle">
<mat-slide-toggle
id="adf-toggle-show-forgot-password"
color="primary"
(change)="toggleForgotPassword()"
[checked]="showForgotPassword">
{{ 'LOGIN.FORGOT-PASSWORD.FORGOT-PASSWORD' | translate }}
</mat-slide-toggle>
</p>
<p class="app-toggle"> <p class="app-toggle">
<mat-slide-toggle <mat-slide-toggle
id="adf-toggle-show-successRoute" id="adf-toggle-show-successRoute"
@@ -81,6 +90,7 @@
[logoImageUrl]="customLogoImageURL" [logoImageUrl]="customLogoImageURL"
[showLoginActions]="showFooter" [showLoginActions]="showFooter"
[showRememberMe]="showFooter && showRememberMe" [showRememberMe]="showFooter && showRememberMe"
[showForgotPassword]="showForgotPassword"
copyrightText="{{ 'application.copyright' | adfAppConfig }}" copyrightText="{{ 'application.copyright' | adfAppConfig }}"
(success)="onLogin()" (success)="onLogin()"
(error)="onError($event)"> (error)="onError($event)">
@@ -33,6 +33,7 @@ export class LoginComponent {
disableCsrf = false; disableCsrf = false;
showFooter = true; showFooter = true;
showRememberMe = true; showRememberMe = true;
showForgotPassword = true;
customSuccessRoute = false; customSuccessRoute = false;
customLogoImage = false; customLogoImage = false;
@@ -60,6 +61,10 @@ export class LoginComponent {
this.showRememberMe = !this.showRememberMe; this.showRememberMe = !this.showRememberMe;
} }
toggleForgotPassword() {
this.showForgotPassword = !this.showForgotPassword;
}
toggleSuccessRoute() { toggleSuccessRoute() {
this.customSuccessRoute = !this.customSuccessRoute; this.customSuccessRoute = !this.customSuccessRoute;
if (!this.customSuccessRoute) { if (!this.customSuccessRoute) {
@@ -1,71 +1,53 @@
<div class="forgot-password-div" *ngIf="!passwordResetStatus"> <div class="adf-forgot-password" *ngIf="!passwordResetStatus">
<mat-card>
<mat-card-header>
<mat-card-title class="adf-forgot-password-title">
{{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }}
</mat-card-title>
</mat-card-header>
<hr>
<mat-card> <mat-card-content>
<p class="adf-forgot-password-filler">{{ 'RECOVER-PASSWORD.MESSAGES.FILLER' | translate }}</p>
<form [formGroup]="forgotPasswordForm">
<div class="adf-orgot-paassword-form-field">
<label class="adf-forgot-password-label">
{{ 'RECOVER-PASSWORD.MESSAGES.ENTER-USERNAME' | translate }}
</label>
<mat-card-header> <input class="adf-forgot-password-field" placeholder="{{ 'RECOVER-PASSWORD.PLACEHOLDERS.USERNAME' | translate }}"
<mat-card-title class="forgot-password-title"> formControlName="userName" required>
{{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }}
</mat-card-title>
</mat-card-header>
<hr>
<mat-card-content>
<p class="filler">{{ 'RECOVER-PASSWORD.MESSAGES.FILLER' | translate }}</p>
<form [formGroup]="forgotPasswordForm">
<div class="forgot-paassword-form-field">
<label class="forgot-password-label">
{{ 'RECOVER-PASSWORD.MESSAGES.ENTER-USERNAME' | translate }}
</label>
<input class="forgot-password-field"
placeholder="{{ 'RECOVER-PASSWORD.PLACEHOLDERS.USERNAME' | translate }}" formControlName="userName"
required>
</div>
<button type="button" (click)="sendInstructions()" class="send-instructions-button"
[attr.aria-label]="'RECOVER-PASSWORD.BUTTONS.SEND-INSTRUCTIONS' | translate"
[disabled]="isButtonDisabled()" mat-raised-button color="primary">
{{ 'RECOVER-PASSWORD.BUTTONS.SEND-INSTRUCTIONS' | translate }}
</button>
<button mat-button class="close-button" (click)="close()">{{ 'RECOVER-PASSWORD.BUTTONS.CLOSE' | translate }}</button>
</form>
</mat-card-content>
</mat-card>
</div>
<div class="forgot-password-div" *ngIf="passwordResetStatus">
<mat-card>
<mat-card-header>
<mat-card-title class="forgot-password-title">
{{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }}
</mat-card-title>
</mat-card-header>
<hr>
<mat-card-content>
<div>
<p class="password-reset-link-message">
{{ 'RECOVER-PASSWORD.MESSAGES.RESET-PASSWORD-EMAIL-SENT' | translate }}
</p>
</div> </div>
<button mat-button class="close-button" (click)="close()">{{ 'RECOVER-PASSWORD.BUTTONS.CLOSE' | translate }}</button> <button type="button" (click)="sendInstructions()" class="adf-send-instructions-button"
[attr.aria-label]="'RECOVER-PASSWORD.BUTTONS.SEND-INSTRUCTIONS' | translate" [disabled]="isButtonDisabled()"
mat-raised-button color="primary">
{{ 'RECOVER-PASSWORD.BUTTONS.SEND-INSTRUCTIONS' | translate }}
</button>
<button mat-button class="adf-close-button" (click)="close()">{{ 'RECOVER-PASSWORD.BUTTONS.CLOSE' | translate}}</button>
</form>
</mat-card-content>
</mat-card>
</div>
</mat-card-content> <div class="adf-forgot-password" *ngIf="passwordResetStatus">
<mat-card>
<mat-card-header>
<mat-card-title class="adf-forgot-password-title">
{{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }}
</mat-card-title>
</mat-card-header>
<hr>
</mat-card> <mat-card-content>
<div>
<p class="adf-password-reset-link-message">
{{ 'RECOVER-PASSWORD.MESSAGES.RESET-PASSWORD-EMAIL-SENT' | translate }}
</p>
</div>
</div> <button mat-button class="adf-close-button" (click)="close()">{{ 'RECOVER-PASSWORD.BUTTONS.CLOSE' | translate}}</button>
</mat-card-content>
</mat-card>
</div>
@@ -1,129 +1,111 @@
.forgot-password-div { .adf-forgot-password {
width: 100%;
height: 100vh;
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: fixed; min-height: 100vh;
top: 0;
left: 0;
transform: translate(calc(50vw - 50%));
border-radius: 12px; border-radius: 12px;
background-color: var(--theme-forgot-password-background); background-color: var(--theme-forgot-password-background);
mat-card {
padding: 24px;
width: 371px;
}
::ng-deep .mat-card-header-text {
margin: 0 !important;
}
.adf-forgot-password-title {
font-style: normal;
font-weight: 400;
font-size: 20px;
line-height: 28px;
letter-spacing: 0.15px;
color: var(--theme-forgot-password-title-color);
padding: 2px 0;
margin: 0;
}
hr {
margin: 12px 0;
}
.adf-forgot-password-filler {
display: flex;
align-items: center;
padding: 8px 0;
height: 16px;
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
letter-spacing: 0.5px;
color: var(--theme-forgot-password-label-color);
margin: 0 0 8px;
}
.adf-forgot-password-form-field {
height: 64px;
margin-top: 24px;
}
.adf-forgot-password-label {
height: 32px;
padding: 6px 0;
font-style: normal;
font-weight: 700;
font-size: 14px;
line-height: 20px;
letter-spacing: 0.15px;
color: var(--theme-forgot-password-title-color);
}
.adf-forgot-password-field {
text-decoration: none;
height: 32px;
line-height: 32px;
background: var(--theme-forgot-password-input-background-color);
border-radius: 6px;
width: 100%;
border: none;
outline: none;
margin-top: 10px;
padding: 0 6px;
}
.adf-send-instructions-button {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 4px 12px;
height: 32px;
background: var(--theme-forgot-password-button-background-color);
border-radius: 6px;
margin: 24px 0 0;
}
.adf-close-button {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--theme-forgot-password-input-background-color);
color: var(--theme-forgot-password-title-color);
margin-top: 8px;
padding: 4px 12px;
height: 32px;
border-radius: 6px;
}
.adf-password-reset-link-message {
height: 52px;
padding: 6px 0;
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 20px;
letter-spacing: 0.25px;
color: var(--theme-forgot-password-title-color);
}
} }
mat-card {
padding: 24px 24px;
width: 371px;
//height: 264px;
}
::ng-deep .mat-card-header-text {
margin: 0 !important;
}
.forgot-password-title {
font-style: normal;
font-weight: 400;
font-size: 20px;
line-height: 28px;
letter-spacing: 0.15px;
color: var(--theme-forgot-password-title-color);
padding: 2px 0;
margin: 0 !important;
}
hr {
margin: 12px 0;
}
.filler {
display: flex;
flex-direction: row;
align-items: center;
padding: 8px 0px;
height: 16px;
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
letter-spacing: 0.5px;
color: var(--theme-forgot-password-label-color);
margin: 0 0 8px 0;
}
.forgot-password-form-field {
height: 64px;
margin-top: 24px;
}
.forgot-password-label {
height: 32px;
padding: 6px 0;
font-style: normal;
font-weight: 700;
font-size: 14px;
line-height: 20px;
letter-spacing: 0.15px;
color: var(--theme-forgot-password-title-color);
}
.forgot-password-field {
text-decoration: none;
height: 32px;
line-height: 32px;
background: var(--theme-forgot-password-input-background-color);
border-radius: 6px;
width: 100%;
border: none !important;
outline: none;
margin-top: 10px !important;
}
.send-instructions-button {
width: 100% !important;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 4px 12px;
height: 32px;
background: var(--theme-forgot-password-button-background-color);
border-radius: 6px;
margin: 24px 0 0 0 !important;
}
.close-button {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: var(--theme-forgot-password-input-background-color);
color: var(--theme-forgot-password-title-color);
margin-top: 8px;
padding: 4px 12px;
height: 32px;
border-radius: 6px;
}
.password-reset-link-message {
height: 52px;
padding: 6px 0;
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 20px;
letter-spacing: 0.25px;
color: var(--theme-forgot-password-title-color);
}
@@ -20,7 +20,6 @@ import { Router } from '@angular/router';
import { CoreTestingModule } from '../testing/core.testing.module'; import { CoreTestingModule } from '../testing/core.testing.module';
import { ForgotPasswordComponent } from './forgot-password.component'; import { ForgotPasswordComponent } from './forgot-password.component';
describe('ResetPasswordComponent', () => { describe('ResetPasswordComponent', () => {
let component: ForgotPasswordComponent; let component: ForgotPasswordComponent;
let fixture: ComponentFixture<ForgotPasswordComponent>; let fixture: ComponentFixture<ForgotPasswordComponent>;
@@ -30,7 +29,6 @@ describe('ResetPasswordComponent', () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule], imports: [CoreTestingModule],
declarations: [ForgotPasswordComponent], declarations: [ForgotPasswordComponent],
providers: []
}); });
fixture = TestBed.createComponent(ForgotPasswordComponent); fixture = TestBed.createComponent(ForgotPasswordComponent);
@@ -39,37 +37,27 @@ describe('ResetPasswordComponent', () => {
router = TestBed.inject(Router); router = TestBed.inject(Router);
}); });
it('should be created', () => { afterEach(() => {
expect(component).toBeTruthy(); fixture.destroy();
}); });
it('send instructions button should be disabled by default', async () => { it('send instructions button should be disabled by default', async () => {
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
expect(component.isButtonDisabled).toBeTruthy(); expect(component.isButtonDisabled).toBeTruthy();
}); });
it('send instructions button should be disabled if username field is empty', async () => { it('send instructions button should be disabled if username field is empty', async () => {
component.ngOnInit();
component.forgotPasswordForm.controls['userName'].setValue(''); component.forgotPasswordForm.controls['userName'].setValue('');
fixture.detectChanges();
await fixture.whenStable();
expect(component.isButtonDisabled).toBeTruthy(); expect(component.isButtonDisabled).toBeTruthy();
}); });
it('send instructions button should be enabled when username field is not empty', async () => { it('send instructions button should be enabled when username field is not empty', async () => {
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
component.forgotPasswordForm.controls['userName'].setValue('userABC'); component.forgotPasswordForm.controls['userName'].setValue('userABC');
spyOn(component, 'isButtonDisabled').and.callThrough(); spyOn(component, 'isButtonDisabled').and.callThrough();
const sendInstructionsBtn = fixture.debugElement.nativeElement.querySelector('.send-instructions-button'); const sendInstructionsBtn = fixture.debugElement.nativeElement.querySelector('.adf-send-instructions-button');
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
@@ -79,37 +67,28 @@ describe('ResetPasswordComponent', () => {
}); });
it('should send instructions to the email id corresponding to the username when the send instructions button is clicked', async () => { it('should send instructions to the email id corresponding to the username when the send instructions button is clicked', async () => {
component.ngOnInit();
component.forgotPasswordForm.controls['userName'].setValue('userABC'); component.forgotPasswordForm.controls['userName'].setValue('userABC');
spyOn(component, 'sendInstructions').and.callThrough(); spyOn(component, 'sendInstructions').and.callThrough();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
const sendInstructionsBtn = fixture.debugElement.nativeElement.querySelector('.send-instructions-button'); const sendInstructionsBtn = fixture.debugElement.nativeElement.querySelector('.adf-send-instructions-button');
sendInstructionsBtn.dispatchEvent(new Event('click')); sendInstructionsBtn.dispatchEvent(new Event('click'));
fixture.detectChanges();
await fixture.whenStable();
expect(component.sendInstructions).toHaveBeenCalled(); expect(component.sendInstructions).toHaveBeenCalled();
}); });
it('should route user back to login page when the close button is clicked', async () => { it('should route user back to login page when the close button is clicked', async () => {
component.ngOnInit();
spyOn(component, 'close').and.callThrough(); spyOn(component, 'close').and.callThrough();
spyOn(router, 'navigate'); spyOn(router, 'navigate');
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
const closeBtn = fixture.debugElement.nativeElement.querySelector('.close-button'); const closeBtn = fixture.debugElement.nativeElement.querySelector('.adf-close-button');
closeBtn.dispatchEvent(new Event('click')); closeBtn.dispatchEvent(new Event('click'));
fixture.detectChanges();
await fixture.whenStable();
expect(component.close).toHaveBeenCalled(); expect(component.close).toHaveBeenCalled();
expect(router.navigate).toHaveBeenCalledWith(['./login']); expect(router.navigate).toHaveBeenCalledWith(['./login']);
}); });
@@ -9,7 +9,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { PeopleApi, ClientBody } from '@alfresco/js-api'; import { PeopleApi, ClientBody } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '../services/alfresco-api.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@Component({ @Component({
+18
View File
@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './public-api';
@@ -0,0 +1,19 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './forgot-password.module';
export * from './forgot-password.component';
@@ -168,8 +168,8 @@
{{ 'LOGIN.LABEL.REMEMBER' | translate }} {{ 'LOGIN.LABEL.REMEMBER' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
<div class="adf-login-action"> <div *ngIf="showForgotPassword && isECMProvider()" class="adf-login-action">
<div id="adf-login-action" class="adf-login-action adf-full-width"> <div id="adf-login-forgot-password">
<a class="adf-login-forgot-password-link" (click)="forgotPassword()"> <a class="adf-login-forgot-password-link" (click)="forgotPassword()">
{{ 'LOGIN.FORGOT-PASSWORD.FORGOT-PASSWORD' | translate }} {{ 'LOGIN.FORGOT-PASSWORD.FORGOT-PASSWORD' | translate }}
</a> </a>
@@ -306,6 +306,20 @@ describe('LoginComponent', () => {
})); }));
}); });
describe('Forgot password', () => {
it('should route user to forgot password component', async () => {
spyOn(component, 'forgotPassword').and.callThrough();
spyOn(router, 'navigate');
const forgotPasswordLink = fixture.debugElement.nativeElement.querySelector('.adf-login-forgot-password-link');
forgotPasswordLink.dispatchEvent(new Event('click'));
expect(component.forgotPassword).toHaveBeenCalled();
expect(router.navigate).toHaveBeenCalledWith(['./forgot-password']);
});
});
it('should render Login form with all the keys to be translated', () => { it('should render Login form with all the keys to be translated', () => {
expect(element.querySelector('[for="username"]')).toBeDefined(); expect(element.querySelector('[for="username"]')).toBeDefined();
expect(element.querySelector('[for="username"]').innerText).toEqual('LOGIN.LABEL.USERNAME'); expect(element.querySelector('[for="username"]').innerText).toEqual('LOGIN.LABEL.USERNAME');
@@ -68,6 +68,10 @@ export class LoginComponent implements OnInit, OnDestroy {
@Input() @Input()
showRememberMe: boolean = true; showRememberMe: boolean = true;
/** Should the Forgot Password link be shown? */
@Input()
showForgotPassword: boolean = true;
/** Should the extra actions (`Need Help`, `Register`, etc) be shown? */ /** Should the extra actions (`Need Help`, `Register`, etc) be shown? */
@Input() @Input()
showLoginActions: boolean = true; showLoginActions: boolean = true;
@@ -192,6 +196,10 @@ export class LoginComponent implements OnInit, OnDestroy {
this.router.navigate(['./forgot-password']); this.router.navigate(['./forgot-password']);
} }
isECMProvider() {
return this.authService.isECMProvider();
}
redirectToImplicitLogin() { redirectToImplicitLogin() {
this.alfrescoApiService.getInstance().oauth2Auth.implicitLogin(); this.alfrescoApiService.getInstance().oauth2Auth.implicitLogin();
} }
+1 -1
View File
@@ -100,7 +100,7 @@
--theme-forgot-password-title-color: #212121, --theme-forgot-password-title-color: #212121,
--theme-forgot-password-label-color: rgba(33, 35, 40, 0.7), --theme-forgot-password-label-color: rgba(33, 35, 40, 0.7),
--theme-forgot-password-input-background-color: rgba(33, 33, 33, 0.05), --theme-forgot-password-input-background-color: rgba(33, 33, 33, 0.05),
--theme-forgot-password-button-background-color: #1F74DB, --theme-forgot-password-button-background-color: #1f74db,
--theme-forgot-password-dialog-border-color: rgba(33, 33, 33, 0.12), --theme-forgot-password-dialog-border-color: rgba(33, 33, 33, 0.12),
--theme-forgot-password-dialog-shadow-color: rgba(33, 35, 40, 0.06), --theme-forgot-password-dialog-shadow-color: rgba(33, 35, 40, 0.06),
+1
View File
@@ -20,6 +20,7 @@ export * from './lib/viewer/index';
export * from './lib/toolbar/index'; export * from './lib/toolbar/index';
export * from './lib/pagination/index'; export * from './lib/pagination/index';
export * from './lib/login/index'; export * from './lib/login/index';
export * from './lib/forgot-password/index';
export * from './lib/language-menu/index'; export * from './lib/language-menu/index';
export * from './lib/info-drawer/index'; export * from './lib/info-drawer/index';
export * from './lib/identity-user-info/index'; export * from './lib/identity-user-info/index';