Feature 10914: Enforce Password change on First login

	* Added NG-UI support to Enforce Password change on First login
	* A popup will be opened on First login with current password, new password and confirm password fields
	* Once new password is entered, Click apply button
	* The popup is closed & redirected to Login page.
	* Sign in using the new password.

Change-Id: I9ee6bf923e897b40d06a1781cdd7d044b171c825
Signed-off-by: SANDHYA.JS <sandhya.j@tataelxsi.co.in>
diff --git a/src/app/users/UsersModule.ts b/src/app/users/UsersModule.ts
index 2014c48..8b5f316 100644
--- a/src/app/users/UsersModule.ts
+++ b/src/app/users/UsersModule.ts
@@ -28,7 +28,7 @@
 import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
 import { NgSelectModule } from '@ng-select/ng-select';
 import { TranslateModule } from '@ngx-translate/core';
-import { AddEditUserComponent } from 'AddEditUserComponent';
+import { ChangePasswordModule } from 'ChangePasswordModule';
 import { DataService } from 'DataService';
 import { LoaderModule } from 'LoaderModule';
 import { Ng2SmartTableModule } from 'ng2-smart-table';
@@ -60,10 +60,11 @@
  */
 @NgModule({
     imports: [ReactiveFormsModule, FormsModule, CommonModule, HttpClientModule, Ng2SmartTableModule, TranslateModule,
-        FlexLayoutModule, NgSelectModule, NgbModule, RouterModule.forChild(routes), PagePerRowModule, LoaderModule, PageReloadModule],
-    declarations: [UsersComponent, UserDetailsComponent, AddEditUserComponent, ProjectRoleComponent],
+        FlexLayoutModule, NgSelectModule, NgbModule, RouterModule.forChild(routes), PagePerRowModule, LoaderModule,
+        PageReloadModule, ChangePasswordModule],
+    declarations: [UsersComponent, UserDetailsComponent, ProjectRoleComponent],
     providers: [DataService],
-    entryComponents: [AddEditUserComponent, ProjectRoleComponent]
+    entryComponents: [ProjectRoleComponent]
 })
 /** Exporting a class @exports UsersModule */
 export class UsersModule {
diff --git a/src/app/users/add-user/AddEditUserComponent.html b/src/app/users/add-user/AddEditUserComponent.html
index 8c496cc..d3a0b08 100644
--- a/src/app/users/add-user/AddEditUserComponent.html
+++ b/src/app/users/add-user/AddEditUserComponent.html
@@ -15,75 +15,105 @@
 
 Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
 -->
-<form [formGroup]="userForm" (ngSubmit)="userAction(userType)" autocomplete="off">
-  <div class="modal-header">
-    <h4 class="modal-title" id="modal-basic-title">{{userTitle}}</h4>
-    <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
-      <i class="fas fa-times-circle text-danger"></i>
-    </button>
-  </div>
-  <div class="modal-body">
-    <label class="col-sm-12 col-form-label mandatory-label"
-      [ngClass]="{'text-danger': userForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
-    <div class="row form-group" *ngIf="userType === 'add' || userType === 'editUserName'">
-      <div class="col-sm-4">
-        <label for="userName">{{'PAGE.USERS.USERNAME' | translate}} *</label>
-      </div>
-      <div class="col-sm-8">
-        <input class="form-control" placeholder="{{'PAGE.USERS.USERNAME' | translate}}" type="text"
-          formControlName="userName" id="userName" [ngClass]="{ 'is-invalid': submitted && f.userName.errors }"
-          required>
-      </div>
-      <div *ngIf="submitted && f.userName.errors" class="input-validation-msg">
-        <div *ngIf="f.userName.errors.minlength">
-          {{'PAGE.LOGIN.USERNAMEMINLENGTHVALIDMESSAGE' | translate}} </div>
-      </div>
+<div class="wrap-user" [ngClass]="{'change-password': isPassword}">
+  <form [formGroup]="userForm" (ngSubmit)="userAction(userType)" autocomplete="off">
+    <div class="modal-header">
+      <h4 class="modal-title" id="modal-basic-title">{{userTitle}}</h4>
+      <button *ngIf="!isFirstLogin" class="button-xs" type="button" class="close" aria-label="Close"
+        (click)="activeModal.close()">
+        <i class="fas fa-times-circle text-danger"></i>
+      </button>
     </div>
-    <ng-container *ngIf="userType === 'add' || userType === 'editPassword'">
-      <div class="row form-group">
+    <div class="modal-body">
+      <label class="col-sm-12 col-form-label mandatory-label"
+        [ngClass]="{'text-danger': userForm.invalid === true && submitted === true,'message': isPassword && userForm.invalid === true && submitted  }">{{'MANDATORYCHECK'|
+        translate}}</label>
+      <div class="row form-group" *ngIf="userType === 'add' || userType === 'editUserName'">
         <div class="col-sm-4">
-          <label for="password">{{'PAGE.USERS.PASSWORD' | translate}} *</label>
+          <label for="userName">{{'PAGE.USERS.USERNAME' | translate}} *</label>
         </div>
         <div class="col-sm-8">
-          <input class="form-control" placeholder="{{'PAGE.USERS.PASSWORD' | translate}}" minlength="8" maxlength="50"
-            type="password" formControlName="password" id="password" autocomplete="new-password"
-            [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+          <input class="form-control" placeholder="{{'PAGE.USERS.USERNAME' | translate}}" type="text"
+            formControlName="userName" id="userName" [ngClass]="{ 'is-invalid': submitted && f.userName.errors }"
+            required>
         </div>
-        <div class="input-validation-msg">
-          <div *ngIf="userForm?.controls.password.hasError('minlength') || userForm?.controls.password.errors?.pattern">
-            {{'PAGE.LOGIN.PASSWORDMINLENGTHVALIDMESSAGE' | translate}} </div>
+        <div *ngIf="submitted && f.userName.errors" class="input-validation-msg">
+          <div *ngIf="f.userName.errors.minlength">
+            {{'PAGE.LOGIN.USERNAMEMINLENGTHVALIDMESSAGE' | translate}} </div>
         </div>
       </div>
-      <div class="row form-group">
-        <div class="col-sm-4">
-          <label for="password2">{{'PAGE.USERS.CONFPASSWORD' | translate}} *</label>
-        </div>
-        <div class="col-sm-8">
-          <input class="form-control" placeholder="{{'PAGE.USERS.CONFPASSWORD' | translate}}" type="password"
-            formControlName="password2" id="password2" autocomplete="new-password"
-            [ngClass]="{ 'is-invalid': submitted && f.password2.errors }" required>
-          <div class="mr-top-5" *ngIf="userForm?.controls.password.value && userForm?.controls.password2.value">
-            <i class="far"
-              [ngClass]="{'fa-times-circle text-danger':userForm?.controls.password.value !== userForm?.controls.password2.value,
-            'fa-check-circle text-success':userForm?.controls.password.value === userForm?.controls.password2.value}"></i>
-            {{'PAGE.USERS.PASSWORDMATCH' | translate}}
+      <ng-container *ngIf="userType === 'add' || userType === 'editPassword' || userType === 'changePassword'">
+        <div class="row form-group" *ngIf=" userType === 'changePassword'">
+          <div class="col-sm-4">
+            <label for="oldpassword">{{'PAGE.USERS.OLDPASSWORD' | translate}} *</label>
+          </div>
+          <div class="col-sm-8">
+            <input class="form-control" placeholder="{{'PAGE.USERS.OLDPASSWORD' | translate}}" type="password"
+              formControlName="old_password" id="old_password" autocomplete="old-password"
+              [ngClass]="{ 'is-invalid': submitted && f.old_password.errors }" required>
           </div>
         </div>
-      </div>
-    </ng-container>
-    <div class="form-group row" *ngIf="userType === 'add'">
-      <label class="col-sm-4 col-form-label">{{'DOMAIN' | translate}} {{'NAME' | translate}}</label>
-      <div class="col-sm-8">
-        <ng-select [clearable]="false" placeholder="{{'SELECT' | translate}}" [items]="domains" bindLabel="title"
-          bindValue="value" formControlName="domain_name" id="domain_name"
-          [ngClass]="{ 'is-invalid': submitted && f.domain_name.errors }"></ng-select>
+        <div class="row form-group" *ngIf="userType === 'add' || userType === 'editPassword'">
+          <div class="col-sm-4">
+            <label for="password">{{'PAGE.USERS.PASSWORD' | translate}} *</label>
+          </div>
+          <div class="col-sm-8">
+            <input class="form-control" placeholder="{{'PAGE.USERS.PASSWORD' | translate}}" minlength="8" maxlength="50"
+              type="password" formControlName="password" id="password" autocomplete="new-password"
+              [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+          </div>
+          <div class="input-validation-msg" [ngClass]="{'message': isPassword}">
+            <div
+              *ngIf="userForm?.controls.password.hasError('minlength') || userForm?.controls.password.errors?.pattern">
+              {{'PAGE.LOGIN.PASSWORDMINLENGTHVALIDMESSAGE' | translate}} </div>
+          </div>
+        </div>
+        <div class="row form-group" *ngIf="userType === 'changePassword'">
+          <div class="col-sm-4">
+            <label for="password">{{'PAGE.USERS.NEWPASSWORD' | translate}} *</label>
+          </div>
+          <div class="col-sm-8">
+            <input class="form-control" placeholder="{{'PAGE.USERS.NEWPASSWORD' | translate}}" minlength="8"
+              maxlength="50" type="password" formControlName="password" id="password" autocomplete="new-password"
+              [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+          </div>
+          <div class="input-validation-msg" [ngClass]="{'message': isPassword}">
+            <div
+              *ngIf="userForm?.controls.password.hasError('minlength') || userForm?.controls.password.errors?.pattern">
+              {{'PAGE.LOGIN.PASSWORDMINLENGTHVALIDMESSAGE' | translate}} </div>
+          </div>
+        </div>
+        <div class="row form-group">
+          <div class="col-sm-4">
+            <label for="password2">{{'PAGE.USERS.CONFPASSWORD' | translate}} *</label>
+          </div>
+          <div class="col-sm-8">
+            <input class="form-control" placeholder="{{'PAGE.USERS.CONFPASSWORD' | translate}}" type="password"
+              formControlName="password2" id="password2" autocomplete="new-password"
+              [ngClass]="{ 'is-invalid': submitted && f.password2.errors }" required>
+            <div class="mr-top-5" *ngIf="userForm?.controls.password.value && userForm?.controls.password2.value">
+              <i class="far"
+                [ngClass]="{'fa-times-circle text-danger':userForm?.controls.password.value !== userForm?.controls.password2.value,
+            'fa-check-circle text-success':userForm?.controls.password.value === userForm?.controls.password2.value}"></i>
+              {{'PAGE.USERS.PASSWORDMATCH' | translate}}
+            </div>
+          </div>
+        </div>
+      </ng-container>
+      <div class="form-group row" *ngIf="userType === 'add'">
+        <label class="col-sm-4 col-form-label">{{'DOMAIN' | translate}} {{'NAME' | translate}}</label>
+        <div class="col-sm-8">
+          <ng-select [clearable]="false" placeholder="{{'SELECT' | translate}}" [items]="domains" bindLabel="title"
+            bindValue="value" formControlName="domain_name" id="domain_name"
+            [ngClass]="{ 'is-invalid': submitted && f.domain_name.errors }"></ng-select>
+        </div>
       </div>
     </div>
-  </div>
-  <div class="modal-footer">
-    <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
-    <button *ngIf="userType==='add'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
-    <button *ngIf="userType!=='add'" type="submit" class="btn btn-primary">{{'APPLY' | translate}}</button>
-  </div>
-</form>
+    <div class="modal-footer">
+      <button type="button" class="btn btn-danger" (click)="close()">{{'CANCEL' | translate}}</button>
+      <button *ngIf="userType==='add'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+      <button *ngIf="userType!=='add'" type="submit" class="btn btn-primary">{{'APPLY' | translate}}</button>
+    </div>
+  </form>
+</div>
 <app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
diff --git a/src/app/users/add-user/AddEditUserComponent.scss b/src/app/users/add-user/AddEditUserComponent.scss
index 05f2819..3520b4e 100644
--- a/src/app/users/add-user/AddEditUserComponent.scss
+++ b/src/app/users/add-user/AddEditUserComponent.scss
@@ -15,11 +15,46 @@
 
  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
 */
-@import '../../../assets/scss/mixins/mixin';
-@import '../../../assets/scss/variable';
-.input-validation-msg{
-    color:$red;
-    text-align:left;
+@import "../../../assets/scss/mixins/mixin";
+@import "../../../assets/scss/variable";
+.input-validation-msg {
+    color: $red;
+    text-align: left;
     @include padding-value(0, 0, 0, 10);
     @include font(null, 11px, null);
+}
+.change-password {
+    @include background(
+        linear-gradient(
+            to left bottom,
+            #00c0ef,
+            #00b3f9,
+            #3ea3fd,
+            #7190f8,
+            #9c78e8,
+            #a86cdd,
+            #b25fd1,
+            #bb51c3,
+            #b151c4,
+            #a652c6,
+            #9b53c6,
+            #9053c7
+        ),
+        null,
+        null,
+        null,
+        null
+    );
+    color: $white;
+    overflow: visible;
+    @include box-shadow(0px, 3px, 10px, 0px, rgba($black, 0.5));
+}
+.message {
+    @include roundedCorners(25);
+    @include background(null, $cerise-pink, null, null, null);
+    color: $white !important;
+    text-align: left;
+    @include padding-value(0, 0, 0, 10);
+    @include margin-value(0, 0, 10, 0);
+    @include font(null, 11px, null);
 }
\ No newline at end of file
diff --git a/src/app/users/add-user/AddEditUserComponent.ts b/src/app/users/add-user/AddEditUserComponent.ts
index d988548..0e9456a 100644
--- a/src/app/users/add-user/AddEditUserComponent.ts
+++ b/src/app/users/add-user/AddEditUserComponent.ts
@@ -36,6 +36,7 @@
  * @Component takes AddEditUserComponent.html as template url
  */
 @Component({
+    selector: 'app-add-edit-user',
     templateUrl: './AddEditUserComponent.html',
     styleUrls: ['./AddEditUserComponent.scss']
 })
@@ -74,6 +75,12 @@
     /** Holds list of domains @public */
     public domains: TYPESECTION[] = [];
 
+    /** Variable contains type is changepassword or not @public */
+    public isPassword: boolean;
+
+    /** Variable holds value for first login user @public */
+    public isFirstLogin: boolean = Boolean(localStorage.getItem('firstLogin') === 'true');
+
     /** Instance of the rest service @private */
     private restService: RestService;
 
@@ -113,6 +120,7 @@
             userName: ['', Validators.required],
             password: [null, [Validators.required, Validators.pattern(this.sharedService.REGX_PASSWORD_PATTERN)]],
             password2: [null, Validators.required],
+            old_password: [null, Validators.required],
             domain_name: [null]
         });
     }
@@ -131,6 +139,8 @@
             this.getDomainList();
         } else if (this.userType === 'editUserName') {
             this.userForm.patchValue({ userName: this.userName });
+        } else if (this.isFirstLogin) {
+            this.isPassword = true;
         }
     }
 
@@ -139,11 +149,21 @@
         if (userType === 'editPassword') {
             this.getFormControl('userName').setValidators([]);
             this.getFormControl('userName').updateValueAndValidity();
+            this.getFormControl('old_password').setValidators([]);
+            this.getFormControl('old_password').updateValueAndValidity();
         } else if (userType === 'editUserName') {
             this.getFormControl('password').setValidators([]);
             this.getFormControl('password').updateValueAndValidity();
             this.getFormControl('password2').setValidators([]);
             this.getFormControl('password2').updateValueAndValidity();
+            this.getFormControl('old_password').setValidators([]);
+            this.getFormControl('old_password').updateValueAndValidity();
+        } else if (userType === 'changePassword') {
+            this.getFormControl('userName').setValidators([]);
+            this.getFormControl('userName').updateValueAndValidity();
+        } else if (userType === 'add') {
+            this.getFormControl('old_password').setValidators([]);
+            this.getFormControl('old_password').updateValueAndValidity();
         }
         this.submitted = true;
         this.modalData = {
@@ -157,7 +177,7 @@
             }
             if (userType === 'add') {
                 this.addUser();
-            } else if (userType === 'editUserName' || userType === 'editPassword') {
+            } else {
                 this.editUser();
             }
         }
@@ -191,6 +211,9 @@
         const payLoad: LOGINPARAMS = {};
         if (this.userType === 'editPassword') {
             payLoad.password = (this.userForm.value.password);
+        } else if (this.userType === 'changePassword') {
+            payLoad.password = (this.userForm.value.password);
+            payLoad.old_password = (this.userForm.value.old_password);
         } else {
             payLoad.username = this.userForm.value.userName.toLowerCase();
         }
@@ -201,13 +224,33 @@
         this.restService.patchResource(apiURLHeader, payLoad).subscribe((result: {}): void => {
             this.checkUsername(payLoad);
             this.activeModal.close(this.modalData);
+            if (this.isFirstLogin) {
+                this.notifierService.notify('success', this.translateService.instant('PAGE.USERS.CHANGEPASSWORD'));
+                this.authService.destoryToken();
+            } else {
+                this.notifierService.notify('success', this.translateService.instant('PAGE.USERS.EDITEDSUCCESSFULLY'));
+            }
             this.isLoadingResults = false;
-            this.notifierService.notify('success', this.translateService.instant('PAGE.USERS.EDITEDSUCCESSFULLY'));
         }, (error: ERRORDATA): void => {
-            this.restService.handleError(error, 'put');
+            if (this.isFirstLogin) {
+                this.notifierService.notify('error', error.error.detail);
+                this.activeModal.close(this.modalData);
+                this.authService.destoryToken();
+            } else {
+                this.restService.handleError(error, 'put');
+            }
             this.isLoadingResults = false;
         });
     }
+    /** Close the modal and destroy subscribe @public */
+    public close(): void {
+        if (this.isFirstLogin) {
+            this.activeModal.close(this.modalData);
+            this.authService.destoryToken();
+        } else {
+            this.activeModal.close(this.modalData);
+        }
+    }
     /** Get domain name list @private */
     private getDomainList(): void {
         this.isLoadingResults = true;