diff --git a/client/angular/app/app.component.ts b/client/angular/app/app.component.ts index 68c9ba0090510fd8d9e3c1c3446e74dec5a4283c..da995983635f1fb1fa50ccb04421085df5da7454 100644 --- a/client/angular/app/app.component.ts +++ b/client/angular/app/app.component.ts @@ -53,11 +53,7 @@ export class AppComponent { private _authService: AuthService, private _router: Router ) { - if (localStorage.getItem('access_token')) { - this.isLoggedIn = true; - } else { - this.isLoggedIn = false; - } + this.isLoggedIn = this._authService.isLoggedIn(); this._authService.loginChanged$.subscribe( status => { diff --git a/client/angular/users/components/login/login.component.ts b/client/angular/users/components/login/login.component.ts index 0881a3a15295d680c22a83387ab344ad882baa34..35dea4f9bcaff0b498644f35ea8777bd56086fa4 100644 --- a/client/angular/users/components/login/login.component.ts +++ b/client/angular/users/components/login/login.component.ts @@ -3,7 +3,7 @@ import { Router } from 'angular2/router'; import { AuthService } from '../../services/auth.service'; import { AuthStatus } from '../../models/authStatus'; -import { Token } from '../../models/token'; +import { User } from '../../models/user'; @Component({ selector: 'my-user-login', @@ -17,16 +17,21 @@ export class UserLoginComponent { 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(); + const user = new User(username, result); + user.save(); this._authService.setStatus(AuthStatus.LoggedIn); this._router.navigate(['VideosList']); }, - error => alert(error) + error => { + if (error.error === 'invalid_grant') { + alert('Credentials are invalid.'); + } + else { + alert(`${error.error}: ${error.error_description}`) + } + } ); } } diff --git a/client/angular/users/models/token.ts b/client/angular/users/models/token.ts index 688dfdc803c2d08c83d949a0216be8cd4f7ecefa..906bf501b401595b4dca25d6fe042b6e114ec53f 100644 --- a/client/angular/users/models/token.ts +++ b/client/angular/users/models/token.ts @@ -3,13 +3,27 @@ export class Token { 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; + 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() { + static load(): Token { + return new Token({ + access_token: localStorage.getItem('access_token'), + refresh_token: localStorage.getItem('refresh_token'), + token_type: localStorage.getItem('token_type') + }); + } + + save():void { 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/models/user.ts b/client/angular/users/models/user.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c56a61327a8fd4186b81d290592c38b00e9a661 --- /dev/null +++ b/client/angular/users/models/user.ts @@ -0,0 +1,20 @@ +import { Token } from './token'; + +export class User { + username: string; + token: Token; + + constructor (username: string, hash_token: any) { + this.username = username; + this.token = new Token(hash_token); + } + + static load(): User { + return new User(localStorage.getItem('username'), Token.load()); + } + + save(): void { + localStorage.setItem('username', this.username); + this.token.save(); + } +} diff --git a/client/angular/users/services/auth.service.ts b/client/angular/users/services/auth.service.ts index 80886346ca529f39d841e084df51184bd09aa24b..89412c3dff559abf555ae1664282253b08349236 100644 --- a/client/angular/users/services/auth.service.ts +++ b/client/angular/users/services/auth.service.ts @@ -1,20 +1,23 @@ import { Injectable } from 'angular2/core'; -import { Http, Response, Headers, URLSearchParams } from 'angular2/http'; +import { Http, Response, Headers, URLSearchParams, RequestOptions } from 'angular2/http'; import { Observable, Subject } from 'rxjs/Rx'; import { AuthStatus } from '../models/authStatus'; +import { User } from '../models/user'; @Injectable() export class AuthService { - loginChanged$ = this._loginChanged.asObservable(); - - private _loginChanged = new Subject<AuthStatus>(); + loginChanged$; + private _loginChanged; private _baseLoginUrl = '/api/v1/users/token'; private _clientId = '56f055587305d40b21904240'; private _clientSecret = 'megustalabanana'; - constructor (private http: Http) {} + constructor (private http: Http) { + this._loginChanged = new Subject<AuthStatus>(); + this.loginChanged$ = this._loginChanged.asObservable(); + } login(username: string, password: string) { let body = new URLSearchParams(); @@ -42,12 +45,46 @@ export class AuthService { // TODO make HTTP request } + getRequestHeader(): Headers { + return new Headers({ 'Authorization': `${this.getTokenType()} ${this.getToken()}` }); + } + + getAuthRequestOptions(): RequestOptions { + return new RequestOptions({ headers: this.getRequestHeader() }); + } + + getToken(): string { + return localStorage.getItem('access_token'); + } + + getTokenType(): string { + return localStorage.getItem('token_type'); + } + + getUser(): User { + if (this.isLoggedIn() === false) { + return null; + } + + const user = User.load(); + + return user; + } + + isLoggedIn(): boolean { + if (this.getToken()) { + return true; + } else { + return false; + } + } + setStatus(status: AuthStatus) { this._loginChanged.next(status); } private handleError (error: Response) { console.error(error); - return Observable.throw(error.json().error || 'Server error'); + return Observable.throw(error.json() || { error: 'Server error' }); } } diff --git a/client/angular/videos/components/add/videos-add.component.ts b/client/angular/videos/components/add/videos-add.component.ts index 7ae11db226db5e5e628172f8391d71a432af1b2b..bc7b4057c469f7b15c8b4860ed2b38f8b806f167 100644 --- a/client/angular/videos/components/add/videos-add.component.ts +++ b/client/angular/videos/components/add/videos-add.component.ts @@ -1,6 +1,9 @@ import { Component, ElementRef, OnInit } from 'angular2/core'; import { Router } from 'angular2/router'; +import { AuthService } from '../../../users/services/auth.service'; +import { User } from '../../../users/models/user'; + // TODO: import it with systemjs declare var jQuery:any; @@ -11,14 +14,19 @@ declare var jQuery:any; }) export class VideosAddComponent implements OnInit { + user: User; fileToUpload: any; progressBar: { value: number; max: number; } = { value: 0, max: 0 }; private _form: any; - constructor(private _router: Router, private _elementRef: ElementRef) {} + constructor( + private _router: Router, private _elementRef: ElementRef, + private _authService: AuthService + ) {} ngOnInit() { + this.user = User.load(); jQuery(this._elementRef.nativeElement).find('#videofile').fileupload({ url: '/api/v1/videos', dataType: 'json', @@ -49,6 +57,7 @@ export class VideosAddComponent implements OnInit { } uploadFile() { + this._form.headers = this._authService.getRequestHeader().toJSON(); this._form.formData = jQuery(this._elementRef.nativeElement).find('form').serializeArray(); this._form.submit(); } diff --git a/client/angular/videos/components/list/videos-list.component.html b/client/angular/videos/components/list/videos-list.component.html index 38708aff613c0db8f4958ebbe53488d17d9a5bd1..75b860f387577dedfbe487b5421f3ae695721581 100644 --- a/client/angular/videos/components/list/videos-list.component.html +++ b/client/angular/videos/components/list/videos-list.component.html @@ -2,7 +2,7 @@ <div> <a [routerLink]="['VideosWatch', { id: video.id }]" class="video_name">{{ video.name }}</a> <span class="video_pod_url">{{ video.podUrl }}</span> - <span *ngIf="video.isLocal === true" (click)="removeVideo(video.id)" class="video_remove glyphicon glyphicon-remove"></span> + <span *ngIf="video.isLocal === true && user && video.author === user.username" (click)="removeVideo(video.id)" class="video_remove glyphicon glyphicon-remove"></span> </div> <div class="video_description"> diff --git a/client/angular/videos/components/list/videos-list.component.ts b/client/angular/videos/components/list/videos-list.component.ts index ae58f4d7e8abf27a4b1330aac1c8d6ff26c11186..b9b440d40b3afa5d97030be46e0443c95d1088c3 100644 --- a/client/angular/videos/components/list/videos-list.component.ts +++ b/client/angular/videos/components/list/videos-list.component.ts @@ -1,6 +1,8 @@ import { Component, OnInit } from 'angular2/core'; import { ROUTER_DIRECTIVES, RouteParams } from 'angular2/router'; +import { AuthService } from '../../../users/services/auth.service'; +import { User } from '../../../users/models/user'; import { VideosService } from '../../services/videos.service'; import { Video } from '../../models/video'; @@ -12,11 +14,13 @@ import { Video } from '../../models/video'; }) export class VideosListComponent implements OnInit { + user: User = null; videos: Video[]; private search: string; constructor( + private _authService: AuthService, private _videosService: VideosService, routeParams: RouteParams ) { @@ -24,13 +28,17 @@ export class VideosListComponent implements OnInit { } ngOnInit() { + if (this._authService.isLoggedIn()) { + this.user = User.load(); + } + this.getVideos(); } getVideos() { let observable = null; - if (this.search !== null) { + if (this.search !== null) {"" observable = this._videosService.searchVideos(this.search); } else { observable = this._videosService.getVideos(); diff --git a/client/angular/videos/components/watch/videos-watch.component.ts b/client/angular/videos/components/watch/videos-watch.component.ts index 28786ebb9c129328727eae6e6f14b6b5f4f1445e..d1b90c190da842faeb1763b1f89654db10581acc 100644 --- a/client/angular/videos/components/watch/videos-watch.component.ts +++ b/client/angular/videos/components/watch/videos-watch.component.ts @@ -1,5 +1,3 @@ -/// <reference path='../../../../typings/browser/ambient/webtorrent/webtorrent.d.ts' /> - import { Component, OnInit, ElementRef } from 'angular2/core'; import { RouteParams, CanDeactivate, ComponentInstruction } from 'angular2/router'; diff --git a/client/angular/videos/services/videos.service.ts b/client/angular/videos/services/videos.service.ts index 17ae89c8bf5d2e3b22c69661c0d335817a9bc5c3..74b6a1ddc46f5573d24e344671e4d87bc33c2de3 100644 --- a/client/angular/videos/services/videos.service.ts +++ b/client/angular/videos/services/videos.service.ts @@ -1,14 +1,15 @@ -import {Injectable} from 'angular2/core'; -import {Http, Response} from 'angular2/http'; -import {Observable} from 'rxjs/Rx'; +import { Injectable } from 'angular2/core'; +import { Http, Response } from 'angular2/http'; +import { Observable } from 'rxjs/Rx'; -import {Video} from '../models/video'; +import { Video } from '../models/video'; +import { AuthService } from '../../users/services/auth.service'; @Injectable() export class VideosService { private _baseVideoUrl = '/api/v1/videos/'; - constructor (private http: Http) {} + constructor (private http: Http, private _authService: AuthService) {} getVideos() { return this.http.get(this._baseVideoUrl) @@ -24,7 +25,8 @@ export class VideosService { removeVideo(id: string) { if (confirm('Are you sure?')) { - return this.http.delete(this._baseVideoUrl + id) + const options = this._authService.getAuthRequestOptions(); + return this.http.delete(this._baseVideoUrl + id, options) .map(res => <number> res.status) .catch(this.handleError); }