Feature 10914: Enforce Password change on First login
[osm/NG-UI.git] / src / services / AuthenticationService.ts
1 /*
2  Copyright 2020 TATA ELXSI
3
4  Licensed under the Apache License, Version 2.0 (the 'License');
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17  */
18 /**
19  * @file Auth service
20  */
21 import { HttpHeaders } from '@angular/common/http';
22 import { Injectable, Injector } from '@angular/core';
23 import { Router } from '@angular/router';
24 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
25 import { Idle } from '@ng-idle/core';
26 import { APIURLHEADER, ERRORDATA } from 'CommonModel';
27 import { environment } from 'environment';
28 import { BehaviorSubject, Observable } from 'rxjs';
29 import { map } from 'rxjs/operators';
30 import { isNullOrUndefined } from 'util';
31 import { ProjectModel } from '../models/VNFDModel';
32 import { RestService } from './RestService';
33
34 /**
35  * An Injectable is a class adorned with the @Injectable decorator function.
36  * @Injectable takes a metadata object that tells Angular how to compile and run module code
37  */
38 @Injectable()
39 export class AuthenticationService {
40     /** To inject services @public */
41     public injector: Injector;
42
43     /** Instance for modal service @public */
44     public modalService: NgbModal;
45
46     /** Handle 401 response for multiple API calls */
47     public handle401: boolean = true;
48
49     /** contains return URL link @public */
50     public returnUrl: string;
51
52     /** Holds the username in condition of type BehaviorSubject<string> @public */
53     public userName: BehaviorSubject<string> = new BehaviorSubject<string>('');
54
55     /** Holds the projectname in condition of type BehaviorSubject<string> @public */
56     public projectName$: BehaviorSubject<string> = new BehaviorSubject<string>('');
57
58     /** Holds the instance of router class @private */
59     private router: Router;
60
61     /** Holds the logged in condition of type BehaviorSubject<boolean> @private */
62     private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
63
64     /** Holds the change password in condition of type BehaviorSubject<boolean> @private */
65     private changePassword: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
66
67     /** Hold Rest Service Objects */
68     private restService: RestService;
69
70     /** Holds auth payloads @private */
71     private payLoad: {};
72
73     /** Holds header options for auth service @private */
74     private httpOptions: HttpHeaders;
75
76     /** handle idle time out service @private */
77     private idle: Idle;
78
79     /** create the instance of the component */
80     constructor(injector: Injector) {
81         this.injector = injector;
82         this.router = this.injector.get(Router);
83         this.restService = this.injector.get(RestService);
84         this.modalService = this.injector.get(NgbModal);
85         this.idle = this.injector.get(Idle);
86         if (localStorage.getItem('username') !== null) {
87             this.loggedIn.next(true);
88             this.changePassword.next(false);
89         } else if (localStorage.getItem('firstLogin') !== null) {
90             this.changePassword.next(true);
91             this.loggedIn.next(false);
92         } else {
93             this.loggedIn.next(false);
94         }
95         this.userName.next(localStorage.getItem('username'));
96         this.redirectToPage();
97     }
98
99     /**
100      * Get method for  Observable loggedIn
101      */
102     get isLoggedIn(): Observable<boolean> {
103         return this.loggedIn.asObservable();
104     }
105
106     /**
107      * Get method for  Observable changepassword
108      */
109     get isChangePassword(): Observable<boolean> {
110         return this.changePassword.asObservable();
111     }
112
113     /**
114      * Get method for Observable Username
115      */
116     get username(): Observable<string> {
117         return this.userName.asObservable();
118     }
119
120     /** Get method for project name */
121     get ProjectName(): Observable<string> {
122         return this.projectName$.asObservable();
123     }
124
125     /**
126      * Send request and authenticate the user
127      * @param user of type User
128      */
129     public login(username: string, password: string): Observable<{}> {
130         this.setHeader();
131         this.setPayLoad(username, password);
132         const apiURLHeader: APIURLHEADER = {
133             url: environment.GENERATETOKEN_URL,
134             httpOptions: { headers: this.httpOptions }
135         };
136         return this.restService.postResource(apiURLHeader, this.payLoad)
137             .pipe(map((data: ProjectModel): BehaviorSubject<boolean> => {
138                 if (data.message === 'change_password') {
139                     localStorage.setItem('firstLogin', 'true');
140                     localStorage.setItem('id_token', data.id);
141                     localStorage.setItem('user_id', data.user_id);
142                     this.idle.watch(true);
143                     this.changePassword.next(true);
144                     this.loggedIn.next(false);
145                     return this.changePassword;
146                 } else {
147                     this.setLocalStorage(data);
148                     this.idle.watch(true);
149                     this.loggedIn.next(true);
150                     this.handle401 = true;
151                     this.userName.next(data.username);
152                     return this.loggedIn;
153                 }
154             }, (error: ERRORDATA): void => { this.restService.handleError(error, 'post'); }
155             ));
156     }
157
158     /** Set headers for auth session @public */
159     public setHeader(): void {
160         this.httpOptions = new HttpHeaders({
161             'Content-Type': 'application/json; charset=UTF-8',
162             Accept: 'application/json',
163             'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
164         });
165     }
166
167     /** Set payloads for auth session @public  */
168     public setPayLoad(username: string, password: string): void {
169         this.payLoad = JSON.stringify({
170             username,
171             password
172         });
173     }
174
175     /** set local storage on auth process @public */
176     public setLocalStorage(data: ProjectModel): void {
177         localStorage.setItem('id_token', data.id);
178         localStorage.setItem('expires', data.expires.toString());
179         localStorage.setItem('username', data.username);
180         localStorage.setItem('isAdmin', (data.admin) ? 'true' : 'false');
181         localStorage.setItem('project_id', data.project_id);
182         localStorage.setItem('project', data.project_name);
183         localStorage.setItem('token_state', data.id);
184         this.projectName$.next(data.project_name);
185     }
186     /** Destory tokens API response handling @public */
187     public logoutResponse(): void {
188         this.loggedIn.next(false);
189         this.changePassword.next(false);
190         const langCode: string = localStorage.getItem('languageCode');
191         const redirecturl: string = isNullOrUndefined(localStorage.getItem('returnUrl')) ? '/' : localStorage.getItem('returnUrl');
192         const osmVersion: string = isNullOrUndefined(localStorage.getItem('osmVersion')) ? '' : localStorage.getItem('osmVersion');
193         localStorage.clear();
194         localStorage.setItem('languageCode', langCode);
195         localStorage.setItem('returnUrl', redirecturl);
196         localStorage.setItem('token_state', null);
197         localStorage.setItem('osmVersion', osmVersion);
198         this.idle.stop();
199         this.router.navigate(['login']).catch();
200     }
201     /**
202      * Logout the user & clearing the token.
203      */
204     public logout(): void {
205         this.returnUrl = this.router.url;
206         localStorage.setItem('returnUrl', this.returnUrl);
207         this.modalService.dismissAll();
208         this.destoryToken();
209     }
210     /** Destory tokens on logout @public */
211     public destoryToken(): void {
212         const tokenID: string = localStorage.getItem('id_token');
213         if (tokenID !== null) {
214             const deletingURl: string = environment.GENERATETOKEN_URL + '/' + tokenID;
215             this.restService.deleteResource(deletingURl).subscribe((res: {}): void => {
216                 this.logoutResponse();
217             }, (error: ERRORDATA): void => {
218                 this.restService.handleError(error, 'delete');
219             });
220         }
221     }
222
223     /** Return to previous page deny access to changepassword */
224     public redirectToPage(): void {
225         if (window.location.pathname === '/changepassword' && localStorage.getItem('username') !== null) {
226             window.history.back();
227         } else if (window.location.pathname === '/' && localStorage.getItem('firstLogin') === 'true') {
228             this.router.navigate(['/login']).catch();
229         }
230     }
231 }