aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/auth/auth.service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared/auth/auth.service.ts')
-rw-r--r--client/src/app/shared/auth/auth.service.ts94
1 files changed, 70 insertions, 24 deletions
diff --git a/client/src/app/shared/auth/auth.service.ts b/client/src/app/shared/auth/auth.service.ts
index 584298fff..a30c79c86 100644
--- a/client/src/app/shared/auth/auth.service.ts
+++ b/client/src/app/shared/auth/auth.service.ts
@@ -1,32 +1,39 @@
1import { Injectable } from '@angular/core'; 1import { Injectable } from '@angular/core';
2import { Headers, Http, Response, URLSearchParams } from '@angular/http'; 2import { Headers, Http, Response, URLSearchParams } from '@angular/http';
3import { Router } from '@angular/router';
3import { Observable } from 'rxjs/Observable'; 4import { Observable } from 'rxjs/Observable';
4import { Subject } from 'rxjs/Subject'; 5import { Subject } from 'rxjs/Subject';
5 6
6import { AuthStatus } from './auth-status.model'; 7import { AuthStatus } from './auth-status.model';
7import { User } from './user.model'; 8import { AuthUser } from './auth-user.model';
9import { RestExtractor } from '../rest';
8 10
9@Injectable() 11@Injectable()
10export class AuthService { 12export class AuthService {
11 private static BASE_CLIENT_URL = '/api/v1/users/client'; 13 private static BASE_CLIENT_URL = '/api/v1/clients/local';
12 private static BASE_TOKEN_URL = '/api/v1/users/token'; 14 private static BASE_TOKEN_URL = '/api/v1/users/token';
15 private static BASE_USER_INFORMATIONS_URL = '/api/v1/users/me';
13 16
14 loginChangedSource: Observable<AuthStatus>; 17 loginChangedSource: Observable<AuthStatus>;
15 18
16 private clientId: string; 19 private clientId: string;
17 private clientSecret: string; 20 private clientSecret: string;
18 private loginChanged: Subject<AuthStatus>; 21 private loginChanged: Subject<AuthStatus>;
19 private user: User = null; 22 private user: AuthUser = null;
20 23
21 constructor(private http: Http) { 24 constructor(
25 private http: Http,
26 private restExtractor: RestExtractor,
27 private router: Router
28 ) {
22 this.loginChanged = new Subject<AuthStatus>(); 29 this.loginChanged = new Subject<AuthStatus>();
23 this.loginChangedSource = this.loginChanged.asObservable(); 30 this.loginChangedSource = this.loginChanged.asObservable();
24 31
25 // Fetch the client_id/client_secret 32 // Fetch the client_id/client_secret
26 // FIXME: save in local storage? 33 // FIXME: save in local storage?
27 this.http.get(AuthService.BASE_CLIENT_URL) 34 this.http.get(AuthService.BASE_CLIENT_URL)
28 .map(res => res.json()) 35 .map(this.restExtractor.extractDataGet)
29 .catch(this.handleError) 36 .catch((res) => this.restExtractor.handleError(res))
30 .subscribe( 37 .subscribe(
31 result => { 38 result => {
32 this.clientId = result.client_id; 39 this.clientId = result.client_id;
@@ -34,12 +41,15 @@ export class AuthService {
34 console.log('Client credentials loaded.'); 41 console.log('Client credentials loaded.');
35 }, 42 },
36 error => { 43 error => {
37 alert(error); 44 alert(
45 `Cannot retrieve OAuth Client credentials: ${error.text}. \n` +
46 'Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.'
47 );
38 } 48 }
39 ); 49 );
40 50
41 // Return null if there is nothing to load 51 // Return null if there is nothing to load
42 this.user = User.load(); 52 this.user = AuthUser.load();
43 } 53 }
44 54
45 getRefreshToken() { 55 getRefreshToken() {
@@ -64,10 +74,16 @@ export class AuthService {
64 return this.user.getTokenType(); 74 return this.user.getTokenType();
65 } 75 }
66 76
67 getUser(): User { 77 getUser(): AuthUser {
68 return this.user; 78 return this.user;
69 } 79 }
70 80
81 isAdmin() {
82 if (this.user === null) return false;
83
84 return this.user.isAdmin();
85 }
86
71 isLoggedIn() { 87 isLoggedIn() {
72 if (this.getAccessToken()) { 88 if (this.getAccessToken()) {
73 return true; 89 return true;
@@ -94,21 +110,23 @@ export class AuthService {
94 }; 110 };
95 111
96 return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options) 112 return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
97 .map(res => res.json()) 113 .map(this.restExtractor.extractDataGet)
98 .map(res => { 114 .map(res => {
99 res.username = username; 115 res.username = username;
100 return res; 116 return res;
101 }) 117 })
118 .flatMap(res => this.fetchUserInformations(res))
102 .map(res => this.handleLogin(res)) 119 .map(res => this.handleLogin(res))
103 .catch(this.handleError); 120 .catch((res) => this.restExtractor.handleError(res));
104 } 121 }
105 122
106 logout() { 123 logout() {
107 // TODO: make an HTTP request to revoke the tokens 124 // TODO: make an HTTP request to revoke the tokens
108 this.user = null; 125 this.user = null;
109 User.flush();
110 126
111 this.setStatus(AuthStatus.LoggedIn); 127 AuthUser.flush();
128
129 this.setStatus(AuthStatus.LoggedOut);
112 } 130 }
113 131
114 refreshAccessToken() { 132 refreshAccessToken() {
@@ -131,36 +149,64 @@ export class AuthService {
131 }; 149 };
132 150
133 return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options) 151 return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
134 .map(res => res.json()) 152 .map(this.restExtractor.extractDataGet)
135 .map(res => this.handleRefreshToken(res)) 153 .map(res => this.handleRefreshToken(res))
136 .catch(this.handleError); 154 .catch((res: Response) => {
155 // The refresh token is invalid?
156 if (res.status === 400 && res.json() && res.json().error === 'invalid_grant') {
157 console.error('Cannot refresh token -> logout...');
158 this.logout();
159 this.router.navigate(['/login']);
160
161 return Observable.throw({
162 json: '',
163 text: 'You need to reconnect.'
164 });
165 }
166
167 return this.restExtractor.handleError(res);
168 });
137 } 169 }
138 170
139 private setStatus(status: AuthStatus) { 171 private fetchUserInformations (obj: any) {
140 this.loginChanged.next(status); 172 // Do not call authHttp here to avoid circular dependencies headaches
173
174 const headers = new Headers();
175 headers.set('Authorization', `Bearer ${obj.access_token}`);
176
177 return this.http.get(AuthService.BASE_USER_INFORMATIONS_URL, { headers })
178 .map(res => res.json())
179 .map(res => {
180 obj.id = res.id;
181 obj.role = res.role;
182 return obj;
183 }
184 );
141 } 185 }
142 186
143 private handleLogin (obj: any) { 187 private handleLogin (obj: any) {
188 const id = obj.id;
144 const username = obj.username; 189 const username = obj.username;
145 const hash_tokens = { 190 const role = obj.role;
191 const hashTokens = {
146 access_token: obj.access_token, 192 access_token: obj.access_token,
147 token_type: obj.token_type, 193 token_type: obj.token_type,
148 refresh_token: obj.refresh_token 194 refresh_token: obj.refresh_token
149 }; 195 };
150 196
151 this.user = new User(username, hash_tokens); 197 this.user = new AuthUser({ id, username, role }, hashTokens);
152 this.user.save(); 198 this.user.save();
153 199
154 this.setStatus(AuthStatus.LoggedIn); 200 this.setStatus(AuthStatus.LoggedIn);
155 } 201 }
156 202
157 private handleError (error: Response) {
158 console.error(error);
159 return Observable.throw(error.json() || { error: 'Server error' });
160 }
161
162 private handleRefreshToken (obj: any) { 203 private handleRefreshToken (obj: any) {
163 this.user.refreshTokens(obj.access_token, obj.refresh_token); 204 this.user.refreshTokens(obj.access_token, obj.refresh_token);
164 this.user.save(); 205 this.user.save();
165 } 206 }
207
208 private setStatus(status: AuthStatus) {
209 this.loginChanged.next(status);
210 }
211
166} 212}