Login in Angular : first draft
authorChocobozzz <florian.bigard@gmail.com>
Tue, 22 Mar 2016 14:51:54 +0000 (15:51 +0100)
committerChocobozzz <florian.bigard@gmail.com>
Tue, 22 Mar 2016 14:51:54 +0000 (15:51 +0100)
client/angular/app/app.component.html
client/angular/app/app.component.ts
client/angular/users/components/login/login.component.html [new file with mode: 0644]
client/angular/users/components/login/login.component.scss [new file with mode: 0644]
client/angular/users/components/login/login.component.ts [new file with mode: 0644]
client/angular/users/models/authStatus.ts [new file with mode: 0644]
client/angular/users/models/token.ts [new file with mode: 0644]
client/angular/users/services/auth.service.ts [new file with mode: 0644]

index 25911731edf843da47618903f07f9eae4ad7a01b..647697a0a62f82035ef998c89d9501f3f32a0677 100644 (file)
   <div class="row">
 
     <menu class="col-md-2">
+      <div class="panel_block">
+        <div id="panel_user_login" class="panel_button">
+          <span class="glyphicon glyphicon-user"></span>
+          <a *ngIf="!isLoggedIn" [routerLink]="['UserLogin']">Login</a>
+          <a *ngIf="isLoggedIn" (click)="logout()">Logout</a>
+        </div>
+      </div>
+
       <div class="panel_block">
         <div id="panel_get_videos" class="panel_button">
           <span class="glyphicon glyphicon-list"></span>
@@ -31,7 +39,7 @@
 
       <div class="panel_block">
         <div id="panel_make_friends" class="panel_button">
-          <span class="glyphicon glyphicon-user"></span>
+          <span class="glyphicon glyphicon-cloud"></span>
           <a (click)='makeFriends()'>Make friends</a>
         </div>
 
index cb961a3c8157052b0c3f16abb10cebeecc235ec0..1648b887020df7fcaa73cbdca7a5bc264f902e65 100644 (file)
@@ -7,8 +7,16 @@ import { VideosListComponent } from '../videos/components/list/videos-list.compo
 import { VideosWatchComponent } from '../videos/components/watch/videos-watch.component';
 import { VideosService } from '../videos/services/videos.service';
 import { FriendsService } from '../friends/services/friends.service';
+import { UserLoginComponent } from '../users/components/login/login.component';
+import { AuthService } from '../users/services/auth.service';
+import { AuthStatus } from '../users/models/authStatus';
 
 @RouteConfig([
+  {
+    path: '/users/login',
+    name: 'UserLogin',
+    component: UserLoginComponent
+  },
   {
     path: '/videos/list',
     name: 'VideosList',
@@ -32,11 +40,30 @@ import { FriendsService } from '../friends/services/friends.service';
     templateUrl: 'app/angular/app/app.component.html',
     styleUrls: [ 'app/angular/app/app.component.css' ],
     directives: [ ROUTER_DIRECTIVES ],
-    providers: [ ROUTER_PROVIDERS, HTTP_PROVIDERS, ElementRef, VideosService, FriendsService ]
+    providers: [ ROUTER_PROVIDERS, HTTP_PROVIDERS,
+                 ElementRef, VideosService, FriendsService,
+                 AuthService
+               ]
 })
 
 export class AppComponent {
-  constructor(private _friendsService: FriendsService, private _router: Router) {}
+  isLoggedIn: boolean;
+
+  constructor(private _friendsService: FriendsService,
+              private _authService: AuthService,
+              private _router: Router
+  ) {
+    if (localStorage.getItem('access_token')) this.isLoggedIn = true;
+    else this.isLoggedIn = false;
+
+    this._authService.loginChanged$.subscribe(
+      status => {
+        if (status === AuthStatus.LoggedIn) {
+          this.isLoggedIn = true;
+        }
+      }
+    );
+  }
 
   doSearch(search: string) {
     if (search !== '') {
@@ -46,6 +73,10 @@ export class AppComponent {
     }
   }
 
+  logout() {
+    // this._authService.logout();
+  }
+
   makeFriends() {
     this._friendsService.makeFriends().subscribe(
       status => {
diff --git a/client/angular/users/components/login/login.component.html b/client/angular/users/components/login/login.component.html
new file mode 100644 (file)
index 0000000..9406945
--- /dev/null
@@ -0,0 +1,14 @@
+<h3>Login</h3>
+<form role="form" (submit)="login(username.value, password.value)">
+  <div class="form-group">
+    <label for="username">Username</label>
+    <input type="text" #username class="form-control" id="username" placeholder="Username">
+  </div>
+
+  <div class="form-group">
+    <label for="password">Password</label>
+    <input type="password" #password class="form-control" id="password" placeholder="Password">
+  </div>
+
+  <input type="submit" value="Login" class="btn btn-default">
+</form>
diff --git a/client/angular/users/components/login/login.component.scss b/client/angular/users/components/login/login.component.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/client/angular/users/components/login/login.component.ts b/client/angular/users/components/login/login.component.ts
new file mode 100644 (file)
index 0000000..0881a3a
--- /dev/null
@@ -0,0 +1,32 @@
+import { Component } from 'angular2/core';
+import { Router } from 'angular2/router';
+
+import { AuthService } from '../../services/auth.service';
+import { AuthStatus } from '../../models/authStatus';
+import { Token } from '../../models/token';
+
+@Component({
+  selector: 'my-user-login',
+  styleUrls: [ 'app/angular/users/components/login/login.component.css' ],
+  templateUrl: 'app/angular/users/components/login/login.component.html'
+})
+
+export class UserLoginComponent {
+  constructor(private _authService: AuthService, private _router: Router) {}
+
+  login(username: string, password: string) {
+    this._authService.login(username, password).subscribe(
+      result => {
+        if (result.error) return alert(result.error_description);
+
+        let token = new Token(result);
+        token.save();
+
+        this._authService.setStatus(AuthStatus.LoggedIn);
+
+        this._router.navigate(['VideosList']);
+      },
+      error => alert(error)
+    );
+  }
+}
diff --git a/client/angular/users/models/authStatus.ts b/client/angular/users/models/authStatus.ts
new file mode 100644 (file)
index 0000000..f646bd4
--- /dev/null
@@ -0,0 +1,4 @@
+export enum AuthStatus {
+  LoggedIn,
+  LoggedOut
+}
diff --git a/client/angular/users/models/token.ts b/client/angular/users/models/token.ts
new file mode 100644 (file)
index 0000000..688dfdc
--- /dev/null
@@ -0,0 +1,17 @@
+export class Token {
+  access_token: string;
+  refresh_token: string;
+  token_type: string;
+
+  constructor (hash) {
+    this.access_token = hash.access_token;
+    this.refresh_token = hash.refresh_token;
+    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/angular/users/services/auth.service.ts b/client/angular/users/services/auth.service.ts
new file mode 100644 (file)
index 0000000..a512c3d
--- /dev/null
@@ -0,0 +1,54 @@
+import { Injectable } from 'angular2/core';
+import { Http, Response, Headers, URLSearchParams } from 'angular2/http';
+import { Observable, Subject } from 'rxjs/Rx';
+
+import { Token } from '../models/token';
+import { AuthStatus } from '../models/authStatus';
+
+@Injectable()
+export class AuthService {
+  private _loginChanged = new Subject<AuthStatus>();
+
+  private _baseLoginUrl = '/api/v1/users/token';
+  private _clientId = '56f055587305d40b21904240';
+  private _clientSecret = 'megustalabanana';
+
+  loginChanged$ = this._loginChanged.asObservable();
+
+  constructor (private http: Http) {}
+
+  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(this._baseLoginUrl, 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');
+  }
+}