aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/app.component.ts2
-rw-r--r--client/src/app/core/auth/auth-user.model.ts10
-rw-r--r--client/src/app/core/auth/auth.service.ts48
-rw-r--r--client/src/app/shared/forms/form-validators/video.ts7
-rw-r--r--client/src/app/shared/users/user.service.ts7
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.html12
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.ts13
-rw-r--r--client/src/app/videos/video-list/video-list.component.ts10
-rw-r--r--server/tests/api/friends-advanced.ts4
9 files changed, 72 insertions, 41 deletions
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index 7d890e72a..984470d69 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -37,7 +37,7 @@ export class AppComponent implements OnInit {
37 37
38 if (this.authService.isLoggedIn()) { 38 if (this.authService.isLoggedIn()) {
39 // The service will automatically redirect to the login page if the token is not valid anymore 39 // The service will automatically redirect to the login page if the token is not valid anymore
40 this.userService.checkTokenValidity() 40 this.authService.refreshUserInformation()
41 } 41 }
42 42
43 // Load custom data from server 43 // Load custom data from server
diff --git a/client/src/app/core/auth/auth-user.model.ts b/client/src/app/core/auth/auth-user.model.ts
index 4155aea19..81bff99a0 100644
--- a/client/src/app/core/auth/auth-user.model.ts
+++ b/client/src/app/core/auth/auth-user.model.ts
@@ -1,6 +1,6 @@
1// Do not use the barrel (dependency loop) 1// Do not use the barrel (dependency loop)
2import { UserRole } from '../../../../../shared/models/users/user-role.type' 2import { UserRole } from '../../../../../shared/models/users/user-role.type'
3import { User } from '../../shared/users/user.model' 3import { User, UserConstructorHash } from '../../shared/users/user.model'
4 4
5export type TokenOptions = { 5export type TokenOptions = {
6 accessToken: string 6 accessToken: string
@@ -100,13 +100,7 @@ export class AuthUser extends User {
100 Tokens.flush() 100 Tokens.flush()
101 } 101 }
102 102
103 constructor (userHash: { 103 constructor (userHash: UserConstructorHash, hashTokens: TokenOptions) {
104 id: number,
105 username: string,
106 role: UserRole,
107 email: string,
108 displayNSFW: boolean
109 }, hashTokens: TokenOptions) {
110 super(userHash) 104 super(userHash)
111 this.tokens = new Tokens(hashTokens) 105 this.tokens = new Tokens(hashTokens)
112 } 106 }
diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts
index 4a8814c4e..9ac9ba7bb 100644
--- a/client/src/app/core/auth/auth.service.ts
+++ b/client/src/app/core/auth/auth.service.ts
@@ -11,11 +11,17 @@ import { NotificationsService } from 'angular2-notifications'
11 11
12import { AuthStatus } from './auth-status.model' 12import { AuthStatus } from './auth-status.model'
13import { AuthUser } from './auth-user.model' 13import { AuthUser } from './auth-user.model'
14import { OAuthClientLocal, UserRole, UserRefreshToken } from '../../../../../shared' 14import {
15 OAuthClientLocal,
16 UserRole,
17 UserRefreshToken,
18 VideoChannel,
19 User as UserServerModel
20} from '../../../../../shared'
15// Do not use the barrel (dependency loop) 21// Do not use the barrel (dependency loop)
16import { RestExtractor } from '../../shared/rest' 22import { RestExtractor } from '../../shared/rest'
17import { UserLogin } from '../../../../../shared/models/users/user-login.model' 23import { UserLogin } from '../../../../../shared/models/users/user-login.model'
18import { User } from '../../shared/users/user.model' 24import { User, UserConstructorHash } from '../../shared/users/user.model'
19 25
20interface UserLoginWithUsername extends UserLogin { 26interface UserLoginWithUsername extends UserLogin {
21 access_token: string 27 access_token: string
@@ -33,6 +39,12 @@ interface UserLoginWithUserInformation extends UserLogin {
33 role: UserRole 39 role: UserRole
34 displayNSFW: boolean 40 displayNSFW: boolean
35 email: string 41 email: string
42 videoQuota: number
43 author: {
44 id: number
45 uuid: string
46 }
47 videoChannels: VideoChannel[]
36} 48}
37 49
38@Injectable() 50@Injectable()
@@ -197,6 +209,8 @@ export class AuthService {
197 res => { 209 res => {
198 this.user.displayNSFW = res.displayNSFW 210 this.user.displayNSFW = res.displayNSFW
199 this.user.role = res.role 211 this.user.role = res.role
212 this.user.videoChannels = res.videoChannels
213 this.user.author = res.author
200 214
201 this.user.save() 215 this.user.save()
202 } 216 }
@@ -207,13 +221,16 @@ export class AuthService {
207 // User is not loaded yet, set manually auth header 221 // User is not loaded yet, set manually auth header
208 const headers = new HttpHeaders().set('Authorization', `${obj.token_type} ${obj.access_token}`) 222 const headers = new HttpHeaders().set('Authorization', `${obj.token_type} ${obj.access_token}`)
209 223
210 return this.http.get<User>(AuthService.BASE_USER_INFORMATION_URL, { headers }) 224 return this.http.get<UserServerModel>(AuthService.BASE_USER_INFORMATION_URL, { headers })
211 .map(res => { 225 .map(res => {
212 const newProperties = { 226 const newProperties = {
213 id: res.id as number, 227 id: res.id,
214 role: res.role as UserRole, 228 role: res.role,
215 displayNSFW: res.displayNSFW as boolean, 229 displayNSFW: res.displayNSFW,
216 email: res.email as string 230 email: res.email,
231 videoQuota: res.videoQuota,
232 author: res.author,
233 videoChannels: res.videoChannels
217 } 234 }
218 235
219 return Object.assign(obj, newProperties) 236 return Object.assign(obj, newProperties)
@@ -222,18 +239,23 @@ export class AuthService {
222 } 239 }
223 240
224 private handleLogin (obj: UserLoginWithUserInformation) { 241 private handleLogin (obj: UserLoginWithUserInformation) {
225 const id = obj.id 242 const hashUser: UserConstructorHash = {
226 const username = obj.username 243 id: obj.id,
227 const role = obj.role 244 username: obj.username,
228 const email = obj.email 245 role: obj.role,
229 const displayNSFW = obj.displayNSFW 246 email: obj.email,
247 displayNSFW: obj.displayNSFW,
248 videoQuota: obj.videoQuota,
249 videoChannels: obj.videoChannels,
250 author: obj.author
251 }
230 const hashTokens = { 252 const hashTokens = {
231 accessToken: obj.access_token, 253 accessToken: obj.access_token,
232 tokenType: obj.token_type, 254 tokenType: obj.token_type,
233 refreshToken: obj.refresh_token 255 refreshToken: obj.refresh_token
234 } 256 }
235 257
236 this.user = new AuthUser({ id, username, role, displayNSFW, email }, hashTokens) 258 this.user = new AuthUser(hashUser, hashTokens)
237 this.user.save() 259 this.user.save()
238 260
239 this.setStatus(AuthStatus.LoggedIn) 261 this.setStatus(AuthStatus.LoggedIn)
diff --git a/client/src/app/shared/forms/form-validators/video.ts b/client/src/app/shared/forms/form-validators/video.ts
index 32b1f1c2e..213ab15db 100644
--- a/client/src/app/shared/forms/form-validators/video.ts
+++ b/client/src/app/shared/forms/form-validators/video.ts
@@ -28,6 +28,13 @@ export const VIDEO_LANGUAGE = {
28 MESSAGES: {} 28 MESSAGES: {}
29} 29}
30 30
31export const VIDEO_CHANNEL = {
32 VALIDATORS: [ Validators.required ],
33 MESSAGES: {
34 'required': 'Video channel is required.'
35 }
36}
37
31export const VIDEO_DESCRIPTION = { 38export const VIDEO_DESCRIPTION = {
32 VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ], 39 VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ],
33 MESSAGES: { 40 MESSAGES: {
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts
index 5c089d221..6d1017fc9 100644
--- a/client/src/app/shared/users/user.service.ts
+++ b/client/src/app/shared/users/user.service.ts
@@ -15,13 +15,6 @@ export class UserService {
15 private restExtractor: RestExtractor 15 private restExtractor: RestExtractor
16 ) {} 16 ) {}
17 17
18 checkTokenValidity () {
19 const url = UserService.BASE_USERS_URL + 'me'
20
21 // AuthHttp will redirect us to the login page if the token is not valid anymore
22 this.authHttp.get(url).subscribe()
23 }
24
25 changePassword (newPassword: string) { 18 changePassword (newPassword: string) {
26 const url = UserService.BASE_USERS_URL + 'me' 19 const url = UserService.BASE_USERS_URL + 'me'
27 const body: UserUpdateMe = { 20 const body: UserUpdateMe = {
diff --git a/client/src/app/videos/+video-edit/video-add.component.html b/client/src/app/videos/+video-edit/video-add.component.html
index 698152ff9..7946c0879 100644
--- a/client/src/app/videos/+video-edit/video-add.component.html
+++ b/client/src/app/videos/+video-edit/video-add.component.html
@@ -26,6 +26,18 @@
26 </div> 26 </div>
27 27
28 <div class="form-group"> 28 <div class="form-group">
29 <label for="category">Channel</label>
30 <select class="form-control" id="channelId" formControlName="channelId">
31 <option></option>
32 <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
33 </select>
34
35 <div *ngIf="formErrors.channelId" class="alert alert-danger">
36 {{ formErrors.channelId }}
37 </div>
38 </div>
39
40 <div class="form-group">
29 <label for="category">Category</label> 41 <label for="category">Category</label>
30 <select class="form-control" id="category" formControlName="category"> 42 <select class="form-control" id="category" formControlName="category">
31 <option></option> 43 <option></option>
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts
index 8043bb41c..92b03e8c9 100644
--- a/client/src/app/videos/+video-edit/video-add.component.ts
+++ b/client/src/app/videos/+video-edit/video-add.component.ts
@@ -12,9 +12,10 @@ import {
12 VIDEO_LANGUAGE, 12 VIDEO_LANGUAGE,
13 VIDEO_DESCRIPTION, 13 VIDEO_DESCRIPTION,
14 VIDEO_TAGS, 14 VIDEO_TAGS,
15 VIDEO_CHANNEL,
15 VIDEO_FILE 16 VIDEO_FILE
16} from '../../shared' 17} from '../../shared'
17import { ServerService } from '../../core' 18import { AuthService, ServerService } from '../../core'
18import { VideoService } from '../shared' 19import { VideoService } from '../shared'
19import { VideoCreate } from '../../../../../shared' 20import { VideoCreate } from '../../../../../shared'
20import { HttpEventType, HttpResponse } from '@angular/common/http' 21import { HttpEventType, HttpResponse } from '@angular/common/http'
@@ -33,6 +34,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
33 videoCategories = [] 34 videoCategories = []
34 videoLicences = [] 35 videoLicences = []
35 videoLanguages = [] 36 videoLanguages = []
37 userVideoChannels = []
36 38
37 tagValidators = VIDEO_TAGS.VALIDATORS 39 tagValidators = VIDEO_TAGS.VALIDATORS
38 tagValidatorsMessages = VIDEO_TAGS.MESSAGES 40 tagValidatorsMessages = VIDEO_TAGS.MESSAGES
@@ -44,6 +46,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
44 category: '', 46 category: '',
45 licence: '', 47 licence: '',
46 language: '', 48 language: '',
49 channelId: '',
47 description: '', 50 description: '',
48 videofile: '' 51 videofile: ''
49 } 52 }
@@ -52,6 +55,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
52 category: VIDEO_CATEGORY.MESSAGES, 55 category: VIDEO_CATEGORY.MESSAGES,
53 licence: VIDEO_LICENCE.MESSAGES, 56 licence: VIDEO_LICENCE.MESSAGES,
54 language: VIDEO_LANGUAGE.MESSAGES, 57 language: VIDEO_LANGUAGE.MESSAGES,
58 channelId: VIDEO_CHANNEL.MESSAGES,
55 description: VIDEO_DESCRIPTION.MESSAGES, 59 description: VIDEO_DESCRIPTION.MESSAGES,
56 videofile: VIDEO_FILE.MESSAGES 60 videofile: VIDEO_FILE.MESSAGES
57 } 61 }
@@ -60,6 +64,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
60 private formBuilder: FormBuilder, 64 private formBuilder: FormBuilder,
61 private router: Router, 65 private router: Router,
62 private notificationsService: NotificationsService, 66 private notificationsService: NotificationsService,
67 private authService: AuthService,
63 private serverService: ServerService, 68 private serverService: ServerService,
64 private videoService: VideoService 69 private videoService: VideoService
65 ) { 70 ) {
@@ -77,6 +82,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
77 category: [ '', VIDEO_CATEGORY.VALIDATORS ], 82 category: [ '', VIDEO_CATEGORY.VALIDATORS ],
78 licence: [ '', VIDEO_LICENCE.VALIDATORS ], 83 licence: [ '', VIDEO_LICENCE.VALIDATORS ],
79 language: [ '', VIDEO_LANGUAGE.VALIDATORS ], 84 language: [ '', VIDEO_LANGUAGE.VALIDATORS ],
85 channelId: [ this.userVideoChannels[0].id, VIDEO_CHANNEL.VALIDATORS ],
80 description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], 86 description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
81 videofile: [ '', VIDEO_FILE.VALIDATORS ], 87 videofile: [ '', VIDEO_FILE.VALIDATORS ],
82 tags: [ '' ] 88 tags: [ '' ]
@@ -90,6 +96,9 @@ export class VideoAddComponent extends FormReactive implements OnInit {
90 this.videoLicences = this.serverService.getVideoLicences() 96 this.videoLicences = this.serverService.getVideoLicences()
91 this.videoLanguages = this.serverService.getVideoLanguages() 97 this.videoLanguages = this.serverService.getVideoLanguages()
92 98
99 const user = this.authService.getUser()
100 this.userVideoChannels = user.videoChannels.map(v => ({ id: v.id, label: v.name }))
101
93 this.buildForm() 102 this.buildForm()
94 } 103 }
95 104
@@ -122,6 +131,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
122 const category = formValue.category 131 const category = formValue.category
123 const licence = formValue.licence 132 const licence = formValue.licence
124 const language = formValue.language 133 const language = formValue.language
134 const channelId = formValue.channelId
125 const description = formValue.description 135 const description = formValue.description
126 const tags = formValue.tags 136 const tags = formValue.tags
127 const videofile = this.videofileInput.nativeElement.files[0] 137 const videofile = this.videofileInput.nativeElement.files[0]
@@ -131,6 +141,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
131 formData.append('category', '' + category) 141 formData.append('category', '' + category)
132 formData.append('nsfw', '' + nsfw) 142 formData.append('nsfw', '' + nsfw)
133 formData.append('licence', '' + licence) 143 formData.append('licence', '' + licence)
144 formData.append('channelId', '' + channelId)
134 formData.append('videofile', videofile) 145 formData.append('videofile', videofile)
135 146
136 // Language is optional 147 // Language is optional
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 4714ce01e..d2f0ae045 100644
--- a/client/src/app/videos/video-list/video-list.component.ts
+++ b/client/src/app/videos/video-list/video-list.component.ts
@@ -1,4 +1,4 @@
1import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { Subscription } from 'rxjs/Subscription' 3import { Subscription } from 'rxjs/Subscription'
4import { BehaviorSubject } from 'rxjs/BehaviorSubject' 4import { BehaviorSubject } from 'rxjs/BehaviorSubject'
@@ -11,7 +11,6 @@ import {
11 VideoService, 11 VideoService,
12 VideoPagination 12 VideoPagination
13} from '../shared' 13} from '../shared'
14import { AuthService, AuthUser } from '../../core'
15import { Search, SearchField, SearchService } from '../../shared' 14import { Search, SearchField, SearchService } from '../../shared'
16 15
17@Component({ 16@Component({
@@ -27,7 +26,6 @@ export class VideoListComponent implements OnInit, OnDestroy {
27 totalItems: null 26 totalItems: null
28 } 27 }
29 sort: SortField 28 sort: SortField
30 user: AuthUser = null
31 videos: Video[] = [] 29 videos: Video[] = []
32 30
33 private search: Search 31 private search: Search
@@ -36,8 +34,6 @@ export class VideoListComponent implements OnInit, OnDestroy {
36 34
37 constructor ( 35 constructor (
38 private notificationsService: NotificationsService, 36 private notificationsService: NotificationsService,
39 private authService: AuthService,
40 private changeDetector: ChangeDetectorRef,
41 private router: Router, 37 private router: Router,
42 private route: ActivatedRoute, 38 private route: ActivatedRoute,
43 private videoService: VideoService, 39 private videoService: VideoService,
@@ -45,10 +41,6 @@ export class VideoListComponent implements OnInit, OnDestroy {
45 ) {} 41 ) {}
46 42
47 ngOnInit () { 43 ngOnInit () {
48 if (this.authService.isLoggedIn()) {
49 this.user = AuthUser.load()
50 }
51
52 // Subscribe to route changes 44 // Subscribe to route changes
53 this.subActivatedRoute = this.route.params.subscribe(routeParams => { 45 this.subActivatedRoute = this.route.params.subscribe(routeParams => {
54 this.loadRouteParams(routeParams) 46 this.loadRouteParams(routeParams)
diff --git a/server/tests/api/friends-advanced.ts b/server/tests/api/friends-advanced.ts
index fbfdf227e..139019398 100644
--- a/server/tests/api/friends-advanced.ts
+++ b/server/tests/api/friends-advanced.ts
@@ -221,11 +221,11 @@ describe('Test advanced friends', function () {
221 // Pod 4 is friend with : 2 3 221 // Pod 4 is friend with : 2 3
222 // Pod 6 is friend with : 2 3 222 // Pod 6 is friend with : 2 3
223 it('Should make friends between pod 1, 2, 3 and 6 and exchange their videos', async function () { 223 it('Should make friends between pod 1, 2, 3 and 6 and exchange their videos', async function () {
224 this.timeout(20000) 224 this.timeout(30000)
225 225
226 await makeFriendsWrapper(1) 226 await makeFriendsWrapper(1)
227 227
228 await wait(11000) 228 await wait(22000)
229 229
230 const res = await getVideosWrapper(1) 230 const res = await getVideosWrapper(1)
231 const videos = res.body.data 231 const videos = res.body.data