aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/core
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/core')
-rw-r--r--client/src/app/core/auth/auth.service.ts61
-rw-r--r--client/src/app/core/confirm/confirm.component.html6
-rw-r--r--client/src/app/core/confirm/confirm.component.ts3
-rw-r--r--client/src/app/core/core.module.ts8
-rw-r--r--client/src/app/core/index.ts1
-rw-r--r--client/src/app/core/menu/index.ts2
-rw-r--r--client/src/app/core/menu/menu-admin.component.html35
-rw-r--r--client/src/app/core/menu/menu-admin.component.ts33
-rw-r--r--client/src/app/core/menu/menu.component.html55
-rw-r--r--client/src/app/core/menu/menu.component.scss51
-rw-r--r--client/src/app/core/menu/menu.component.ts92
-rw-r--r--client/src/app/core/server/server.service.ts38
12 files changed, 56 insertions, 329 deletions
diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts
index 9e6c6b888..e887dde1f 100644
--- a/client/src/app/core/auth/auth.service.ts
+++ b/client/src/app/core/auth/auth.service.ts
@@ -1,30 +1,25 @@
1import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'
1import { Injectable } from '@angular/core' 2import { Injectable } from '@angular/core'
2import { Router } from '@angular/router' 3import { Router } from '@angular/router'
3import { Observable } from 'rxjs/Observable' 4
4import { Subject } from 'rxjs/Subject' 5import { NotificationsService } from 'angular2-notifications'
5import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http' 6import 'rxjs/add/observable/throw'
6import { ReplaySubject } from 'rxjs/ReplaySubject'
7import 'rxjs/add/operator/do' 7import 'rxjs/add/operator/do'
8import 'rxjs/add/operator/map' 8import 'rxjs/add/operator/map'
9import 'rxjs/add/operator/mergeMap' 9import 'rxjs/add/operator/mergeMap'
10import 'rxjs/add/observable/throw' 10import { Observable } from 'rxjs/Observable'
11 11import { ReplaySubject } from 'rxjs/ReplaySubject'
12import { NotificationsService } from 'angular2-notifications' 12import { Subject } from 'rxjs/Subject'
13 13import { OAuthClientLocal, User as UserServerModel, UserRefreshToken, UserRole, VideoChannel } from '../../../../../shared'
14import { AuthStatus } from './auth-status.model' 14import { Account } from '../../../../../shared/models/accounts'
15import { AuthUser } from './auth-user.model' 15import { UserLogin } from '../../../../../shared/models/users/user-login.model'
16import {
17 OAuthClientLocal,
18 UserRole,
19 UserRefreshToken,
20 VideoChannel,
21 User as UserServerModel
22} from '../../../../../shared'
23// Do not use the barrel (dependency loop) 16// Do not use the barrel (dependency loop)
24import { RestExtractor } from '../../shared/rest' 17import { RestExtractor } from '../../shared/rest'
25import { UserLogin } from '../../../../../shared/models/users/user-login.model'
26import { UserConstructorHash } from '../../shared/users/user.model' 18import { UserConstructorHash } from '../../shared/users/user.model'
27 19
20import { AuthStatus } from './auth-status.model'
21import { AuthUser } from './auth-user.model'
22
28interface UserLoginWithUsername extends UserLogin { 23interface UserLoginWithUsername extends UserLogin {
29 access_token: string 24 access_token: string
30 refresh_token: string 25 refresh_token: string
@@ -42,10 +37,7 @@ interface UserLoginWithUserInformation extends UserLogin {
42 displayNSFW: boolean 37 displayNSFW: boolean
43 email: string 38 email: string
44 videoQuota: number 39 videoQuota: number
45 account: { 40 account: Account
46 id: number
47 uuid: string
48 }
49 videoChannels: VideoChannel[] 41 videoChannels: VideoChannel[]
50} 42}
51 43
@@ -177,19 +169,15 @@ export class AuthService {
177 169
178 return this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers }) 170 return this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers })
179 .map(res => this.handleRefreshToken(res)) 171 .map(res => this.handleRefreshToken(res))
180 .catch(res => { 172 .catch(err => {
181 // The refresh token is invalid? 173 console.error(err)
182 if (res.status === 400 && res.error.error === 'invalid_grant') { 174 console.log('Cannot refresh token -> logout...')
183 console.error('Cannot refresh token -> logout...') 175 this.logout()
184 this.logout() 176 this.router.navigate(['/login'])
185 this.router.navigate(['/login']) 177
186 178 return Observable.throw({
187 return Observable.throw({ 179 error: 'You need to reconnect.'
188 error: 'You need to reconnect.' 180 })
189 })
190 }
191
192 return this.restExtractor.handleError(res)
193 }) 181 })
194 } 182 }
195 183
@@ -202,7 +190,6 @@ export class AuthService {
202 } 190 }
203 191
204 this.mergeUserInformation(obj) 192 this.mergeUserInformation(obj)
205 .do(() => this.userInformationLoaded.next(true))
206 .subscribe( 193 .subscribe(
207 res => { 194 res => {
208 this.user.displayNSFW = res.displayNSFW 195 this.user.displayNSFW = res.displayNSFW
@@ -211,6 +198,8 @@ export class AuthService {
211 this.user.account = res.account 198 this.user.account = res.account
212 199
213 this.user.save() 200 this.user.save()
201
202 this.userInformationLoaded.next(true)
214 } 203 }
215 ) 204 )
216 } 205 }
diff --git a/client/src/app/core/confirm/confirm.component.html b/client/src/app/core/confirm/confirm.component.html
index 2726af6cc..31b735f97 100644
--- a/client/src/app/core/confirm/confirm.component.html
+++ b/client/src/app/core/confirm/confirm.component.html
@@ -6,14 +6,14 @@
6 <button type="button" class="close" aria-label="Close" (click)="cancel()"> 6 <button type="button" class="close" aria-label="Close" (click)="cancel()">
7 <span aria-hidden="true">&times;</span> 7 <span aria-hidden="true">&times;</span>
8 </button> 8 </button>
9 <h4 class="modal-title">{{ title }}</h4> 9 <h4 class="title-page title-page-single">{{ title }}</h4>
10 </div> 10 </div>
11 11
12 <div class="modal-body" [innerHtml]="message"></div> 12 <div class="modal-body" [innerHtml]="message"></div>
13 13
14 <div class="modal-footer"> 14 <div class="modal-footer">
15 <button type="button" class="btn btn-default" data-dismiss="modal" (click)="cancel()">Cancel</button> 15 <button type="button" class="grey-button" data-dismiss="modal" (click)="cancel()">Cancel</button>
16 <button type="button" class="btn btn-primary" (click)="confirm()">Confirm</button> 16 <button type="button" class="orange-button" (click)="confirm()">Confirm</button>
17 </div> 17 </div>
18 </div> 18 </div>
19 </div> 19 </div>
diff --git a/client/src/app/core/confirm/confirm.component.ts b/client/src/app/core/confirm/confirm.component.ts
index c8e41e233..0515d969a 100644
--- a/client/src/app/core/confirm/confirm.component.ts
+++ b/client/src/app/core/confirm/confirm.component.ts
@@ -11,7 +11,8 @@ export interface ConfigChangedEvent {
11 11
12@Component({ 12@Component({
13 selector: 'my-confirm', 13 selector: 'my-confirm',
14 templateUrl: './confirm.component.html' 14 templateUrl: './confirm.component.html',
15 styles: [ '.button { padding: 0 13px; }' ]
15}) 16})
16export class ConfirmComponent implements OnInit { 17export class ConfirmComponent implements OnInit {
17 @ViewChild('confirmModal') confirmModal: ModalDirective 18 @ViewChild('confirmModal') confirmModal: ModalDirective
diff --git a/client/src/app/core/core.module.ts b/client/src/app/core/core.module.ts
index c4ce2b637..75262e6cf 100644
--- a/client/src/app/core/core.module.ts
+++ b/client/src/app/core/core.module.ts
@@ -26,17 +26,13 @@ import { throwIfAlreadyLoaded } from './module-import-guard'
26 ], 26 ],
27 27
28 declarations: [ 28 declarations: [
29 ConfirmComponent, 29 ConfirmComponent
30 MenuComponent,
31 MenuAdminComponent
32 ], 30 ],
33 31
34 exports: [ 32 exports: [
35 SimpleNotificationsModule, 33 SimpleNotificationsModule,
36 34
37 ConfirmComponent, 35 ConfirmComponent
38 MenuComponent,
39 MenuAdminComponent
40 ], 36 ],
41 37
42 providers: [ 38 providers: [
diff --git a/client/src/app/core/index.ts b/client/src/app/core/index.ts
index 8358261ae..3c01e05aa 100644
--- a/client/src/app/core/index.ts
+++ b/client/src/app/core/index.ts
@@ -1,6 +1,5 @@
1export * from './auth' 1export * from './auth'
2export * from './server' 2export * from './server'
3export * from './confirm' 3export * from './confirm'
4export * from './menu'
5export * from './routing' 4export * from './routing'
6export * from './core.module' 5export * from './core.module'
diff --git a/client/src/app/core/menu/index.ts b/client/src/app/core/menu/index.ts
deleted file mode 100644
index c905ed20a..000000000
--- a/client/src/app/core/menu/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
1export * from './menu.component'
2export * from './menu-admin.component'
diff --git a/client/src/app/core/menu/menu-admin.component.html b/client/src/app/core/menu/menu-admin.component.html
deleted file mode 100644
index 9857b2e3e..000000000
--- a/client/src/app/core/menu/menu-admin.component.html
+++ /dev/null
@@ -1,35 +0,0 @@
1<menu>
2 <div class="panel-block">
3 <a *ngIf="hasUsersRight()" routerLink="/admin/users" routerLinkActive="active">
4 <span class="hidden-xs glyphicon glyphicon-user"></span>
5 List users
6 </a>
7
8 <a *ngIf="hasServerFollowRight()" routerLink="/admin/follows" routerLinkActive="active">
9 <span class="hidden-xs glyphicon glyphicon-cloud"></span>
10 Manage follows
11 </a>
12
13 <a *ngIf="hasVideoAbusesRight()" routerLink="/admin/video-abuses" routerLinkActive="active">
14 <span class="hidden-xs glyphicon glyphicon-alert"></span>
15 Video abuses
16 </a>
17
18 <a *ngIf="hasVideoBlacklistRight()" routerLink="/admin/video-blacklist" routerLinkActive="active">
19 <span class="hidden-xs glyphicon glyphicon-eye-close"></span>
20 Video blacklist
21 </a>
22
23 <a *ngIf="hasJobsRight()" routerLink="/admin/jobs" routerLinkActive="active">
24 <span class="hidden-xs glyphicon glyphicon-tasks"></span>
25 Jobs
26 </a>
27 </div>
28
29 <div class="panel-block">
30 <a routerLink="/videos/list" routerLinkActive="active">
31 <span class="hidden-xs glyphicon glyphicon-cog"></span>
32 Quit admin.
33 </a>
34 </div>
35</menu>
diff --git a/client/src/app/core/menu/menu-admin.component.ts b/client/src/app/core/menu/menu-admin.component.ts
deleted file mode 100644
index ea8d5f57c..000000000
--- a/client/src/app/core/menu/menu-admin.component.ts
+++ /dev/null
@@ -1,33 +0,0 @@
1import { Component } from '@angular/core'
2
3import { AuthService } from '../auth/auth.service'
4import { UserRight } from '../../../../../shared'
5
6@Component({
7 selector: 'my-menu-admin',
8 templateUrl: './menu-admin.component.html',
9 styleUrls: [ './menu.component.scss' ]
10})
11export class MenuAdminComponent {
12 constructor (private auth: AuthService) {}
13
14 hasUsersRight () {
15 return this.auth.getUser().hasRight(UserRight.MANAGE_USERS)
16 }
17
18 hasServerFollowRight () {
19 return this.auth.getUser().hasRight(UserRight.MANAGE_SERVER_FOLLOW)
20 }
21
22 hasVideoAbusesRight () {
23 return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
24 }
25
26 hasVideoBlacklistRight () {
27 return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
28 }
29
30 hasJobsRight () {
31 return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS)
32 }
33}
diff --git a/client/src/app/core/menu/menu.component.html b/client/src/app/core/menu/menu.component.html
deleted file mode 100644
index fcde23fdd..000000000
--- a/client/src/app/core/menu/menu.component.html
+++ /dev/null
@@ -1,55 +0,0 @@
1<menu>
2 <div class="panel-block">
3 <div class="block-title">Account</div>
4
5 <div id="panel-user-login" class="panel-button">
6 <a *ngIf="!isLoggedIn" routerLink="/login" routerLinkActive="active">
7 <span class="hidden-xs glyphicon glyphicon-log-in"></span>
8 Login
9 </a>
10
11 <a *ngIf="isLoggedIn" (click)="logout()">
12 <span class="hidden-xs glyphicon glyphicon-log-out"></span>
13 Logout
14 </a>
15 </div>
16
17 <a *ngIf="!isLoggedIn && isRegistrationAllowed()" routerLink="/signup" routerLinkActive="active">
18 <span class="hidden-xs glyphicon glyphicon-user"></span>
19 Signup
20 </a>
21
22 <a *ngIf="isLoggedIn" routerLink="/account" routerLinkActive="active">
23 <span class="hidden-xs glyphicon glyphicon-user"></span>
24 My account
25 </a>
26
27 <a *ngIf="isLoggedIn" routerLink="/videos/mine" routerLinkActive="active">
28 <span class="hidden-xs glyphicon glyphicon-folder-open"></span>
29 My videos
30 </a>
31 </div>
32
33 <div class="panel-block">
34 <div class="block-title">Videos</div>
35
36 <a routerLink="/videos/list" routerLinkActive="active">
37 <span class="hidden-xs glyphicon glyphicon-list"></span>
38 See videos
39 </a>
40
41 <a *ngIf="isLoggedIn" routerLink="/videos/upload" routerLinkActive="active">
42 <span class="hidden-xs glyphicon glyphicon-cloud-upload"></span>
43 Upload a video
44 </a>
45 </div>
46
47 <div *ngIf="userHasAdminAccess" class="panel-block">
48 <div class="block-title">Other</div>
49
50 <a [routerLink]="getFirstAdminRouteAvailable()" routerLinkActive="active">
51 <span class="hidden-xs glyphicon glyphicon-cog"></span>
52 Administration
53 </a>
54 </div>
55</menu>
diff --git a/client/src/app/core/menu/menu.component.scss b/client/src/app/core/menu/menu.component.scss
deleted file mode 100644
index 45679c310..000000000
--- a/client/src/app/core/menu/menu.component.scss
+++ /dev/null
@@ -1,51 +0,0 @@
1menu {
2 background-color: $black-background;
3 padding: 15px;
4 margin: 0;
5 height: 100%;
6 white-space: nowrap;
7 text-overflow: ellipsis;
8 overflow: hidden;
9 z-index: 1000;
10
11 @media screen and (max-width: 550px) {
12 font-size: 90%;
13 }
14
15 @media screen and (min-width: 1200px) {
16 padding: 25px;
17 }
18
19 .panel-block {
20 margin-bottom: 15px;
21 }
22
23 .block-title {
24 text-transform: uppercase;
25 font-weight: bold;
26 color: $menu-color-block;
27 margin-bottom: 10px;
28 }
29
30 a {
31 display: block;
32 margin-left: 5px;
33 height: 30px;
34 color: $menu-color-link;
35 cursor: pointer;
36 transition: color 0.3s;
37
38 &:hover, &:focus {
39 text-decoration: none !important;
40 outline: none !important;
41 }
42
43 .glyphicon {
44 margin-right: 15px;
45 }
46
47 &:hover, &.active {
48 color: #fff;
49 }
50 }
51}
diff --git a/client/src/app/core/menu/menu.component.ts b/client/src/app/core/menu/menu.component.ts
deleted file mode 100644
index d2bd71534..000000000
--- a/client/src/app/core/menu/menu.component.ts
+++ /dev/null
@@ -1,92 +0,0 @@
1import { Component, OnInit } from '@angular/core'
2import { Router } from '@angular/router'
3
4import { AuthService, AuthStatus } from '../auth'
5import { ServerService } from '../server'
6import { UserRight } from '../../../../../shared/models/users/user-right.enum'
7
8@Component({
9 selector: 'my-menu',
10 templateUrl: './menu.component.html',
11 styleUrls: [ './menu.component.scss' ]
12})
13export class MenuComponent implements OnInit {
14 isLoggedIn: boolean
15 userHasAdminAccess = false
16
17 private routesPerRight = {
18 [UserRight.MANAGE_USERS]: '/admin/users',
19 [UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends',
20 [UserRight.MANAGE_VIDEO_ABUSES]: '/admin/video-abuses',
21 [UserRight.MANAGE_VIDEO_BLACKLIST]: '/admin/video-blacklist'
22 }
23
24 constructor (
25 private authService: AuthService,
26 private serverService: ServerService,
27 private router: Router
28 ) {}
29
30 ngOnInit () {
31 this.isLoggedIn = this.authService.isLoggedIn()
32 this.computeIsUserHasAdminAccess()
33
34 this.authService.loginChangedSource.subscribe(
35 status => {
36 if (status === AuthStatus.LoggedIn) {
37 this.isLoggedIn = true
38 this.computeIsUserHasAdminAccess()
39 console.log('Logged in.')
40 } else if (status === AuthStatus.LoggedOut) {
41 this.isLoggedIn = false
42 this.computeIsUserHasAdminAccess()
43 console.log('Logged out.')
44 } else {
45 console.error('Unknown auth status: ' + status)
46 }
47 }
48 )
49 }
50
51 isRegistrationAllowed () {
52 return this.serverService.getConfig().signup.allowed
53 }
54
55 getFirstAdminRightAvailable () {
56 const user = this.authService.getUser()
57 if (!user) return undefined
58
59 const adminRights = [
60 UserRight.MANAGE_USERS,
61 UserRight.MANAGE_SERVER_FOLLOW,
62 UserRight.MANAGE_VIDEO_ABUSES,
63 UserRight.MANAGE_VIDEO_BLACKLIST
64 ]
65
66 for (const adminRight of adminRights) {
67 if (user.hasRight(adminRight)) {
68 return adminRight
69 }
70 }
71
72 return undefined
73 }
74
75 getFirstAdminRouteAvailable () {
76 const right = this.getFirstAdminRightAvailable()
77
78 return this.routesPerRight[right]
79 }
80
81 logout () {
82 this.authService.logout()
83 // Redirect to home page
84 this.router.navigate(['/videos/list'])
85 }
86
87 private computeIsUserHasAdminAccess () {
88 const right = this.getFirstAdminRightAvailable()
89
90 this.userHasAdminAccess = right !== undefined
91 }
92}
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts
index cbc4074c9..16e0595b6 100644
--- a/client/src/app/core/server/server.service.ts
+++ b/client/src/app/core/server/server.service.ts
@@ -1,5 +1,7 @@
1import { Injectable } from '@angular/core'
2import { HttpClient } from '@angular/common/http' 1import { HttpClient } from '@angular/common/http'
2import { Injectable } from '@angular/core'
3import 'rxjs/add/operator/do'
4import { ReplaySubject } from 'rxjs/ReplaySubject'
3 5
4import { ServerConfig } from '../../../../../shared' 6import { ServerConfig } from '../../../../../shared'
5 7
@@ -8,6 +10,11 @@ export class ServerService {
8 private static BASE_CONFIG_URL = API_URL + '/api/v1/config/' 10 private static BASE_CONFIG_URL = API_URL + '/api/v1/config/'
9 private static BASE_VIDEO_URL = API_URL + '/api/v1/videos/' 11 private static BASE_VIDEO_URL = API_URL + '/api/v1/videos/'
10 12
13 videoPrivaciesLoaded = new ReplaySubject<boolean>(1)
14 videoCategoriesLoaded = new ReplaySubject<boolean>(1)
15 videoLicencesLoaded = new ReplaySubject<boolean>(1)
16 videoLanguagesLoaded = new ReplaySubject<boolean>(1)
17
11 private config: ServerConfig = { 18 private config: ServerConfig = {
12 signup: { 19 signup: {
13 allowed: false 20 allowed: false
@@ -29,19 +36,19 @@ export class ServerService {
29 } 36 }
30 37
31 loadVideoCategories () { 38 loadVideoCategories () {
32 return this.loadVideoAttributeEnum('categories', this.videoCategories) 39 return this.loadVideoAttributeEnum('categories', this.videoCategories, this.videoCategoriesLoaded)
33 } 40 }
34 41
35 loadVideoLicences () { 42 loadVideoLicences () {
36 return this.loadVideoAttributeEnum('licences', this.videoLicences) 43 return this.loadVideoAttributeEnum('licences', this.videoLicences, this.videoLicencesLoaded)
37 } 44 }
38 45
39 loadVideoLanguages () { 46 loadVideoLanguages () {
40 return this.loadVideoAttributeEnum('languages', this.videoLanguages) 47 return this.loadVideoAttributeEnum('languages', this.videoLanguages, this.videoLanguagesLoaded)
41 } 48 }
42 49
43 loadVideoPrivacies () { 50 loadVideoPrivacies () {
44 return this.loadVideoAttributeEnum('privacies', this.videoPrivacies) 51 return this.loadVideoAttributeEnum('privacies', this.videoPrivacies, this.videoPrivaciesLoaded)
45 } 52 }
46 53
47 getConfig () { 54 getConfig () {
@@ -66,17 +73,20 @@ export class ServerService {
66 73
67 private loadVideoAttributeEnum ( 74 private loadVideoAttributeEnum (
68 attributeName: 'categories' | 'licences' | 'languages' | 'privacies', 75 attributeName: 'categories' | 'licences' | 'languages' | 'privacies',
69 hashToPopulate: { id: number, label: string }[] 76 hashToPopulate: { id: number, label: string }[],
77 notifier: ReplaySubject<boolean>
70 ) { 78 ) {
71 return this.http.get(ServerService.BASE_VIDEO_URL + attributeName) 79 return this.http.get(ServerService.BASE_VIDEO_URL + attributeName)
72 .subscribe(data => { 80 .subscribe(data => {
73 Object.keys(data) 81 Object.keys(data)
74 .forEach(dataKey => { 82 .forEach(dataKey => {
75 hashToPopulate.push({ 83 hashToPopulate.push({
76 id: parseInt(dataKey, 10), 84 id: parseInt(dataKey, 10),
77 label: data[dataKey] 85 label: data[dataKey]
78 }) 86 })
79 })
80 }) 87 })
88
89 notifier.next(true)
90 })
81 } 91 }
82} 92}