diff options
-rw-r--r-- | client/src/app/app.component.ts | 2 | ||||
-rw-r--r-- | client/src/app/core/auth/auth-user.model.ts | 10 | ||||
-rw-r--r-- | client/src/app/core/auth/auth.service.ts | 48 | ||||
-rw-r--r-- | client/src/app/shared/forms/form-validators/video.ts | 7 | ||||
-rw-r--r-- | client/src/app/shared/users/user.service.ts | 7 | ||||
-rw-r--r-- | client/src/app/videos/+video-edit/video-add.component.html | 12 | ||||
-rw-r--r-- | client/src/app/videos/+video-edit/video-add.component.ts | 13 | ||||
-rw-r--r-- | client/src/app/videos/video-list/video-list.component.ts | 10 | ||||
-rw-r--r-- | server/tests/api/friends-advanced.ts | 4 |
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) |
2 | import { UserRole } from '../../../../../shared/models/users/user-role.type' | 2 | import { UserRole } from '../../../../../shared/models/users/user-role.type' |
3 | import { User } from '../../shared/users/user.model' | 3 | import { User, UserConstructorHash } from '../../shared/users/user.model' |
4 | 4 | ||
5 | export type TokenOptions = { | 5 | export 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 | ||
12 | import { AuthStatus } from './auth-status.model' | 12 | import { AuthStatus } from './auth-status.model' |
13 | import { AuthUser } from './auth-user.model' | 13 | import { AuthUser } from './auth-user.model' |
14 | import { OAuthClientLocal, UserRole, UserRefreshToken } from '../../../../../shared' | 14 | import { |
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) |
16 | import { RestExtractor } from '../../shared/rest' | 22 | import { RestExtractor } from '../../shared/rest' |
17 | import { UserLogin } from '../../../../../shared/models/users/user-login.model' | 23 | import { UserLogin } from '../../../../../shared/models/users/user-login.model' |
18 | import { User } from '../../shared/users/user.model' | 24 | import { User, UserConstructorHash } from '../../shared/users/user.model' |
19 | 25 | ||
20 | interface UserLoginWithUsername extends UserLogin { | 26 | interface 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 | ||
31 | export const VIDEO_CHANNEL = { | ||
32 | VALIDATORS: [ Validators.required ], | ||
33 | MESSAGES: { | ||
34 | 'required': 'Video channel is required.' | ||
35 | } | ||
36 | } | ||
37 | |||
31 | export const VIDEO_DESCRIPTION = { | 38 | export 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' |
17 | import { ServerService } from '../../core' | 18 | import { AuthService, ServerService } from '../../core' |
18 | import { VideoService } from '../shared' | 19 | import { VideoService } from '../shared' |
19 | import { VideoCreate } from '../../../../../shared' | 20 | import { VideoCreate } from '../../../../../shared' |
20 | import { HttpEventType, HttpResponse } from '@angular/common/http' | 21 | import { 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 @@ | |||
1 | import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core' | 1 | import { Component, OnDestroy, OnInit } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { Subscription } from 'rxjs/Subscription' | 3 | import { Subscription } from 'rxjs/Subscription' |
4 | import { BehaviorSubject } from 'rxjs/BehaviorSubject' | 4 | import { BehaviorSubject } from 'rxjs/BehaviorSubject' |
@@ -11,7 +11,6 @@ import { | |||
11 | VideoService, | 11 | VideoService, |
12 | VideoPagination | 12 | VideoPagination |
13 | } from '../shared' | 13 | } from '../shared' |
14 | import { AuthService, AuthUser } from '../../core' | ||
15 | import { Search, SearchField, SearchService } from '../../shared' | 14 | import { 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 |