diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2016-08-09 21:45:21 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2016-08-09 21:45:21 +0200 |
commit | 7da18e4420c4b71a8ecfda07f39324fbfec081c3 (patch) | |
tree | 2755feedd730a78cdc407e7a79bcbfce3ebe71c8 /client | |
parent | 68a3b9f2aacb0225ae8b883b561b144bac339cbd (diff) | |
download | PeerTube-7da18e4420c4b71a8ecfda07f39324fbfec081c3.tar.gz PeerTube-7da18e4420c4b71a8ecfda07f39324fbfec081c3.tar.zst PeerTube-7da18e4420c4b71a8ecfda07f39324fbfec081c3.zip |
Client: add user management
Diffstat (limited to 'client')
27 files changed, 338 insertions, 27 deletions
diff --git a/client/src/app/admin/admin.component.ts b/client/src/app/admin/admin.component.ts new file mode 100644 index 000000000..82f2529ec --- /dev/null +++ b/client/src/app/admin/admin.component.ts | |||
@@ -0,0 +1,10 @@ | |||
1 | import { Component } from '@angular/core'; | ||
2 | import { ROUTER_DIRECTIVES } from '@angular/router'; | ||
3 | |||
4 | @Component({ | ||
5 | template: '<router-outlet></router-outlet>', | ||
6 | directives: [ ROUTER_DIRECTIVES ] | ||
7 | }) | ||
8 | |||
9 | export class AdminComponent { | ||
10 | } | ||
diff --git a/client/src/app/admin/admin.routes.ts b/client/src/app/admin/admin.routes.ts new file mode 100644 index 000000000..d375a86af --- /dev/null +++ b/client/src/app/admin/admin.routes.ts | |||
@@ -0,0 +1,14 @@ | |||
1 | import { RouterConfig } from '@angular/router'; | ||
2 | |||
3 | import { AdminComponent } from './admin.component'; | ||
4 | import { UsersRoutes } from './users'; | ||
5 | |||
6 | export const AdminRoutes: RouterConfig = [ | ||
7 | { | ||
8 | path: 'admin', | ||
9 | component: AdminComponent, | ||
10 | children: [ | ||
11 | ...UsersRoutes | ||
12 | ] | ||
13 | } | ||
14 | ]; | ||
diff --git a/client/src/app/admin/index.ts b/client/src/app/admin/index.ts new file mode 100644 index 000000000..3b0540818 --- /dev/null +++ b/client/src/app/admin/index.ts | |||
@@ -0,0 +1,3 @@ | |||
1 | export * from './users'; | ||
2 | export * from './admin.component'; | ||
3 | export * from './admin.routes'; | ||
diff --git a/client/src/app/admin/users/index.ts b/client/src/app/admin/users/index.ts new file mode 100644 index 000000000..e98a81f62 --- /dev/null +++ b/client/src/app/admin/users/index.ts | |||
@@ -0,0 +1,5 @@ | |||
1 | export * from './shared'; | ||
2 | export * from './user-add'; | ||
3 | export * from './user-list'; | ||
4 | export * from './users.component'; | ||
5 | export * from './users.routes'; | ||
diff --git a/client/src/app/admin/users/shared/index.ts b/client/src/app/admin/users/shared/index.ts new file mode 100644 index 000000000..e17ee5c7a --- /dev/null +++ b/client/src/app/admin/users/shared/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './user.service'; | |||
diff --git a/client/src/app/admin/users/shared/user.service.ts b/client/src/app/admin/users/shared/user.service.ts new file mode 100644 index 000000000..be433f0a1 --- /dev/null +++ b/client/src/app/admin/users/shared/user.service.ts | |||
@@ -0,0 +1,49 @@ | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { Response } from '@angular/http'; | ||
3 | import { Observable } from 'rxjs/Observable'; | ||
4 | |||
5 | import { AuthHttp, User } from '../../../shared'; | ||
6 | |||
7 | @Injectable() | ||
8 | export class UserService { | ||
9 | // TODO: merge this constant with account | ||
10 | private static BASE_USERS_URL = '/api/v1/users/'; | ||
11 | |||
12 | constructor(private authHttp: AuthHttp) {} | ||
13 | |||
14 | addUser(username: string, password: string) { | ||
15 | const body = { | ||
16 | username, | ||
17 | password | ||
18 | }; | ||
19 | |||
20 | return this.authHttp.post(UserService.BASE_USERS_URL, body); | ||
21 | } | ||
22 | |||
23 | getUsers() { | ||
24 | return this.authHttp.get(UserService.BASE_USERS_URL) | ||
25 | .map(res => res.json()) | ||
26 | .map(this.extractUsers) | ||
27 | .catch(this.handleError); | ||
28 | } | ||
29 | |||
30 | removeUser(user: User) { | ||
31 | return this.authHttp.delete(UserService.BASE_USERS_URL + user.id); | ||
32 | } | ||
33 | |||
34 | private extractUsers(body: any) { | ||
35 | const usersJson = body.data; | ||
36 | const totalUsers = body.total; | ||
37 | const users = []; | ||
38 | for (const userJson of usersJson) { | ||
39 | users.push(new User(userJson)); | ||
40 | } | ||
41 | |||
42 | return { users, totalUsers }; | ||
43 | } | ||
44 | |||
45 | private handleError(error: Response) { | ||
46 | console.error(error); | ||
47 | return Observable.throw(error.json().error || 'Server error'); | ||
48 | } | ||
49 | } | ||
diff --git a/client/src/app/admin/users/user-add/index.ts b/client/src/app/admin/users/user-add/index.ts new file mode 100644 index 000000000..66d5ca04f --- /dev/null +++ b/client/src/app/admin/users/user-add/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './user-add.component'; | |||
diff --git a/client/src/app/admin/users/user-add/user-add.component.html b/client/src/app/admin/users/user-add/user-add.component.html new file mode 100644 index 000000000..aa102358a --- /dev/null +++ b/client/src/app/admin/users/user-add/user-add.component.html | |||
@@ -0,0 +1,29 @@ | |||
1 | <h3>Add user</h3> | ||
2 | |||
3 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
4 | |||
5 | <form role="form" (ngSubmit)="addUser(username.value, password.value)" #addUserForm="ngForm"> | ||
6 | <div class="form-group"> | ||
7 | <label for="username">Username</label> | ||
8 | <input | ||
9 | type="text" class="form-control" name="username" id="username" placeholder="Username" required | ||
10 | ngControl="username" #username="ngForm" | ||
11 | > | ||
12 | <div [hidden]="username.valid || username.pristine" class="alert alert-danger"> | ||
13 | Username is required with a length >= 3 and <= 20 | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | <div class="form-group"> | ||
18 | <label for="password">Password</label> | ||
19 | <input | ||
20 | type="password" class="form-control" name="password" id="password" placeholder="Password" required | ||
21 | ngControl="password" #password="ngForm" | ||
22 | > | ||
23 | <div [hidden]="password.valid || password.pristine" class="alert alert-danger"> | ||
24 | Password is required with a length >= 6 | ||
25 | </div> | ||
26 | </div> | ||
27 | |||
28 | <input type="submit" value="Add user" class="btn btn-default" [disabled]="!addUserForm.form.valid"> | ||
29 | </form> | ||
diff --git a/client/src/app/admin/users/user-add/user-add.component.ts b/client/src/app/admin/users/user-add/user-add.component.ts new file mode 100644 index 000000000..30ca947a0 --- /dev/null +++ b/client/src/app/admin/users/user-add/user-add.component.ts | |||
@@ -0,0 +1,33 @@ | |||
1 | import { Control, ControlGroup, Validators } from '@angular/common'; | ||
2 | import { Component, OnInit } from '@angular/core'; | ||
3 | import { Router } from '@angular/router'; | ||
4 | |||
5 | import { UserService } from '../shared'; | ||
6 | |||
7 | @Component({ | ||
8 | selector: 'my-user-add', | ||
9 | template: require('./user-add.component.html'), | ||
10 | }) | ||
11 | export class UserAddComponent implements OnInit { | ||
12 | userAddForm: ControlGroup; | ||
13 | error: string = null; | ||
14 | |||
15 | constructor(private router: Router, private userService: UserService) {} | ||
16 | |||
17 | ngOnInit() { | ||
18 | this.userAddForm = new ControlGroup({ | ||
19 | username: new Control('', Validators.compose([ Validators.required, Validators.minLength(3), Validators.maxLength(20) ])), | ||
20 | password: new Control('', Validators.compose([ Validators.required, Validators.minLength(6) ])), | ||
21 | }); | ||
22 | } | ||
23 | |||
24 | addUser(username: string, password: string) { | ||
25 | this.error = null; | ||
26 | |||
27 | this.userService.addUser(username, password).subscribe( | ||
28 | ok => this.router.navigate([ '/admin/users/list' ]), | ||
29 | |||
30 | err => this.error = err | ||
31 | ); | ||
32 | } | ||
33 | } | ||
diff --git a/client/src/app/admin/users/user-list/index.ts b/client/src/app/admin/users/user-list/index.ts new file mode 100644 index 000000000..51fbefa80 --- /dev/null +++ b/client/src/app/admin/users/user-list/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './user-list.component'; | |||
diff --git a/client/src/app/admin/users/user-list/user-list.component.html b/client/src/app/admin/users/user-list/user-list.component.html new file mode 100644 index 000000000..2aca05f2b --- /dev/null +++ b/client/src/app/admin/users/user-list/user-list.component.html | |||
@@ -0,0 +1,24 @@ | |||
1 | <table class="table table-hover"> | ||
2 | <thead> | ||
3 | <tr> | ||
4 | <th>Id</th> | ||
5 | <th>Username</th> | ||
6 | <th class="text-right">Remove</th> | ||
7 | </tr> | ||
8 | </thead> | ||
9 | |||
10 | <tbody> | ||
11 | <tr *ngFor="let user of users"> | ||
12 | <td>{{ user.id }}</td> | ||
13 | <td>{{ user.username }}</td> | ||
14 | <td class="text-right"> | ||
15 | <span class="glyphicon glyphicon-remove" *ngIf="!user.isAdmin()" (click)="removeUser(user)"></span> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </tbody> | ||
19 | </table> | ||
20 | |||
21 | <a class="add-user btn btn-success pull-right" [routerLink]="['/admin/users/add']"> | ||
22 | <span class="glyphicon glyphicon-plus"></span> | ||
23 | Add user | ||
24 | </a> | ||
diff --git a/client/src/app/admin/users/user-list/user-list.component.scss b/client/src/app/admin/users/user-list/user-list.component.scss new file mode 100644 index 000000000..e9f61e900 --- /dev/null +++ b/client/src/app/admin/users/user-list/user-list.component.scss | |||
@@ -0,0 +1,7 @@ | |||
1 | .glyphicon-remove { | ||
2 | cursor: pointer; | ||
3 | } | ||
4 | |||
5 | .add-user { | ||
6 | margin-top: 10px; | ||
7 | } | ||
diff --git a/client/src/app/admin/users/user-list/user-list.component.ts b/client/src/app/admin/users/user-list/user-list.component.ts new file mode 100644 index 000000000..598daa42a --- /dev/null +++ b/client/src/app/admin/users/user-list/user-list.component.ts | |||
@@ -0,0 +1,44 @@ | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { ROUTER_DIRECTIVES } from '@angular/router'; | ||
3 | |||
4 | import { User } from '../../../shared'; | ||
5 | import { UserService } from '../shared'; | ||
6 | |||
7 | @Component({ | ||
8 | selector: 'my-user-list', | ||
9 | template: require('./user-list.component.html'), | ||
10 | styles: [ require('./user-list.component.scss') ], | ||
11 | directives: [ ROUTER_DIRECTIVES ] | ||
12 | }) | ||
13 | export class UserListComponent implements OnInit { | ||
14 | totalUsers: number; | ||
15 | users: User[]; | ||
16 | |||
17 | constructor(private userService: UserService) {} | ||
18 | |||
19 | ngOnInit() { | ||
20 | this.getUsers(); | ||
21 | } | ||
22 | |||
23 | getUsers() { | ||
24 | this.userService.getUsers().subscribe( | ||
25 | ({ users, totalUsers }) => { | ||
26 | this.users = users; | ||
27 | this.totalUsers = totalUsers; | ||
28 | }, | ||
29 | |||
30 | err => alert(err) | ||
31 | ); | ||
32 | } | ||
33 | |||
34 | |||
35 | removeUser(user: User) { | ||
36 | if (confirm('Are you sure?')) { | ||
37 | this.userService.removeUser(user).subscribe( | ||
38 | () => this.getUsers(), | ||
39 | |||
40 | err => alert(err) | ||
41 | ); | ||
42 | } | ||
43 | } | ||
44 | } | ||
diff --git a/client/src/app/admin/users/users.component.ts b/client/src/app/admin/users/users.component.ts new file mode 100644 index 000000000..46aa0862f --- /dev/null +++ b/client/src/app/admin/users/users.component.ts | |||
@@ -0,0 +1,13 @@ | |||
1 | import { Component } from '@angular/core'; | ||
2 | import { ROUTER_DIRECTIVES } from '@angular/router'; | ||
3 | |||
4 | import { UserService } from './shared'; | ||
5 | |||
6 | @Component({ | ||
7 | template: '<router-outlet></router-outlet>', | ||
8 | directives: [ ROUTER_DIRECTIVES ], | ||
9 | providers: [ UserService ] | ||
10 | }) | ||
11 | |||
12 | export class UsersComponent { | ||
13 | } | ||
diff --git a/client/src/app/admin/users/users.routes.ts b/client/src/app/admin/users/users.routes.ts new file mode 100644 index 000000000..0457c3843 --- /dev/null +++ b/client/src/app/admin/users/users.routes.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | import { RouterConfig } from '@angular/router'; | ||
2 | |||
3 | import { UsersComponent } from './users.component'; | ||
4 | import { UserAddComponent } from './user-add'; | ||
5 | import { UserListComponent } from './user-list'; | ||
6 | |||
7 | export const UsersRoutes: RouterConfig = [ | ||
8 | { | ||
9 | path: 'users', | ||
10 | component: UsersComponent, | ||
11 | children: [ | ||
12 | { | ||
13 | path: '', | ||
14 | redirectTo: 'list', | ||
15 | pathMatch: 'full' | ||
16 | }, | ||
17 | { | ||
18 | path: 'list', | ||
19 | component: UserListComponent | ||
20 | }, | ||
21 | { | ||
22 | path: 'add', | ||
23 | component: UserAddComponent | ||
24 | } | ||
25 | ] | ||
26 | } | ||
27 | ]; | ||
diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html index ea4b31421..58967abca 100644 --- a/client/src/app/app.component.html +++ b/client/src/app/app.component.html | |||
@@ -47,7 +47,12 @@ | |||
47 | </div> | 47 | </div> |
48 | </div> | 48 | </div> |
49 | 49 | ||
50 | <div class="panel-block" *ngIf="isLoggedIn"> | 50 | <div class="panel-block" *ngIf="isUserAdmin()"> |
51 | <div id="panel-users" class="panel-button"> | ||
52 | <span class="hidden-xs glyphicon glyphicon-user"></span> | ||
53 | <a [routerLink]="['/admin/users/list']">List users</a> | ||
54 | </div> | ||
55 | |||
51 | <div id="panel-make-friends" class="panel-button"> | 56 | <div id="panel-make-friends" class="panel-button"> |
52 | <span class="hidden-xs glyphicon glyphicon-cloud"></span> | 57 | <span class="hidden-xs glyphicon glyphicon-cloud"></span> |
53 | <a (click)='makeFriends()'>Make friends</a> | 58 | <a (click)='makeFriends()'>Make friends</a> |
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 5764f24ca..444b6b3b4 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -45,6 +45,10 @@ export class AppComponent { | |||
45 | ); | 45 | ); |
46 | } | 46 | } |
47 | 47 | ||
48 | isUserAdmin() { | ||
49 | return this.authService.isAdmin(); | ||
50 | } | ||
51 | |||
48 | logout() { | 52 | logout() { |
49 | this.authService.logout(); | 53 | this.authService.logout(); |
50 | // Redirect to home page | 54 | // Redirect to home page |
diff --git a/client/src/app/app.routes.ts b/client/src/app/app.routes.ts index 1c414038d..d7194cb4f 100644 --- a/client/src/app/app.routes.ts +++ b/client/src/app/app.routes.ts | |||
@@ -2,6 +2,7 @@ import { RouterConfig } from '@angular/router'; | |||
2 | 2 | ||
3 | import { AccountRoutes } from './account'; | 3 | import { AccountRoutes } from './account'; |
4 | import { LoginRoutes } from './login'; | 4 | import { LoginRoutes } from './login'; |
5 | import { AdminRoutes } from './admin'; | ||
5 | import { VideosRoutes } from './videos'; | 6 | import { VideosRoutes } from './videos'; |
6 | 7 | ||
7 | export const routes: RouterConfig = [ | 8 | export const routes: RouterConfig = [ |
@@ -10,7 +11,7 @@ export const routes: RouterConfig = [ | |||
10 | redirectTo: '/videos/list', | 11 | redirectTo: '/videos/list', |
11 | pathMatch: 'full' | 12 | pathMatch: 'full' |
12 | }, | 13 | }, |
13 | 14 | ...AdminRoutes, | |
14 | ...AccountRoutes, | 15 | ...AccountRoutes, |
15 | ...LoginRoutes, | 16 | ...LoginRoutes, |
16 | ...VideosRoutes | 17 | ...VideosRoutes |
diff --git a/client/src/app/shared/auth/user.model.ts b/client/src/app/shared/auth/auth-user.model.ts index e486873ab..bdd5ea5a9 100644 --- a/client/src/app/shared/auth/user.model.ts +++ b/client/src/app/shared/auth/auth-user.model.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | export class User { | 1 | import { User } from '../users'; |
2 | |||
3 | export class AuthUser extends User { | ||
2 | private static KEYS = { | 4 | private static KEYS = { |
3 | ID: 'id', | 5 | ID: 'id', |
4 | ROLE: 'role', | 6 | ROLE: 'role', |
@@ -13,10 +15,12 @@ export class User { | |||
13 | static load() { | 15 | static load() { |
14 | const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME); | 16 | const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME); |
15 | if (usernameLocalStorage) { | 17 | if (usernameLocalStorage) { |
16 | return new User( | 18 | return new AuthUser( |
17 | localStorage.getItem(this.KEYS.ID), | 19 | { |
18 | localStorage.getItem(this.KEYS.USERNAME), | 20 | id: localStorage.getItem(this.KEYS.ID), |
19 | localStorage.getItem(this.KEYS.ROLE), | 21 | username: localStorage.getItem(this.KEYS.USERNAME), |
22 | role: localStorage.getItem(this.KEYS.ROLE) | ||
23 | }, | ||
20 | Tokens.load() | 24 | Tokens.load() |
21 | ); | 25 | ); |
22 | } | 26 | } |
@@ -31,11 +35,9 @@ export class User { | |||
31 | Tokens.flush(); | 35 | Tokens.flush(); |
32 | } | 36 | } |
33 | 37 | ||
34 | constructor(id: string, username: string, role: string, hash_tokens: any) { | 38 | constructor(userHash: { id: string, username: string, role: string }, hashTokens: any) { |
35 | this.id = id; | 39 | super(userHash); |
36 | this.username = username; | 40 | this.tokens = new Tokens(hashTokens); |
37 | this.role = role; | ||
38 | this.tokens = new Tokens(hash_tokens); | ||
39 | } | 41 | } |
40 | 42 | ||
41 | getAccessToken() { | 43 | getAccessToken() { |
@@ -56,9 +58,9 @@ export class User { | |||
56 | } | 58 | } |
57 | 59 | ||
58 | save() { | 60 | save() { |
59 | localStorage.setItem(User.KEYS.ID, this.id); | 61 | localStorage.setItem(AuthUser.KEYS.ID, this.id); |
60 | localStorage.setItem(User.KEYS.USERNAME, this.username); | 62 | localStorage.setItem(AuthUser.KEYS.USERNAME, this.username); |
61 | localStorage.setItem(User.KEYS.ROLE, this.role); | 63 | localStorage.setItem(AuthUser.KEYS.ROLE, this.role); |
62 | this.tokens.save(); | 64 | this.tokens.save(); |
63 | } | 65 | } |
64 | } | 66 | } |
diff --git a/client/src/app/shared/auth/auth.service.ts b/client/src/app/shared/auth/auth.service.ts index 24d1a4fa2..8eea0c4bf 100644 --- a/client/src/app/shared/auth/auth.service.ts +++ b/client/src/app/shared/auth/auth.service.ts | |||
@@ -4,7 +4,7 @@ import { Observable } from 'rxjs/Observable'; | |||
4 | import { Subject } from 'rxjs/Subject'; | 4 | import { Subject } from 'rxjs/Subject'; |
5 | 5 | ||
6 | import { AuthStatus } from './auth-status.model'; | 6 | import { AuthStatus } from './auth-status.model'; |
7 | import { User } from './user.model'; | 7 | import { AuthUser } from './auth-user.model'; |
8 | 8 | ||
9 | @Injectable() | 9 | @Injectable() |
10 | export class AuthService { | 10 | export class AuthService { |
@@ -17,7 +17,7 @@ export class AuthService { | |||
17 | private clientId: string; | 17 | private clientId: string; |
18 | private clientSecret: string; | 18 | private clientSecret: string; |
19 | private loginChanged: Subject<AuthStatus>; | 19 | private loginChanged: Subject<AuthStatus>; |
20 | private user: User = null; | 20 | private user: AuthUser = null; |
21 | 21 | ||
22 | constructor(private http: Http) { | 22 | constructor(private http: Http) { |
23 | this.loginChanged = new Subject<AuthStatus>(); | 23 | this.loginChanged = new Subject<AuthStatus>(); |
@@ -40,7 +40,7 @@ export class AuthService { | |||
40 | ); | 40 | ); |
41 | 41 | ||
42 | // Return null if there is nothing to load | 42 | // Return null if there is nothing to load |
43 | this.user = User.load(); | 43 | this.user = AuthUser.load(); |
44 | } | 44 | } |
45 | 45 | ||
46 | getRefreshToken() { | 46 | getRefreshToken() { |
@@ -65,10 +65,16 @@ export class AuthService { | |||
65 | return this.user.getTokenType(); | 65 | return this.user.getTokenType(); |
66 | } | 66 | } |
67 | 67 | ||
68 | getUser(): User { | 68 | getUser(): AuthUser { |
69 | return this.user; | 69 | return this.user; |
70 | } | 70 | } |
71 | 71 | ||
72 | isAdmin() { | ||
73 | if (this.user === null) return false; | ||
74 | |||
75 | return this.user.isAdmin(); | ||
76 | } | ||
77 | |||
72 | isLoggedIn() { | 78 | isLoggedIn() { |
73 | if (this.getAccessToken()) { | 79 | if (this.getAccessToken()) { |
74 | return true; | 80 | return true; |
@@ -108,7 +114,7 @@ export class AuthService { | |||
108 | logout() { | 114 | logout() { |
109 | // TODO: make an HTTP request to revoke the tokens | 115 | // TODO: make an HTTP request to revoke the tokens |
110 | this.user = null; | 116 | this.user = null; |
111 | User.flush(); | 117 | AuthUser.flush(); |
112 | 118 | ||
113 | this.setStatus(AuthStatus.LoggedOut); | 119 | this.setStatus(AuthStatus.LoggedOut); |
114 | } | 120 | } |
@@ -163,13 +169,13 @@ export class AuthService { | |||
163 | const id = obj.id; | 169 | const id = obj.id; |
164 | const username = obj.username; | 170 | const username = obj.username; |
165 | const role = obj.role; | 171 | const role = obj.role; |
166 | const hash_tokens = { | 172 | const hashTokens = { |
167 | access_token: obj.access_token, | 173 | access_token: obj.access_token, |
168 | token_type: obj.token_type, | 174 | token_type: obj.token_type, |
169 | refresh_token: obj.refresh_token | 175 | refresh_token: obj.refresh_token |
170 | }; | 176 | }; |
171 | 177 | ||
172 | this.user = new User(id, username, role, hash_tokens); | 178 | this.user = new AuthUser({ id, username, role }, hashTokens); |
173 | this.user.save(); | 179 | this.user.save(); |
174 | 180 | ||
175 | this.setStatus(AuthStatus.LoggedIn); | 181 | this.setStatus(AuthStatus.LoggedIn); |
diff --git a/client/src/app/shared/auth/index.ts b/client/src/app/shared/auth/index.ts index aafaacbf1..ebd9e14cd 100644 --- a/client/src/app/shared/auth/index.ts +++ b/client/src/app/shared/auth/index.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | export * from './auth-http.service'; | 1 | export * from './auth-http.service'; |
2 | export * from './auth-status.model'; | 2 | export * from './auth-status.model'; |
3 | export * from './auth.service'; | 3 | export * from './auth.service'; |
4 | export * from './user.model'; | 4 | export * from './auth-user.model'; |
diff --git a/client/src/app/shared/index.ts b/client/src/app/shared/index.ts index dfea4c67c..c05e8d253 100644 --- a/client/src/app/shared/index.ts +++ b/client/src/app/shared/index.ts | |||
@@ -1,2 +1,3 @@ | |||
1 | export * from './auth'; | 1 | export * from './auth'; |
2 | export * from './search'; | 2 | export * from './search'; |
3 | export * from './users'; | ||
diff --git a/client/src/app/shared/users/index.ts b/client/src/app/shared/users/index.ts new file mode 100644 index 000000000..5a670ce8f --- /dev/null +++ b/client/src/app/shared/users/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './user.model'; | |||
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts new file mode 100644 index 000000000..0f34d4480 --- /dev/null +++ b/client/src/app/shared/users/user.model.ts | |||
@@ -0,0 +1,15 @@ | |||
1 | export class User { | ||
2 | id: string; | ||
3 | username: string; | ||
4 | role: string; | ||
5 | |||
6 | constructor(hash: { id: string, username: string, role: string }) { | ||
7 | this.id = hash.id; | ||
8 | this.username = hash.username; | ||
9 | this.role = hash.role; | ||
10 | } | ||
11 | |||
12 | isAdmin() { | ||
13 | return this.role === 'admin'; | ||
14 | } | ||
15 | } | ||
diff --git a/client/src/app/videos/video-list/video-list.component.ts b/client/src/app/videos/video-list/video-list.component.ts index 5691d684e..062340ec5 100644 --- a/client/src/app/videos/video-list/video-list.component.ts +++ b/client/src/app/videos/video-list/video-list.component.ts | |||
@@ -12,7 +12,7 @@ import { | |||
12 | Video, | 12 | Video, |
13 | VideoService | 13 | VideoService |
14 | } from '../shared'; | 14 | } from '../shared'; |
15 | import { AuthService, Search, SearchField, User } from '../../shared'; | 15 | import { AuthService, AuthUser, Search, SearchField } from '../../shared'; |
16 | import { VideoMiniatureComponent } from './video-miniature.component'; | 16 | import { VideoMiniatureComponent } from './video-miniature.component'; |
17 | import { VideoSortComponent } from './video-sort.component'; | 17 | import { VideoSortComponent } from './video-sort.component'; |
18 | import { SearchService } from '../../shared'; | 18 | import { SearchService } from '../../shared'; |
@@ -33,7 +33,7 @@ export class VideoListComponent implements OnInit, OnDestroy { | |||
33 | totalItems: null | 33 | totalItems: null |
34 | }; | 34 | }; |
35 | sort: SortField; | 35 | sort: SortField; |
36 | user: User = null; | 36 | user: AuthUser = null; |
37 | videos: Video[] = []; | 37 | videos: Video[] = []; |
38 | 38 | ||
39 | private search: Search; | 39 | private search: Search; |
@@ -51,7 +51,7 @@ export class VideoListComponent implements OnInit, OnDestroy { | |||
51 | 51 | ||
52 | ngOnInit() { | 52 | ngOnInit() { |
53 | if (this.authService.isLoggedIn()) { | 53 | if (this.authService.isLoggedIn()) { |
54 | this.user = User.load(); | 54 | this.user = AuthUser.load(); |
55 | } | 55 | } |
56 | 56 | ||
57 | // Subscribe to route changes | 57 | // Subscribe to route changes |
diff --git a/client/src/index.html b/client/src/index.html index 5cf491221..f39d8d2cf 100644 --- a/client/src/index.html +++ b/client/src/index.html | |||
@@ -1,3 +1,4 @@ | |||
1 | <!DOCTYPE html> | ||
1 | <html> | 2 | <html> |
2 | <head> | 3 | <head> |
3 | <base href="/"> | 4 | <base href="/"> |
diff --git a/client/tsconfig.json b/client/tsconfig.json index b10231b7b..5c5f008c3 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json | |||
@@ -31,6 +31,18 @@ | |||
31 | "src/app/account/account.routes.ts", | 31 | "src/app/account/account.routes.ts", |
32 | "src/app/account/account.service.ts", | 32 | "src/app/account/account.service.ts", |
33 | "src/app/account/index.ts", | 33 | "src/app/account/index.ts", |
34 | "src/app/admin/admin.component.ts", | ||
35 | "src/app/admin/admin.routes.ts", | ||
36 | "src/app/admin/index.ts", | ||
37 | "src/app/admin/users/index.ts", | ||
38 | "src/app/admin/users/shared/index.ts", | ||
39 | "src/app/admin/users/shared/user.service.ts", | ||
40 | "src/app/admin/users/user-add/index.ts", | ||
41 | "src/app/admin/users/user-add/user-add.component.ts", | ||
42 | "src/app/admin/users/user-list/index.ts", | ||
43 | "src/app/admin/users/user-list/user-list.component.ts", | ||
44 | "src/app/admin/users/users.component.ts", | ||
45 | "src/app/admin/users/users.routes.ts", | ||
34 | "src/app/app.component.ts", | 46 | "src/app/app.component.ts", |
35 | "src/app/app.routes.ts", | 47 | "src/app/app.routes.ts", |
36 | "src/app/friends/friend.service.ts", | 48 | "src/app/friends/friend.service.ts", |
@@ -40,15 +52,17 @@ | |||
40 | "src/app/login/login.routes.ts", | 52 | "src/app/login/login.routes.ts", |
41 | "src/app/shared/auth/auth-http.service.ts", | 53 | "src/app/shared/auth/auth-http.service.ts", |
42 | "src/app/shared/auth/auth-status.model.ts", | 54 | "src/app/shared/auth/auth-status.model.ts", |
55 | "src/app/shared/auth/auth-user.model.ts", | ||
43 | "src/app/shared/auth/auth.service.ts", | 56 | "src/app/shared/auth/auth.service.ts", |
44 | "src/app/shared/auth/index.ts", | 57 | "src/app/shared/auth/index.ts", |
45 | "src/app/shared/auth/user.model.ts", | ||
46 | "src/app/shared/index.ts", | 58 | "src/app/shared/index.ts", |
47 | "src/app/shared/search/index.ts", | 59 | "src/app/shared/search/index.ts", |
48 | "src/app/shared/search/search-field.type.ts", | 60 | "src/app/shared/search/search-field.type.ts", |
49 | "src/app/shared/search/search.component.ts", | 61 | "src/app/shared/search/search.component.ts", |
50 | "src/app/shared/search/search.model.ts", | 62 | "src/app/shared/search/search.model.ts", |
51 | "src/app/shared/search/search.service.ts", | 63 | "src/app/shared/search/search.service.ts", |
64 | "src/app/shared/users/index.ts", | ||
65 | "src/app/shared/users/user.model.ts", | ||
52 | "src/app/videos/index.ts", | 66 | "src/app/videos/index.ts", |
53 | "src/app/videos/shared/index.ts", | 67 | "src/app/videos/shared/index.ts", |
54 | "src/app/videos/shared/loader/index.ts", | 68 | "src/app/videos/shared/loader/index.ts", |