Client: Add authHttp service that authentificates the http request and
optionally refresh the access token if needed
This commit is contained in:
parent
2f372a8654
commit
bd5c83a8cb
15 changed files with 314 additions and 97 deletions
|
@ -1,5 +1,4 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { HTTP_PROVIDERS } from '@angular/http';
|
|
||||||
import { ActivatedRoute, Router, ROUTER_DIRECTIVES } from '@angular/router';
|
import { ActivatedRoute, Router, ROUTER_DIRECTIVES } from '@angular/router';
|
||||||
|
|
||||||
import { FriendService } from './friends';
|
import { FriendService } from './friends';
|
||||||
|
@ -16,7 +15,7 @@ import { VideoService } from './videos';
|
||||||
template: require('./app.component.html'),
|
template: require('./app.component.html'),
|
||||||
styles: [ require('./app.component.scss') ],
|
styles: [ require('./app.component.scss') ],
|
||||||
directives: [ ROUTER_DIRECTIVES, SearchComponent ],
|
directives: [ ROUTER_DIRECTIVES, SearchComponent ],
|
||||||
providers: [ AuthService, FriendService, HTTP_PROVIDERS, VideoService, SearchService ]
|
providers: [ FriendService, VideoService, SearchService ]
|
||||||
})
|
})
|
||||||
|
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
|
@ -35,14 +34,20 @@ export class AppComponent {
|
||||||
status => {
|
status => {
|
||||||
if (status === AuthStatus.LoggedIn) {
|
if (status === AuthStatus.LoggedIn) {
|
||||||
this.isLoggedIn = true;
|
this.isLoggedIn = true;
|
||||||
|
console.log('Logged in.');
|
||||||
|
} else if (status === AuthStatus.LoggedOut) {
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
console.log('Logged out.');
|
||||||
|
} else {
|
||||||
|
console.error('Unknown auth status: ' + status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME
|
|
||||||
logout() {
|
logout() {
|
||||||
// this._authService.logout();
|
this.authService.logout();
|
||||||
|
this.authService.setStatus(AuthStatus.LoggedOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
makeFriends() {
|
makeFriends() {
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http, Response } from '@angular/http';
|
import { Response } from '@angular/http';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { AuthService } from '../shared';
|
import { AuthHttp, AuthService } from '../shared';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FriendService {
|
export class FriendService {
|
||||||
private static BASE_FRIEND_URL: string = '/api/v1/pods/';
|
private static BASE_FRIEND_URL: string = '/api/v1/pods/';
|
||||||
|
|
||||||
constructor (private http: Http, private authService: AuthService) {}
|
constructor (private authHttp: AuthHttp, private authService: AuthService) {}
|
||||||
|
|
||||||
makeFriends() {
|
makeFriends() {
|
||||||
const headers = this.authService.getRequestHeader();
|
return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'makefriends')
|
||||||
return this.http.get(FriendService.BASE_FRIEND_URL + 'makefriends', { headers })
|
|
||||||
.map(res => res.status)
|
.map(res => res.status)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
quitFriends() {
|
quitFriends() {
|
||||||
const headers = this.authService.getRequestHeader();
|
return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'quitfriends')
|
||||||
return this.http.get(FriendService.BASE_FRIEND_URL + 'quitfriends', { headers })
|
|
||||||
.map(res => res.status)
|
.map(res => res.status)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { AuthService, AuthStatus, User } from '../shared';
|
import { AuthService } from '../shared';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-login',
|
selector: 'my-login',
|
||||||
|
@ -21,14 +21,11 @@ export class LoginComponent {
|
||||||
result => {
|
result => {
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
const user = new User(username, result);
|
|
||||||
user.save();
|
|
||||||
|
|
||||||
this.authService.setStatus(AuthStatus.LoggedIn);
|
|
||||||
|
|
||||||
this.router.navigate(['/videos/list']);
|
this.router.navigate(['/videos/list']);
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
if (error.error === 'invalid_grant') {
|
if (error.error === 'invalid_grant') {
|
||||||
this.error = 'Credentials are invalid.';
|
this.error = 'Credentials are invalid.';
|
||||||
} else {
|
} else {
|
||||||
|
|
77
client/src/app/shared/auth/auth-http.service.ts
Normal file
77
client/src/app/shared/auth/auth-http.service.ts
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {
|
||||||
|
ConnectionBackend,
|
||||||
|
Headers,
|
||||||
|
Http,
|
||||||
|
Request,
|
||||||
|
RequestMethod,
|
||||||
|
RequestOptions,
|
||||||
|
RequestOptionsArgs,
|
||||||
|
Response
|
||||||
|
} from '@angular/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import { AuthService } from './auth.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthHttp extends Http {
|
||||||
|
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
|
||||||
|
super(backend, defaultOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
|
||||||
|
if (!options) options = {};
|
||||||
|
|
||||||
|
options.headers = new Headers();
|
||||||
|
this.setAuthorizationHeader(options.headers);
|
||||||
|
|
||||||
|
return super.request(url, options)
|
||||||
|
.catch((err) => {
|
||||||
|
if (err.status === 401) {
|
||||||
|
return this.handleTokenExpired(err, url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Observable.throw(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||||
|
if (!options) options = {};
|
||||||
|
options.method = RequestMethod.Delete;
|
||||||
|
|
||||||
|
return this.request(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||||
|
if (!options) options = {};
|
||||||
|
options.method = RequestMethod.Get;
|
||||||
|
|
||||||
|
return this.request(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
post(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||||
|
if (!options) options = {};
|
||||||
|
options.method = RequestMethod.Post;
|
||||||
|
|
||||||
|
return this.request(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
put(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||||
|
if (!options) options = {};
|
||||||
|
options.method = RequestMethod.Put;
|
||||||
|
|
||||||
|
return this.request(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleTokenExpired(err: Response, url: string | Request, options: RequestOptionsArgs) {
|
||||||
|
return this.authService.refreshAccessToken().flatMap(() => {
|
||||||
|
this.setAuthorizationHeader(options.headers);
|
||||||
|
|
||||||
|
return super.request(url, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private setAuthorizationHeader(headers: Headers) {
|
||||||
|
headers.set('Authorization', `${this.authService.getTokenType()} ${this.authService.getToken()}`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,13 +9,14 @@ import { User } from './user.model';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private static BASE_CLIENT_URL = '/api/v1/users/client';
|
private static BASE_CLIENT_URL = '/api/v1/users/client';
|
||||||
private static BASE_LOGIN_URL = '/api/v1/users/token';
|
private static BASE_TOKEN_URL = '/api/v1/users/token';
|
||||||
|
|
||||||
loginChangedSource: Observable<AuthStatus>;
|
loginChangedSource: Observable<AuthStatus>;
|
||||||
|
|
||||||
private clientId: string;
|
private clientId: string;
|
||||||
private clientSecret: string;
|
private clientSecret: string;
|
||||||
private loginChanged: Subject<AuthStatus>;
|
private loginChanged: Subject<AuthStatus>;
|
||||||
|
private user: User = null;
|
||||||
|
|
||||||
constructor(private http: Http) {
|
constructor(private http: Http) {
|
||||||
this.loginChanged = new Subject<AuthStatus>();
|
this.loginChanged = new Subject<AuthStatus>();
|
||||||
|
@ -36,12 +37,21 @@ export class AuthService {
|
||||||
alert(error);
|
alert(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Return null if there is nothing to load
|
||||||
|
this.user = User.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
getAuthRequestOptions(): RequestOptions {
|
getAuthRequestOptions(): RequestOptions {
|
||||||
return new RequestOptions({ headers: this.getRequestHeader() });
|
return new RequestOptions({ headers: this.getRequestHeader() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRefreshToken() {
|
||||||
|
if (this.user === null) return null;
|
||||||
|
|
||||||
|
return this.user.getRefreshToken();
|
||||||
|
}
|
||||||
|
|
||||||
getRequestHeader() {
|
getRequestHeader() {
|
||||||
return new Headers({ 'Authorization': this.getRequestHeaderValue() });
|
return new Headers({ 'Authorization': this.getRequestHeaderValue() });
|
||||||
}
|
}
|
||||||
|
@ -51,21 +61,19 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getToken() {
|
getToken() {
|
||||||
return localStorage.getItem('access_token');
|
if (this.user === null) return null;
|
||||||
|
|
||||||
|
return this.user.getAccessToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
getTokenType() {
|
getTokenType() {
|
||||||
return localStorage.getItem('token_type');
|
if (this.user === null) return null;
|
||||||
|
|
||||||
|
return this.user.getTokenType();
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser(): User {
|
getUser(): User {
|
||||||
if (this.isLoggedIn() === false) {
|
return this.user;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = User.load();
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoggedIn() {
|
isLoggedIn() {
|
||||||
|
@ -93,21 +101,72 @@ export class AuthService {
|
||||||
headers: headers
|
headers: headers
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.http.post(AuthService.BASE_LOGIN_URL, body.toString(), options)
|
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
|
||||||
.map(res => res.json())
|
.map(res => res.json())
|
||||||
|
.map(res => {
|
||||||
|
res.username = username;
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.map(res => this.handleLogin(res))
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
// TODO make HTTP request
|
// TODO: make an HTTP request to revoke the tokens
|
||||||
|
this.user = null;
|
||||||
|
User.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshAccessToken() {
|
||||||
|
console.log('Refreshing token...');
|
||||||
|
|
||||||
|
const refreshToken = this.getRefreshToken();
|
||||||
|
|
||||||
|
let body = new URLSearchParams();
|
||||||
|
body.set('refresh_token', refreshToken);
|
||||||
|
body.set('client_id', this.clientId);
|
||||||
|
body.set('client_secret', this.clientSecret);
|
||||||
|
body.set('response_type', 'code');
|
||||||
|
body.set('grant_type', 'refresh_token');
|
||||||
|
|
||||||
|
let headers = new Headers();
|
||||||
|
headers.append('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
|
||||||
|
let options = {
|
||||||
|
headers: headers
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
|
||||||
|
.map(res => res.json())
|
||||||
|
.map(res => this.handleRefreshToken(res))
|
||||||
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus(status: AuthStatus) {
|
setStatus(status: AuthStatus) {
|
||||||
this.loginChanged.next(status);
|
this.loginChanged.next(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleLogin (obj: any) {
|
||||||
|
const username = obj.username;
|
||||||
|
const hash_tokens = {
|
||||||
|
access_token: obj.access_token,
|
||||||
|
token_type: obj.token_type,
|
||||||
|
refresh_token: obj.refresh_token
|
||||||
|
};
|
||||||
|
|
||||||
|
this.user = new User(username, hash_tokens);
|
||||||
|
this.user.save();
|
||||||
|
|
||||||
|
this.setStatus(AuthStatus.LoggedIn);
|
||||||
|
}
|
||||||
|
|
||||||
private handleError (error: Response) {
|
private handleError (error: Response) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return Observable.throw(error.json() || { error: 'Server error' });
|
return Observable.throw(error.json() || { error: 'Server error' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleRefreshToken (obj: any) {
|
||||||
|
this.user.refreshTokens(obj.access_token, obj.refresh_token);
|
||||||
|
this.user.save();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
|
export * from './auth-http.service';
|
||||||
export * from './auth-status.model';
|
export * from './auth-status.model';
|
||||||
export * from './auth.service';
|
export * from './auth.service';
|
||||||
export * from './token.model';
|
|
||||||
export * from './user.model';
|
export * from './user.model';
|
103
client/src/app/shared/auth/user.model.ts
Normal file
103
client/src/app/shared/auth/user.model.ts
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
export class User {
|
||||||
|
private static KEYS = {
|
||||||
|
USERNAME: 'username'
|
||||||
|
};
|
||||||
|
|
||||||
|
username: string;
|
||||||
|
tokens: Tokens;
|
||||||
|
|
||||||
|
static load() {
|
||||||
|
const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME);
|
||||||
|
if (usernameLocalStorage) {
|
||||||
|
return new User(localStorage.getItem(this.KEYS.USERNAME), Tokens.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static flush() {
|
||||||
|
localStorage.removeItem(this.KEYS.USERNAME);
|
||||||
|
Tokens.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(username: string, hash_tokens: any) {
|
||||||
|
this.username = username;
|
||||||
|
this.tokens = new Tokens(hash_tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccessToken() {
|
||||||
|
return this.tokens.access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRefreshToken() {
|
||||||
|
return this.tokens.refresh_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTokenType() {
|
||||||
|
return this.tokens.token_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshTokens(access_token: string, refresh_token: string) {
|
||||||
|
this.tokens.access_token = access_token;
|
||||||
|
this.tokens.refresh_token = refresh_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
localStorage.setItem('username', this.username);
|
||||||
|
this.tokens.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private class used only by User
|
||||||
|
class Tokens {
|
||||||
|
private static KEYS = {
|
||||||
|
ACCESS_TOKEN: 'access_token',
|
||||||
|
REFRESH_TOKEN: 'refresh_token',
|
||||||
|
TOKEN_TYPE: 'token_type',
|
||||||
|
};
|
||||||
|
|
||||||
|
access_token: string;
|
||||||
|
refresh_token: string;
|
||||||
|
token_type: string;
|
||||||
|
|
||||||
|
static load() {
|
||||||
|
const accessTokenLocalStorage = localStorage.getItem(this.KEYS.ACCESS_TOKEN);
|
||||||
|
const refreshTokenLocalStorage = localStorage.getItem(this.KEYS.REFRESH_TOKEN);
|
||||||
|
const tokenTypeLocalStorage = localStorage.getItem(this.KEYS.TOKEN_TYPE);
|
||||||
|
|
||||||
|
if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) {
|
||||||
|
return new Tokens({
|
||||||
|
access_token: accessTokenLocalStorage,
|
||||||
|
refresh_token: refreshTokenLocalStorage,
|
||||||
|
token_type: tokenTypeLocalStorage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static flush() {
|
||||||
|
localStorage.removeItem(this.KEYS.ACCESS_TOKEN);
|
||||||
|
localStorage.removeItem(this.KEYS.REFRESH_TOKEN);
|
||||||
|
localStorage.removeItem(this.KEYS.TOKEN_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(hash?: any) {
|
||||||
|
if (hash) {
|
||||||
|
this.access_token = hash.access_token;
|
||||||
|
this.refresh_token = hash.refresh_token;
|
||||||
|
|
||||||
|
if (hash.token_type === 'bearer') {
|
||||||
|
this.token_type = 'Bearer';
|
||||||
|
} else {
|
||||||
|
this.token_type = hash.token_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
localStorage.setItem('access_token', this.access_token);
|
||||||
|
localStorage.setItem('refresh_token', this.refresh_token);
|
||||||
|
localStorage.setItem('token_type', this.token_type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,2 @@
|
||||||
|
export * from './auth';
|
||||||
export * from './search';
|
export * from './search';
|
||||||
export * from './users'
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
export class Token {
|
|
||||||
access_token: string;
|
|
||||||
refresh_token: string;
|
|
||||||
token_type: string;
|
|
||||||
|
|
||||||
static load() {
|
|
||||||
return new Token({
|
|
||||||
access_token: localStorage.getItem('access_token'),
|
|
||||||
refresh_token: localStorage.getItem('refresh_token'),
|
|
||||||
token_type: localStorage.getItem('token_type')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(hash?: any) {
|
|
||||||
if (hash) {
|
|
||||||
this.access_token = hash.access_token;
|
|
||||||
this.refresh_token = hash.refresh_token;
|
|
||||||
|
|
||||||
if (hash.token_type === 'bearer') {
|
|
||||||
this.token_type = 'Bearer';
|
|
||||||
} else {
|
|
||||||
this.token_type = hash.token_type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
localStorage.setItem('access_token', this.access_token);
|
|
||||||
localStorage.setItem('refresh_token', this.refresh_token);
|
|
||||||
localStorage.setItem('token_type', this.token_type);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { Token } from './token.model';
|
|
||||||
|
|
||||||
export class User {
|
|
||||||
username: string;
|
|
||||||
token: Token;
|
|
||||||
|
|
||||||
static load() {
|
|
||||||
return new User(localStorage.getItem('username'), Token.load());
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(username: string, hash_token: any) {
|
|
||||||
this.username = username;
|
|
||||||
this.token = new Token(hash_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
localStorage.setItem('username', this.username);
|
|
||||||
this.token.save();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ import { Observable } from 'rxjs/Observable';
|
||||||
import { Pagination } from './pagination.model';
|
import { Pagination } from './pagination.model';
|
||||||
import { Search } from '../../shared';
|
import { Search } from '../../shared';
|
||||||
import { SortField } from './sort-field.type';
|
import { SortField } from './sort-field.type';
|
||||||
import { AuthService } from '../../shared';
|
import { AuthHttp, AuthService } from '../../shared';
|
||||||
import { Video } from './video.model';
|
import { Video } from './video.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -14,6 +14,7 @@ export class VideoService {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private authHttp: AuthHttp,
|
||||||
private http: Http
|
private http: Http
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@ -35,8 +36,7 @@ export class VideoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeVideo(id: string) {
|
removeVideo(id: string) {
|
||||||
const options = this.authService.getAuthRequestOptions();
|
return this.authHttp.delete(VideoService.BASE_VIDEO_URL + id)
|
||||||
return this.http.delete(VideoService.BASE_VIDEO_URL + id, options)
|
|
||||||
.map(res => <number> res.status)
|
.map(res => <number> res.status)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,8 +130,22 @@ export class VideoAddComponent implements OnInit {
|
||||||
};
|
};
|
||||||
|
|
||||||
item.onError = (response: string, status: number) => {
|
item.onError = (response: string, status: number) => {
|
||||||
this.error = (status === 400) ? response : 'Unknow error';
|
// We need to handle manually these cases beceause we use the FileUpload component
|
||||||
|
if (status === 400) {
|
||||||
|
this.error = response;
|
||||||
|
} else if (status === 401) {
|
||||||
|
this.error = 'Access token was expired, refreshing token...';
|
||||||
|
this.authService.refreshAccessToken().subscribe(
|
||||||
|
() => {
|
||||||
|
// Update the uploader request header
|
||||||
|
this.uploader.authToken = this.authService.getRequestHeaderValue();
|
||||||
|
this.error += ' access token refreshed. Please retry your request.';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.error = 'Unknow error';
|
||||||
console.error(this.error);
|
console.error(this.error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
import { enableProdMode } from '@angular/core';
|
import { enableProdMode, provide } from '@angular/core';
|
||||||
|
import {
|
||||||
|
HTTP_PROVIDERS,
|
||||||
|
RequestOptions,
|
||||||
|
XHRBackend
|
||||||
|
} from '@angular/http';
|
||||||
import { bootstrap } from '@angular/platform-browser-dynamic';
|
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
import { routes } from './app/app.routes';
|
import { routes } from './app/app.routes';
|
||||||
|
import { AuthHttp, AuthService } from './app/shared';
|
||||||
|
|
||||||
if (process.env.ENV === 'production') {
|
if (process.env.ENV === 'production') {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap(AppComponent, [ provideRouter(routes) ]);
|
bootstrap(AppComponent, [
|
||||||
|
HTTP_PROVIDERS,
|
||||||
|
provide(AuthHttp, {
|
||||||
|
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) => {
|
||||||
|
return new AuthHttp(backend, defaultOptions, authService);
|
||||||
|
},
|
||||||
|
deps: [ XHRBackend, RequestOptions, AuthService ]
|
||||||
|
}),
|
||||||
|
AuthService,
|
||||||
|
provideRouter(routes)
|
||||||
|
]);
|
||||||
|
|
|
@ -34,17 +34,17 @@
|
||||||
"src/app/login/index.ts",
|
"src/app/login/index.ts",
|
||||||
"src/app/login/login.component.ts",
|
"src/app/login/login.component.ts",
|
||||||
"src/app/login/login.routes.ts",
|
"src/app/login/login.routes.ts",
|
||||||
|
"src/app/shared/auth/auth-http.service.ts",
|
||||||
|
"src/app/shared/auth/auth-status.model.ts",
|
||||||
|
"src/app/shared/auth/auth.service.ts",
|
||||||
|
"src/app/shared/auth/index.ts",
|
||||||
|
"src/app/shared/auth/user.model.ts",
|
||||||
"src/app/shared/index.ts",
|
"src/app/shared/index.ts",
|
||||||
"src/app/shared/search/index.ts",
|
"src/app/shared/search/index.ts",
|
||||||
"src/app/shared/search/search-field.type.ts",
|
"src/app/shared/search/search-field.type.ts",
|
||||||
"src/app/shared/search/search.component.ts",
|
"src/app/shared/search/search.component.ts",
|
||||||
"src/app/shared/search/search.model.ts",
|
"src/app/shared/search/search.model.ts",
|
||||||
"src/app/shared/search/search.service.ts",
|
"src/app/shared/search/search.service.ts",
|
||||||
"src/app/shared/users/auth-status.model.ts",
|
|
||||||
"src/app/shared/users/auth.service.ts",
|
|
||||||
"src/app/shared/users/index.ts",
|
|
||||||
"src/app/shared/users/token.model.ts",
|
|
||||||
"src/app/shared/users/user.model.ts",
|
|
||||||
"src/app/videos/index.ts",
|
"src/app/videos/index.ts",
|
||||||
"src/app/videos/shared/index.ts",
|
"src/app/videos/shared/index.ts",
|
||||||
"src/app/videos/shared/loader/index.ts",
|
"src/app/videos/shared/loader/index.ts",
|
||||||
|
|
Loading…
Reference in a new issue