Client: Add authHttp service that authentificates the http request and
authorChocobozzz <florian.bigard@gmail.com>
Wed, 20 Jul 2016 14:24:18 +0000 (16:24 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Wed, 20 Jul 2016 14:25:06 +0000 (16:25 +0200)
optionally refresh the access token if needed

18 files changed:
client/src/app/app.component.ts
client/src/app/friends/friend.service.ts
client/src/app/login/login.component.ts
client/src/app/shared/auth/auth-http.service.ts [new file with mode: 0644]
client/src/app/shared/auth/auth-status.model.ts [new file with mode: 0644]
client/src/app/shared/auth/auth.service.ts [new file with mode: 0644]
client/src/app/shared/auth/index.ts [new file with mode: 0644]
client/src/app/shared/auth/user.model.ts [new file with mode: 0644]
client/src/app/shared/index.ts
client/src/app/shared/users/auth-status.model.ts [deleted file]
client/src/app/shared/users/auth.service.ts [deleted file]
client/src/app/shared/users/index.ts [deleted file]
client/src/app/shared/users/token.model.ts [deleted file]
client/src/app/shared/users/user.model.ts [deleted file]
client/src/app/videos/shared/video.service.ts
client/src/app/videos/video-add/video-add.component.ts
client/src/main.ts
client/tsconfig.json

index 354d00a7a78479598662767e70b39098518d9959..f53896bcf151dd09125b1dc4b8c140fe4389d97e 100644 (file)
@@ -1,5 +1,4 @@
 import { Component } from '@angular/core';
-import { HTTP_PROVIDERS } from '@angular/http';
 import { ActivatedRoute, Router, ROUTER_DIRECTIVES } from '@angular/router';
 
 import { FriendService } from './friends';
@@ -16,7 +15,7 @@ import { VideoService } from './videos';
     template: require('./app.component.html'),
     styles: [ require('./app.component.scss') ],
     directives: [ ROUTER_DIRECTIVES, SearchComponent ],
-    providers: [ AuthService, FriendService, HTTP_PROVIDERS, VideoService, SearchService ]
+    providers: [ FriendService, VideoService, SearchService ]
 })
 
 export class AppComponent {
@@ -35,14 +34,20 @@ export class AppComponent {
       status => {
         if (status === AuthStatus.LoggedIn) {
           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() {
-    // this._authService.logout();
+    this.authService.logout();
+    this.authService.setStatus(AuthStatus.LoggedOut);
   }
 
   makeFriends() {
index f956a5ece7d36541169fcfe757f91a360d658f98..7710464846633a0448d7586594b49c0c54062c7e 100644 (file)
@@ -1,25 +1,23 @@
 import { Injectable } from '@angular/core';
-import { Http, Response } from '@angular/http';
+import { Response } from '@angular/http';
 import { Observable } from 'rxjs/Observable';
 
-import { AuthService } from '../shared';
+import { AuthHttp, AuthService } from '../shared';
 
 @Injectable()
 export class FriendService {
   private static BASE_FRIEND_URL: string = '/api/v1/pods/';
 
-  constructor (private http: Http, private authService: AuthService) {}
+  constructor (private authHttp: AuthHttp, private authService: AuthService) {}
 
   makeFriends() {
-    const headers = this.authService.getRequestHeader();
-    return this.http.get(FriendService.BASE_FRIEND_URL + 'makefriends', { headers })
+    return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'makefriends')
                     .map(res => res.status)
                     .catch(this.handleError);
   }
 
   quitFriends() {
-    const headers = this.authService.getRequestHeader();
-    return this.http.get(FriendService.BASE_FRIEND_URL + 'quitfriends', { headers })
+    return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'quitfriends')
                     .map(res => res.status)
                     .catch(this.handleError);
   }
index bcfa021fab5a2e9fac85d2dfc8966a580cb9a5f7..ddd62462ebed68cbf100f00138c8f0d1e2cb6db1 100644 (file)
@@ -1,7 +1,7 @@
 import { Component } from '@angular/core';
 import { Router } from '@angular/router';
 
-import { AuthService, AuthStatus, User } from '../shared';
+import { AuthService } from '../shared';
 
 @Component({
   selector: 'my-login',
@@ -21,14 +21,11 @@ export class LoginComponent {
       result => {
         this.error = null;
 
-        const user = new User(username, result);
-        user.save();
-
-        this.authService.setStatus(AuthStatus.LoggedIn);
-
         this.router.navigate(['/videos/list']);
       },
       error => {
+        console.error(error);
+
         if (error.error === 'invalid_grant') {
           this.error = 'Credentials are invalid.';
         } else {
diff --git a/client/src/app/shared/auth/auth-http.service.ts b/client/src/app/shared/auth/auth-http.service.ts
new file mode 100644 (file)
index 0000000..ff8099a
--- /dev/null
@@ -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()}`);
+  }
+}
diff --git a/client/src/app/shared/auth/auth-status.model.ts b/client/src/app/shared/auth/auth-status.model.ts
new file mode 100644 (file)
index 0000000..f646bd4
--- /dev/null
@@ -0,0 +1,4 @@
+export enum AuthStatus {
+  LoggedIn,
+  LoggedOut
+}
diff --git a/client/src/app/shared/auth/auth.service.ts b/client/src/app/shared/auth/auth.service.ts
new file mode 100644 (file)
index 0000000..47f7e13
--- /dev/null
@@ -0,0 +1,172 @@
+import { Injectable } from '@angular/core';
+import { Headers, Http, RequestOptions, Response, URLSearchParams } from '@angular/http';
+import { Observable } from 'rxjs/Observable';
+import { Subject } from 'rxjs/Subject';
+
+import { AuthStatus } from './auth-status.model';
+import { User } from './user.model';
+
+@Injectable()
+export class AuthService {
+  private static BASE_CLIENT_URL = '/api/v1/users/client';
+  private static BASE_TOKEN_URL = '/api/v1/users/token';
+
+  loginChangedSource: Observable<AuthStatus>;
+
+  private clientId: string;
+  private clientSecret: string;
+  private loginChanged: Subject<AuthStatus>;
+  private user: User = null;
+
+  constructor(private http: Http) {
+    this.loginChanged = new Subject<AuthStatus>();
+    this.loginChangedSource = this.loginChanged.asObservable();
+
+    // Fetch the client_id/client_secret
+    // FIXME: save in local storage?
+    this.http.get(AuthService.BASE_CLIENT_URL)
+      .map(res => res.json())
+      .catch(this.handleError)
+      .subscribe(
+        result => {
+          this.clientId = result.client_id;
+          this.clientSecret = result.client_secret;
+          console.log('Client credentials loaded.');
+        },
+        error => {
+          alert(error);
+        }
+      );
+
+    // Return null if there is nothing to load
+    this.user = User.load();
+  }
+
+  getAuthRequestOptions(): RequestOptions {
+    return new RequestOptions({ headers: this.getRequestHeader() });
+  }
+
+  getRefreshToken() {
+    if (this.user === null) return null;
+
+    return this.user.getRefreshToken();
+  }
+
+  getRequestHeader() {
+    return new Headers({ 'Authorization': this.getRequestHeaderValue() });
+  }
+
+  getRequestHeaderValue() {
+    return `${this.getTokenType()} ${this.getToken()}`;
+  }
+
+  getToken() {
+    if (this.user === null) return null;
+
+    return this.user.getAccessToken();
+  }
+
+  getTokenType() {
+    if (this.user === null) return null;
+
+    return this.user.getTokenType();
+  }
+
+  getUser(): User {
+    return this.user;
+  }
+
+  isLoggedIn() {
+    if (this.getToken()) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  login(username: string, password: string) {
+    let body = new URLSearchParams();
+    body.set('client_id', this.clientId);
+    body.set('client_secret', this.clientSecret);
+    body.set('response_type', 'code');
+    body.set('grant_type', 'password');
+    body.set('scope', 'upload');
+    body.set('username', username);
+    body.set('password', password);
+
+    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 => {
+                      res.username = username;
+                      return res;
+                    })
+                    .map(res => this.handleLogin(res))
+                    .catch(this.handleError);
+  }
+
+  logout() {
+    // 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) {
+    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) {
+    console.error(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();
+  }
+}
diff --git a/client/src/app/shared/auth/index.ts b/client/src/app/shared/auth/index.ts
new file mode 100644 (file)
index 0000000..aafaacb
--- /dev/null
@@ -0,0 +1,4 @@
+export * from './auth-http.service';
+export * from './auth-status.model';
+export * from './auth.service';
+export * from './user.model';
diff --git a/client/src/app/shared/auth/user.model.ts b/client/src/app/shared/auth/user.model.ts
new file mode 100644 (file)
index 0000000..98852f8
--- /dev/null
@@ -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);
+  }
+}
index 0cab7dad0a92f0e7d1c56e2518c85e8afe435585..dfea4c67cdb959ed561a9dfc2d01774d0e1efca2 100644 (file)
@@ -1,2 +1,2 @@
+export * from './auth';
 export * from './search';
-export * from './users'
diff --git a/client/src/app/shared/users/auth-status.model.ts b/client/src/app/shared/users/auth-status.model.ts
deleted file mode 100644 (file)
index f646bd4..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-export enum AuthStatus {
-  LoggedIn,
-  LoggedOut
-}
diff --git a/client/src/app/shared/users/auth.service.ts b/client/src/app/shared/users/auth.service.ts
deleted file mode 100644 (file)
index 1c822c1..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-import { Injectable } from '@angular/core';
-import { Headers, Http, RequestOptions, Response, URLSearchParams } from '@angular/http';
-import { Observable } from 'rxjs/Observable';
-import { Subject } from 'rxjs/Subject';
-
-import { AuthStatus } from './auth-status.model';
-import { User } from './user.model';
-
-@Injectable()
-export class AuthService {
-  private static BASE_CLIENT_URL = '/api/v1/users/client';
-  private static BASE_LOGIN_URL = '/api/v1/users/token';
-
-  loginChangedSource: Observable<AuthStatus>;
-
-  private clientId: string;
-  private clientSecret: string;
-  private loginChanged: Subject<AuthStatus>;
-
-  constructor(private http: Http) {
-    this.loginChanged = new Subject<AuthStatus>();
-    this.loginChangedSource = this.loginChanged.asObservable();
-
-    // Fetch the client_id/client_secret
-    // FIXME: save in local storage?
-    this.http.get(AuthService.BASE_CLIENT_URL)
-      .map(res => res.json())
-      .catch(this.handleError)
-      .subscribe(
-        result => {
-          this.clientId = result.client_id;
-          this.clientSecret = result.client_secret;
-          console.log('Client credentials loaded.');
-        },
-        error => {
-          alert(error);
-        }
-      );
-  }
-
-  getAuthRequestOptions(): RequestOptions {
-    return new RequestOptions({ headers: this.getRequestHeader() });
-  }
-
-  getRequestHeader() {
-    return new Headers({ 'Authorization': this.getRequestHeaderValue() });
-  }
-
-  getRequestHeaderValue() {
-    return `${this.getTokenType()} ${this.getToken()}`;
-  }
-
-  getToken() {
-    return localStorage.getItem('access_token');
-  }
-
-  getTokenType() {
-    return localStorage.getItem('token_type');
-  }
-
-  getUser(): User {
-    if (this.isLoggedIn() === false) {
-      return null;
-    }
-
-    const user = User.load();
-
-    return user;
-  }
-
-  isLoggedIn() {
-    if (this.getToken()) {
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  login(username: string, password: string) {
-    let body = new URLSearchParams();
-    body.set('client_id', this.clientId);
-    body.set('client_secret', this.clientSecret);
-    body.set('response_type', 'code');
-    body.set('grant_type', 'password');
-    body.set('scope', 'upload');
-    body.set('username', username);
-    body.set('password', password);
-
-    let headers = new Headers();
-    headers.append('Content-Type', 'application/x-www-form-urlencoded');
-
-    let options = {
-      headers: headers
-    };
-
-    return this.http.post(AuthService.BASE_LOGIN_URL, body.toString(), options)
-                    .map(res => res.json())
-                    .catch(this.handleError);
-  }
-
-  logout() {
-    // TODO make HTTP request
-  }
-
-  setStatus(status: AuthStatus) {
-    this.loginChanged.next(status);
-  }
-
-  private handleError (error: Response) {
-    console.error(error);
-    return Observable.throw(error.json() || { error: 'Server error' });
-  }
-}
diff --git a/client/src/app/shared/users/index.ts b/client/src/app/shared/users/index.ts
deleted file mode 100644 (file)
index c6816b3..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './auth-status.model';
-export * from './auth.service';
-export * from './token.model';
-export * from './user.model';
diff --git a/client/src/app/shared/users/token.model.ts b/client/src/app/shared/users/token.model.ts
deleted file mode 100644 (file)
index 021c83f..0000000
+++ /dev/null
@@ -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);
-  }
-}
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts
deleted file mode 100644 (file)
index ca0a5f2..0000000
+++ /dev/null
@@ -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();
-  }
-}
index dcbef77177945e191a8ec317848442012708ae53..b4396f76794abe1eebc2265e66959f3f6ce9f08d 100644 (file)
@@ -5,7 +5,7 @@ import { Observable } from 'rxjs/Observable';
 import { Pagination } from './pagination.model';
 import { Search } from '../../shared';
 import { SortField } from './sort-field.type';
-import { AuthService } from '../../shared';
+import { AuthHttp, AuthService } from '../../shared';
 import { Video } from './video.model';
 
 @Injectable()
@@ -14,6 +14,7 @@ export class VideoService {
 
   constructor(
     private authService: AuthService,
+    private authHttp: AuthHttp,
     private http: Http
   ) {}
 
@@ -35,10 +36,9 @@ export class VideoService {
   }
 
   removeVideo(id: string) {
-    const options = this.authService.getAuthRequestOptions();
-    return this.http.delete(VideoService.BASE_VIDEO_URL + id, options)
-                    .map(res => <number> res.status)
-                    .catch(this.handleError);
+    return this.authHttp.delete(VideoService.BASE_VIDEO_URL + id)
+                        .map(res => <number> res.status)
+                        .catch(this.handleError);
   }
 
   searchVideos(search: Search, pagination: Pagination, sort: SortField) {
index 342935e36c0eab4d48ba64a5e959f9a1b17548f8..c0f8cb9c437921f63bdbb22e8b409bb9dd18ce1d 100644 (file)
@@ -130,8 +130,22 @@ export class VideoAddComponent implements OnInit {
     };
 
     item.onError = (response: string, status: number) => {
-      this.error = (status === 400) ? response : 'Unknow error';
-      console.error(this.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);
+      }
     };
 
 
index f9c1d50b8f963efafbae056c8d861627d459919a..a78d275ad4029191b3d1db1c460f4f3aba4b4ea5 100644 (file)
@@ -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 { provideRouter } from '@angular/router';
 
 import { AppComponent } from './app/app.component';
 import { routes } from './app/app.routes';
+import { AuthHttp, AuthService } from './app/shared';
 
 if (process.env.ENV === 'production') {
   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)
+]);
index c7f61902c1ea3c7877c3b953b1143eac949e5dd8..67d1fb4f179665382c89d2e336bf97b263f1c50e 100644 (file)
     "src/app/login/index.ts",
     "src/app/login/login.component.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/search/index.ts",
     "src/app/shared/search/search-field.type.ts",
     "src/app/shared/search/search.component.ts",
     "src/app/shared/search/search.model.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/shared/index.ts",
     "src/app/videos/shared/loader/index.ts",