]> source.dussan.org Git - archiva.git/blob
519eb27e0b5c07631489af33d8a5f2ecb77b0cbb
[archiva.git] /
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 import {EventEmitter, Injectable} from '@angular/core';
20 import {ArchivaRequestService} from "./archiva-request.service";
21 import {AccessToken} from "../model/access-token";
22 import {environment} from "../../environments/environment";
23 import {ErrorMessage} from "../model/error-message";
24 import {ErrorResult} from "../model/error-result";
25 import {HttpErrorResponse} from "@angular/common/http";
26 import {UserService} from "./user.service";
27 import {UserInfo} from "../model/user-info";
28
29 /**
30  * The AuthenticationService handles user authentication and stores user data after successful login
31  */
32 @Injectable({
33     providedIn: 'root'
34 })
35 export class AuthenticationService {
36     authenticated: boolean;
37     authenticating: boolean;
38
39     /**
40      * The LoginEvent is emitted, when a successful login happened. And the corresponding user info was retrieved.
41      */
42     public LoginEvent: EventEmitter<UserInfo> = new EventEmitter<UserInfo>();
43
44     /**
45      * The LogoutEvent is emitted, when the user has been logged out.
46      */
47     public LogoutEvent: EventEmitter<any> = new EventEmitter<any>();
48
49
50     constructor(private rest: ArchivaRequestService,
51                 private userService: UserService) {
52         this.authenticated = false;
53         this.LoginEvent.subscribe((info)=>{
54             this.authenticating=false;
55         })
56         this.LogoutEvent.subscribe(()=>{
57             this.authenticating=false;
58         })
59         this.restoreLoginData();
60     }
61
62     private restoreLoginData() {
63         console.debug("Restoring login data");
64         let accessToken = localStorage.getItem("access_token");
65         if (accessToken != null) {
66             let expirationDate = localStorage.getItem("token_expire");
67             if (expirationDate != null) {
68                 let expDate = new Date(expirationDate);
69                 let currentDate = new Date();
70                 if (currentDate < expDate) {
71                     console.debug("Retrieving user information");
72                     this.authenticating=true;
73                     let observer = this.userService.retrieveUserInfo();
74                     observer.subscribe({
75                             next: (userInfo: UserInfo) => {
76                                 if (userInfo != null) {
77                                     let permObserver = this.userService.retrievePermissionInfo();
78                                     permObserver.subscribe({
79                                             next: () => {
80                                                 this.authenticated = true;
81                                                 this.LoginEvent.emit(userInfo)
82                                             },
83                                             error: (err) => {
84                                                 console.debug("Error retrieving perms: " + JSON.stringify(err));
85                                             }
86                                         }
87                                     )
88                                 }
89                             },
90                             error: (err: HttpErrorResponse) => {
91                                 console.debug("Error retrieving user info: " + JSON.stringify(err));
92                                 this.logout();
93                             },
94                             complete: () => {
95                                 this.authenticating=false;
96                             }
97                         }
98                     );
99                 } else {
100                     this.logout();
101                 }
102             } else {
103                 this.logout();
104             }
105         }
106
107
108     }
109
110
111     /**
112      * Tries to login by sending the login data to the REST service. If the login was successful the access
113      * and refresh token is stored locally.
114      *
115      * @param userid The user id for the login
116      * @param password The password
117      * @param resultHandler A result handler that is executed, after calling the login service
118      */
119     login(userid: string, password: string, resultHandler: (n: string, err?: ErrorMessage[]) => void) {
120         this.authenticating=true;
121         const data = {
122             'grant_type': 'authorization_code',
123             'client_id': environment.application.client_id,
124             'user_id': userid, 'password': password
125         };
126         let authObserver = this.rest.executeRestCall<AccessToken>('post', 'redback', 'auth/authenticate', data);
127         let tokenObserver = {
128             next: (x: AccessToken) => {
129                 localStorage.setItem("access_token", x.access_token);
130                 localStorage.setItem("refresh_token", x.refresh_token);
131                 if (x.expires_in != null) {
132                     let dt = new Date();
133                     dt.setSeconds(dt.getSeconds() + x.expires_in);
134                     localStorage.setItem("token_expire", dt.toISOString());
135                 }
136                 let userObserver = this.userService.retrieveUserInfo();
137                 this.authenticated = true;
138                 userObserver.subscribe(userInfo => {
139                     if (userInfo != null) {
140                         let permObserver = this.userService.retrievePermissionInfo();
141                         permObserver.subscribe((perms) => {
142                                 this.LoginEvent.emit(userInfo);
143                             }
144                         )
145                     }
146                 });
147                 resultHandler("OK");
148             },
149             error: (err: HttpErrorResponse) => {
150                 this.authenticating = false;
151                 console.log("Error " + (JSON.stringify(err)));
152                 let result = err.error as ErrorResult
153                 if (result.error_messages != null) {
154                     for (let msg of result.error_messages) {
155                         console.debug('Observer got an error: ' + msg.error_key)
156                     }
157                     resultHandler("ERROR", result.error_messages);
158                 } else {
159                     resultHandler("ERROR", null);
160                 }
161
162             },
163             complete: () => {
164                 this.authenticating = false;
165             }
166         };
167         authObserver.subscribe(tokenObserver)
168
169     }
170
171     /**
172      * Resets the stored user data
173      */
174     logout() {
175         localStorage.removeItem("access_token");
176         localStorage.removeItem("refresh_token");
177         localStorage.removeItem("token_expire");
178         this.authenticated = false;
179         this.userService.resetUser();
180         this.rest.resetToken();
181         this.LogoutEvent.emit();
182     }
183 }