aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/api')
-rw-r--r--server/tests/api/check-params/index.ts2
-rw-r--r--server/tests/api/check-params/my-user.ts495
-rw-r--r--server/tests/api/check-params/users-admin.ts477
-rw-r--r--server/tests/api/check-params/users.ts911
-rw-r--r--server/tests/api/users/user-subscriptions.ts18
5 files changed, 1003 insertions, 900 deletions
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts
index ce2335e42..a14e4d3e0 100644
--- a/server/tests/api/check-params/index.ts
+++ b/server/tests/api/check-params/index.ts
@@ -9,6 +9,7 @@ import './debug'
9import './follows' 9import './follows'
10import './jobs' 10import './jobs'
11import './logs' 11import './logs'
12import './my-user'
12import './live' 13import './live'
13import './plugins' 14import './plugins'
14import './redundancy' 15import './redundancy'
@@ -17,6 +18,7 @@ import './services'
17import './upload-quota' 18import './upload-quota'
18import './user-notifications' 19import './user-notifications'
19import './user-subscriptions' 20import './user-subscriptions'
21import './users-admin'
20import './users' 22import './users'
21import './video-blacklist' 23import './video-blacklist'
22import './video-captions' 24import './video-captions'
diff --git a/server/tests/api/check-params/my-user.ts b/server/tests/api/check-params/my-user.ts
new file mode 100644
index 000000000..d35284d60
--- /dev/null
+++ b/server/tests/api/check-params/my-user.ts
@@ -0,0 +1,495 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import {
5 buildAbsoluteFixturePath,
6 checkBadCountPagination,
7 checkBadSortPagination,
8 checkBadStartPagination,
9 cleanupTests,
10 createSingleServer,
11 makeGetRequest,
12 makePutBodyRequest,
13 makeUploadRequest,
14 MockSmtpServer,
15 PeerTubeServer,
16 setAccessTokensToServers,
17 UsersCommand
18} from '@shared/extra-utils'
19import { HttpStatusCode, UserRole, VideoCreateResult } from '@shared/models'
20
21describe('Test my user API validators', function () {
22 const path = '/api/v1/users/'
23 let userId: number
24 let rootId: number
25 let moderatorId: number
26 let video: VideoCreateResult
27 let server: PeerTubeServer
28 let userToken = ''
29 let moderatorToken = ''
30
31 // ---------------------------------------------------------------
32
33 before(async function () {
34 this.timeout(30000)
35
36 {
37 server = await createSingleServer(1)
38 await setAccessTokensToServers([ server ])
39 }
40
41 {
42 const result = await server.users.generate('user1')
43 userToken = result.token
44 userId = result.userId
45 }
46
47 {
48 const result = await server.users.generate('moderator1', UserRole.MODERATOR)
49 moderatorToken = result.token
50 }
51
52 {
53 const result = await server.users.generate('moderator2', UserRole.MODERATOR)
54 moderatorId = result.userId
55 }
56
57 {
58 video = await server.videos.upload()
59 }
60 })
61
62 describe('When updating my account', function () {
63
64 it('Should fail with an invalid email attribute', async function () {
65 const fields = {
66 email: 'blabla'
67 }
68
69 await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
70 })
71
72 it('Should fail with a too small password', async function () {
73 const fields = {
74 currentPassword: 'password',
75 password: 'bla'
76 }
77
78 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
79 })
80
81 it('Should fail with a too long password', async function () {
82 const fields = {
83 currentPassword: 'password',
84 password: 'super'.repeat(61)
85 }
86
87 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
88 })
89
90 it('Should fail without the current password', async function () {
91 const fields = {
92 currentPassword: 'password',
93 password: 'super'.repeat(61)
94 }
95
96 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
97 })
98
99 it('Should fail with an invalid current password', async function () {
100 const fields = {
101 currentPassword: 'my super password fail',
102 password: 'super'.repeat(61)
103 }
104
105 await makePutBodyRequest({
106 url: server.url,
107 path: path + 'me',
108 token: userToken,
109 fields,
110 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
111 })
112 })
113
114 it('Should fail with an invalid NSFW policy attribute', async function () {
115 const fields = {
116 nsfwPolicy: 'hello'
117 }
118
119 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
120 })
121
122 it('Should fail with an invalid autoPlayVideo attribute', async function () {
123 const fields = {
124 autoPlayVideo: -1
125 }
126
127 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
128 })
129
130 it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
131 const fields = {
132 autoPlayNextVideo: -1
133 }
134
135 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
136 })
137
138 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
139 const fields = {
140 videosHistoryEnabled: -1
141 }
142
143 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
144 })
145
146 it('Should fail with an non authenticated user', async function () {
147 const fields = {
148 currentPassword: 'password',
149 password: 'my super password'
150 }
151
152 await makePutBodyRequest({
153 url: server.url,
154 path: path + 'me',
155 token: 'super token',
156 fields,
157 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
158 })
159 })
160
161 it('Should fail with a too long description', async function () {
162 const fields = {
163 description: 'super'.repeat(201)
164 }
165
166 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
167 })
168
169 it('Should fail with an invalid videoLanguages attribute', async function () {
170 {
171 const fields = {
172 videoLanguages: 'toto'
173 }
174
175 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
176 }
177
178 {
179 const languages = []
180 for (let i = 0; i < 1000; i++) {
181 languages.push('fr')
182 }
183
184 const fields = {
185 videoLanguages: languages
186 }
187
188 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
189 }
190 })
191
192 it('Should fail with an invalid theme', async function () {
193 const fields = { theme: 'invalid' }
194 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
195 })
196
197 it('Should fail with an unknown theme', async function () {
198 const fields = { theme: 'peertube-theme-unknown' }
199 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
200 })
201
202 it('Should fail with invalid no modal attributes', async function () {
203 const keys = [
204 'noInstanceConfigWarningModal',
205 'noAccountSetupWarningModal',
206 'noWelcomeModal'
207 ]
208
209 for (const key of keys) {
210 const fields = {
211 [key]: -1
212 }
213
214 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
215 }
216 })
217
218 it('Should succeed to change password with the correct params', async function () {
219 const fields = {
220 currentPassword: 'password',
221 password: 'my super password',
222 nsfwPolicy: 'blur',
223 autoPlayVideo: false,
224 email: 'super_email@example.com',
225 theme: 'default',
226 noInstanceConfigWarningModal: true,
227 noWelcomeModal: true,
228 noAccountSetupWarningModal: true
229 }
230
231 await makePutBodyRequest({
232 url: server.url,
233 path: path + 'me',
234 token: userToken,
235 fields,
236 expectedStatus: HttpStatusCode.NO_CONTENT_204
237 })
238 })
239
240 it('Should succeed without password change with the correct params', async function () {
241 const fields = {
242 nsfwPolicy: 'blur',
243 autoPlayVideo: false
244 }
245
246 await makePutBodyRequest({
247 url: server.url,
248 path: path + 'me',
249 token: userToken,
250 fields,
251 expectedStatus: HttpStatusCode.NO_CONTENT_204
252 })
253 })
254 })
255
256 describe('When updating my avatar', function () {
257 it('Should fail without an incorrect input file', async function () {
258 const fields = {}
259 const attaches = {
260 avatarfile: buildAbsoluteFixturePath('video_short.mp4')
261 }
262 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
263 })
264
265 it('Should fail with a big file', async function () {
266 const fields = {}
267 const attaches = {
268 avatarfile: buildAbsoluteFixturePath('avatar-big.png')
269 }
270 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
271 })
272
273 it('Should fail with an unauthenticated user', async function () {
274 const fields = {}
275 const attaches = {
276 avatarfile: buildAbsoluteFixturePath('avatar.png')
277 }
278 await makeUploadRequest({
279 url: server.url,
280 path: path + '/me/avatar/pick',
281 fields,
282 attaches,
283 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
284 })
285 })
286
287 it('Should succeed with the correct params', async function () {
288 const fields = {}
289 const attaches = {
290 avatarfile: buildAbsoluteFixturePath('avatar.png')
291 }
292 await makeUploadRequest({
293 url: server.url,
294 path: path + '/me/avatar/pick',
295 token: server.accessToken,
296 fields,
297 attaches,
298 expectedStatus: HttpStatusCode.OK_200
299 })
300 })
301 })
302
303 describe('When managing my scoped tokens', function () {
304
305 it('Should fail to get my scoped tokens with an non authenticated user', async function () {
306 await server.users.getMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
307 })
308
309 it('Should fail to get my scoped tokens with a bad token', async function () {
310 await server.users.getMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
311
312 })
313
314 it('Should succeed to get my scoped tokens', async function () {
315 await server.users.getMyScopedTokens()
316 })
317
318 it('Should fail to renew my scoped tokens with an non authenticated user', async function () {
319 await server.users.renewMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
320 })
321
322 it('Should fail to renew my scoped tokens with a bad token', async function () {
323 await server.users.renewMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
324 })
325
326 it('Should succeed to renew my scoped tokens', async function () {
327 await server.users.renewMyScopedTokens()
328 })
329 })
330
331 describe('When getting my information', function () {
332 it('Should fail with a non authenticated user', async function () {
333 await server.users.getMyInfo({ token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
334 })
335
336 it('Should success with the correct parameters', async function () {
337 await server.users.getMyInfo({ token: userToken })
338 })
339 })
340
341 describe('When getting my video rating', function () {
342 let command: UsersCommand
343
344 before(function () {
345 command = server.users
346 })
347
348 it('Should fail with a non authenticated user', async function () {
349 await command.getMyRating({ token: 'fake_token', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
350 })
351
352 it('Should fail with an incorrect video uuid', async function () {
353 await command.getMyRating({ videoId: 'blabla', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
354 })
355
356 it('Should fail with an unknown video', async function () {
357 await command.getMyRating({ videoId: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
358 })
359
360 it('Should succeed with the correct parameters', async function () {
361 await command.getMyRating({ videoId: video.id })
362 await command.getMyRating({ videoId: video.uuid })
363 await command.getMyRating({ videoId: video.shortUUID })
364 })
365 })
366
367 describe('When retrieving my global ratings', function () {
368 const path = '/api/v1/accounts/user1/ratings'
369
370 it('Should fail with a bad start pagination', async function () {
371 await checkBadStartPagination(server.url, path, userToken)
372 })
373
374 it('Should fail with a bad count pagination', async function () {
375 await checkBadCountPagination(server.url, path, userToken)
376 })
377
378 it('Should fail with an incorrect sort', async function () {
379 await checkBadSortPagination(server.url, path, userToken)
380 })
381
382 it('Should fail with a unauthenticated user', async function () {
383 await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
384 })
385
386 it('Should fail with a another user', async function () {
387 await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
388 })
389
390 it('Should fail with a bad type', async function () {
391 await makeGetRequest({
392 url: server.url,
393 path,
394 token: userToken,
395 query: { rating: 'toto ' },
396 expectedStatus: HttpStatusCode.BAD_REQUEST_400
397 })
398 })
399
400 it('Should succeed with the correct params', async function () {
401 await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
402 })
403 })
404
405 describe('When getting my global followers', function () {
406 const path = '/api/v1/accounts/user1/followers'
407
408 it('Should fail with a bad start pagination', async function () {
409 await checkBadStartPagination(server.url, path, userToken)
410 })
411
412 it('Should fail with a bad count pagination', async function () {
413 await checkBadCountPagination(server.url, path, userToken)
414 })
415
416 it('Should fail with an incorrect sort', async function () {
417 await checkBadSortPagination(server.url, path, userToken)
418 })
419
420 it('Should fail with a unauthenticated user', async function () {
421 await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
422 })
423
424 it('Should fail with a another user', async function () {
425 await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
426 })
427
428 it('Should succeed with the correct params', async function () {
429 await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
430 })
431 })
432
433 describe('When blocking/unblocking/removing user', function () {
434
435 it('Should fail with an incorrect id', async function () {
436 const options = { userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
437
438 await server.users.remove(options)
439 await server.users.banUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
440 await server.users.unbanUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
441 })
442
443 it('Should fail with the root user', async function () {
444 const options = { userId: rootId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
445
446 await server.users.remove(options)
447 await server.users.banUser(options)
448 await server.users.unbanUser(options)
449 })
450
451 it('Should return 404 with a non existing id', async function () {
452 const options = { userId: 4545454, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
453
454 await server.users.remove(options)
455 await server.users.banUser(options)
456 await server.users.unbanUser(options)
457 })
458
459 it('Should fail with a non admin user', async function () {
460 const options = { userId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
461
462 await server.users.remove(options)
463 await server.users.banUser(options)
464 await server.users.unbanUser(options)
465 })
466
467 it('Should fail on a moderator with a moderator', async function () {
468 const options = { userId: moderatorId, token: moderatorToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
469
470 await server.users.remove(options)
471 await server.users.banUser(options)
472 await server.users.unbanUser(options)
473 })
474
475 it('Should succeed on a user with a moderator', async function () {
476 const options = { userId, token: moderatorToken }
477
478 await server.users.banUser(options)
479 await server.users.unbanUser(options)
480 })
481 })
482
483 describe('When deleting our account', function () {
484
485 it('Should fail with with the root account', async function () {
486 await server.users.deleteMe({ expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
487 })
488 })
489
490 after(async function () {
491 MockSmtpServer.Instance.kill()
492
493 await cleanupTests([ server ])
494 })
495})
diff --git a/server/tests/api/check-params/users-admin.ts b/server/tests/api/check-params/users-admin.ts
new file mode 100644
index 000000000..f71414a6b
--- /dev/null
+++ b/server/tests/api/check-params/users-admin.ts
@@ -0,0 +1,477 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { omit } from 'lodash'
5import {
6 checkBadCountPagination,
7 checkBadSortPagination,
8 checkBadStartPagination,
9 cleanupTests,
10 createSingleServer,
11 killallServers,
12 makeGetRequest,
13 makePostBodyRequest,
14 makePutBodyRequest,
15 MockSmtpServer,
16 PeerTubeServer,
17 setAccessTokensToServers
18} from '@shared/extra-utils'
19import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models'
20
21describe('Test users admin API validators', function () {
22 const path = '/api/v1/users/'
23 let userId: number
24 let rootId: number
25 let moderatorId: number
26 let server: PeerTubeServer
27 let userToken = ''
28 let moderatorToken = ''
29 let emailPort: number
30
31 // ---------------------------------------------------------------
32
33 before(async function () {
34 this.timeout(30000)
35
36 const emails: object[] = []
37 emailPort = await MockSmtpServer.Instance.collectEmails(emails)
38
39 {
40 server = await createSingleServer(1)
41
42 await setAccessTokensToServers([ server ])
43 }
44
45 {
46 const result = await server.users.generate('user1')
47 userToken = result.token
48 userId = result.userId
49 }
50
51 {
52 const result = await server.users.generate('moderator1', UserRole.MODERATOR)
53 moderatorToken = result.token
54 }
55
56 {
57 const result = await server.users.generate('moderator2', UserRole.MODERATOR)
58 moderatorId = result.userId
59 }
60 })
61
62 describe('When listing users', function () {
63 it('Should fail with a bad start pagination', async function () {
64 await checkBadStartPagination(server.url, path, server.accessToken)
65 })
66
67 it('Should fail with a bad count pagination', async function () {
68 await checkBadCountPagination(server.url, path, server.accessToken)
69 })
70
71 it('Should fail with an incorrect sort', async function () {
72 await checkBadSortPagination(server.url, path, server.accessToken)
73 })
74
75 it('Should fail with a non authenticated user', async function () {
76 await makeGetRequest({
77 url: server.url,
78 path,
79 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
80 })
81 })
82
83 it('Should fail with a non admin user', async function () {
84 await makeGetRequest({
85 url: server.url,
86 path,
87 token: userToken,
88 expectedStatus: HttpStatusCode.FORBIDDEN_403
89 })
90 })
91 })
92
93 describe('When adding a new user', function () {
94 const baseCorrectParams = {
95 username: 'user2',
96 email: 'test@example.com',
97 password: 'my super password',
98 videoQuota: -1,
99 videoQuotaDaily: -1,
100 role: UserRole.USER,
101 adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
102 }
103
104 it('Should fail with a too small username', async function () {
105 const fields = { ...baseCorrectParams, username: '' }
106
107 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
108 })
109
110 it('Should fail with a too long username', async function () {
111 const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
112
113 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
114 })
115
116 it('Should fail with a not lowercase username', async function () {
117 const fields = { ...baseCorrectParams, username: 'Toto' }
118
119 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
120 })
121
122 it('Should fail with an incorrect username', async function () {
123 const fields = { ...baseCorrectParams, username: 'my username' }
124
125 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
126 })
127
128 it('Should fail with a missing email', async function () {
129 const fields = omit(baseCorrectParams, 'email')
130
131 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
132 })
133
134 it('Should fail with an invalid email', async function () {
135 const fields = { ...baseCorrectParams, email: 'test_example.com' }
136
137 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
138 })
139
140 it('Should fail with a too small password', async function () {
141 const fields = { ...baseCorrectParams, password: 'bla' }
142
143 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
144 })
145
146 it('Should fail with a too long password', async function () {
147 const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
148
149 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
150 })
151
152 it('Should fail with empty password and no smtp configured', async function () {
153 const fields = { ...baseCorrectParams, password: '' }
154
155 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
156 })
157
158 it('Should succeed with no password on a server with smtp enabled', async function () {
159 this.timeout(20000)
160
161 await killallServers([ server ])
162
163 const config = {
164 smtp: {
165 hostname: 'localhost',
166 port: emailPort
167 }
168 }
169 await server.run(config)
170
171 const fields = {
172 ...baseCorrectParams,
173
174 password: '',
175 username: 'create_password',
176 email: 'create_password@example.com'
177 }
178
179 await makePostBodyRequest({
180 url: server.url,
181 path: path,
182 token: server.accessToken,
183 fields,
184 expectedStatus: HttpStatusCode.OK_200
185 })
186 })
187
188 it('Should fail with invalid admin flags', async function () {
189 const fields = { ...baseCorrectParams, adminFlags: 'toto' }
190
191 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
192 })
193
194 it('Should fail with an non authenticated user', async function () {
195 await makePostBodyRequest({
196 url: server.url,
197 path,
198 token: 'super token',
199 fields: baseCorrectParams,
200 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
201 })
202 })
203
204 it('Should fail if we add a user with the same username', async function () {
205 const fields = { ...baseCorrectParams, username: 'user1' }
206
207 await makePostBodyRequest({
208 url: server.url,
209 path,
210 token: server.accessToken,
211 fields,
212 expectedStatus: HttpStatusCode.CONFLICT_409
213 })
214 })
215
216 it('Should fail if we add a user with the same email', async function () {
217 const fields = { ...baseCorrectParams, email: 'user1@example.com' }
218
219 await makePostBodyRequest({
220 url: server.url,
221 path,
222 token: server.accessToken,
223 fields,
224 expectedStatus: HttpStatusCode.CONFLICT_409
225 })
226 })
227
228 it('Should fail without a videoQuota', async function () {
229 const fields = omit(baseCorrectParams, 'videoQuota')
230
231 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
232 })
233
234 it('Should fail without a videoQuotaDaily', async function () {
235 const fields = omit(baseCorrectParams, 'videoQuotaDaily')
236
237 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
238 })
239
240 it('Should fail with an invalid videoQuota', async function () {
241 const fields = { ...baseCorrectParams, videoQuota: -5 }
242
243 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
244 })
245
246 it('Should fail with an invalid videoQuotaDaily', async function () {
247 const fields = { ...baseCorrectParams, videoQuotaDaily: -7 }
248
249 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
250 })
251
252 it('Should fail without a user role', async function () {
253 const fields = omit(baseCorrectParams, 'role')
254
255 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
256 })
257
258 it('Should fail with an invalid user role', async function () {
259 const fields = { ...baseCorrectParams, role: 88989 }
260
261 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
262 })
263
264 it('Should fail with a "peertube" username', async function () {
265 const fields = { ...baseCorrectParams, username: 'peertube' }
266
267 await makePostBodyRequest({
268 url: server.url,
269 path,
270 token: server.accessToken,
271 fields,
272 expectedStatus: HttpStatusCode.CONFLICT_409
273 })
274 })
275
276 it('Should fail to create a moderator or an admin with a moderator', async function () {
277 for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
278 const fields = { ...baseCorrectParams, role }
279
280 await makePostBodyRequest({
281 url: server.url,
282 path,
283 token: moderatorToken,
284 fields,
285 expectedStatus: HttpStatusCode.FORBIDDEN_403
286 })
287 }
288 })
289
290 it('Should succeed to create a user with a moderator', async function () {
291 const fields = { ...baseCorrectParams, username: 'a4656', email: 'a4656@example.com', role: UserRole.USER }
292
293 await makePostBodyRequest({
294 url: server.url,
295 path,
296 token: moderatorToken,
297 fields,
298 expectedStatus: HttpStatusCode.OK_200
299 })
300 })
301
302 it('Should succeed with the correct params', async function () {
303 await makePostBodyRequest({
304 url: server.url,
305 path,
306 token: server.accessToken,
307 fields: baseCorrectParams,
308 expectedStatus: HttpStatusCode.OK_200
309 })
310 })
311
312 it('Should fail with a non admin user', async function () {
313 const user = { username: 'user1' }
314 userToken = await server.login.getAccessToken(user)
315
316 const fields = {
317 username: 'user3',
318 email: 'test@example.com',
319 password: 'my super password',
320 videoQuota: 42000000
321 }
322 await makePostBodyRequest({ url: server.url, path, token: userToken, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
323 })
324 })
325
326 describe('When getting a user', function () {
327
328 it('Should fail with an non authenticated user', async function () {
329 await makeGetRequest({
330 url: server.url,
331 path: path + userId,
332 token: 'super token',
333 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
334 })
335 })
336
337 it('Should fail with a non admin user', async function () {
338 await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
339 })
340
341 it('Should succeed with the correct params', async function () {
342 await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
343 })
344 })
345
346 describe('When updating a user', function () {
347
348 it('Should fail with an invalid email attribute', async function () {
349 const fields = {
350 email: 'blabla'
351 }
352
353 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
354 })
355
356 it('Should fail with an invalid emailVerified attribute', async function () {
357 const fields = {
358 emailVerified: 'yes'
359 }
360
361 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
362 })
363
364 it('Should fail with an invalid videoQuota attribute', async function () {
365 const fields = {
366 videoQuota: -90
367 }
368
369 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
370 })
371
372 it('Should fail with an invalid user role attribute', async function () {
373 const fields = {
374 role: 54878
375 }
376
377 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
378 })
379
380 it('Should fail with a too small password', async function () {
381 const fields = {
382 currentPassword: 'password',
383 password: 'bla'
384 }
385
386 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
387 })
388
389 it('Should fail with a too long password', async function () {
390 const fields = {
391 currentPassword: 'password',
392 password: 'super'.repeat(61)
393 }
394
395 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
396 })
397
398 it('Should fail with an non authenticated user', async function () {
399 const fields = {
400 videoQuota: 42
401 }
402
403 await makePutBodyRequest({
404 url: server.url,
405 path: path + userId,
406 token: 'super token',
407 fields,
408 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
409 })
410 })
411
412 it('Should fail when updating root role', async function () {
413 const fields = {
414 role: UserRole.MODERATOR
415 }
416
417 await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
418 })
419
420 it('Should fail with invalid admin flags', async function () {
421 const fields = { adminFlags: 'toto' }
422
423 await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
424 })
425
426 it('Should fail to update an admin with a moderator', async function () {
427 const fields = {
428 videoQuota: 42
429 }
430
431 await makePutBodyRequest({
432 url: server.url,
433 path: path + moderatorId,
434 token: moderatorToken,
435 fields,
436 expectedStatus: HttpStatusCode.FORBIDDEN_403
437 })
438 })
439
440 it('Should succeed to update a user with a moderator', async function () {
441 const fields = {
442 videoQuota: 42
443 }
444
445 await makePutBodyRequest({
446 url: server.url,
447 path: path + userId,
448 token: moderatorToken,
449 fields,
450 expectedStatus: HttpStatusCode.NO_CONTENT_204
451 })
452 })
453
454 it('Should succeed with the correct params', async function () {
455 const fields = {
456 email: 'email@example.com',
457 emailVerified: true,
458 videoQuota: 42,
459 role: UserRole.USER
460 }
461
462 await makePutBodyRequest({
463 url: server.url,
464 path: path + userId,
465 token: server.accessToken,
466 fields,
467 expectedStatus: HttpStatusCode.NO_CONTENT_204
468 })
469 })
470 })
471
472 after(async function () {
473 MockSmtpServer.Instance.kill()
474
475 await cleanupTests([ server ])
476 })
477})
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 517e2f423..5f9cbc5eb 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -3,925 +3,36 @@
3import 'mocha' 3import 'mocha'
4import { omit } from 'lodash' 4import { omit } from 'lodash'
5import { 5import {
6 buildAbsoluteFixturePath,
7 checkBadCountPagination,
8 checkBadSortPagination,
9 checkBadStartPagination,
10 cleanupTests, 6 cleanupTests,
11 createSingleServer, 7 createSingleServer,
12 killallServers,
13 makeGetRequest,
14 makePostBodyRequest, 8 makePostBodyRequest,
15 makePutBodyRequest,
16 makeUploadRequest,
17 MockSmtpServer, 9 MockSmtpServer,
18 PeerTubeServer, 10 PeerTubeServer,
19 setAccessTokensToServers, 11 setAccessTokensToServers
20 UsersCommand
21} from '@shared/extra-utils' 12} from '@shared/extra-utils'
22import { HttpStatusCode, UserAdminFlag, UserRole, VideoCreateResult } from '@shared/models' 13import { HttpStatusCode, UserRole } from '@shared/models'
23 14
24describe('Test users API validators', function () { 15describe('Test users API validators', function () {
25 const path = '/api/v1/users/' 16 const path = '/api/v1/users/'
26 let userId: number
27 let rootId: number
28 let moderatorId: number
29 let video: VideoCreateResult
30 let server: PeerTubeServer 17 let server: PeerTubeServer
31 let serverWithRegistrationDisabled: PeerTubeServer 18 let serverWithRegistrationDisabled: PeerTubeServer
32 let userToken = ''
33 let moderatorToken = ''
34 let emailPort: number
35 let overrideConfig: Object
36 19
37 // --------------------------------------------------------------- 20 // ---------------------------------------------------------------
38 21
39 before(async function () { 22 before(async function () {
40 this.timeout(30000) 23 this.timeout(30000)
41 24
42 const emails: object[] = [] 25 const res = await Promise.all([
43 emailPort = await MockSmtpServer.Instance.collectEmails(emails) 26 createSingleServer(1, { signup: { limit: 3 } }),
27 createSingleServer(2)
28 ])
44 29
45 overrideConfig = { signup: { limit: 8 } } 30 server = res[0]
31 serverWithRegistrationDisabled = res[1]
46 32
47 { 33 await setAccessTokensToServers([ server ])
48 const res = await Promise.all([
49 createSingleServer(1, overrideConfig),
50 createSingleServer(2)
51 ])
52 34
53 server = res[0] 35 await server.users.generate('moderator2', UserRole.MODERATOR)
54 serverWithRegistrationDisabled = res[1]
55
56 await setAccessTokensToServers([ server ])
57 }
58
59 {
60 const user = { username: 'user1' }
61 await server.users.create({ ...user })
62 userToken = await server.login.getAccessToken(user)
63 }
64
65 {
66 const moderator = { username: 'moderator1' }
67 await server.users.create({ ...moderator, role: UserRole.MODERATOR })
68 moderatorToken = await server.login.getAccessToken(moderator)
69 }
70
71 {
72 const moderator = { username: 'moderator2' }
73 await server.users.create({ ...moderator, role: UserRole.MODERATOR })
74 }
75
76 {
77 video = await server.videos.upload()
78 }
79
80 {
81 const { data } = await server.users.list()
82 userId = data.find(u => u.username === 'user1').id
83 rootId = data.find(u => u.username === 'root').id
84 moderatorId = data.find(u => u.username === 'moderator2').id
85 }
86 })
87
88 describe('When listing users', function () {
89 it('Should fail with a bad start pagination', async function () {
90 await checkBadStartPagination(server.url, path, server.accessToken)
91 })
92
93 it('Should fail with a bad count pagination', async function () {
94 await checkBadCountPagination(server.url, path, server.accessToken)
95 })
96
97 it('Should fail with an incorrect sort', async function () {
98 await checkBadSortPagination(server.url, path, server.accessToken)
99 })
100
101 it('Should fail with a non authenticated user', async function () {
102 await makeGetRequest({
103 url: server.url,
104 path,
105 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
106 })
107 })
108
109 it('Should fail with a non admin user', async function () {
110 await makeGetRequest({
111 url: server.url,
112 path,
113 token: userToken,
114 expectedStatus: HttpStatusCode.FORBIDDEN_403
115 })
116 })
117 })
118
119 describe('When adding a new user', function () {
120 const baseCorrectParams = {
121 username: 'user2',
122 email: 'test@example.com',
123 password: 'my super password',
124 videoQuota: -1,
125 videoQuotaDaily: -1,
126 role: UserRole.USER,
127 adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
128 }
129
130 it('Should fail with a too small username', async function () {
131 const fields = { ...baseCorrectParams, username: '' }
132
133 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
134 })
135
136 it('Should fail with a too long username', async function () {
137 const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
138
139 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
140 })
141
142 it('Should fail with a not lowercase username', async function () {
143 const fields = { ...baseCorrectParams, username: 'Toto' }
144
145 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
146 })
147
148 it('Should fail with an incorrect username', async function () {
149 const fields = { ...baseCorrectParams, username: 'my username' }
150
151 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
152 })
153
154 it('Should fail with a missing email', async function () {
155 const fields = omit(baseCorrectParams, 'email')
156
157 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
158 })
159
160 it('Should fail with an invalid email', async function () {
161 const fields = { ...baseCorrectParams, email: 'test_example.com' }
162
163 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
164 })
165
166 it('Should fail with a too small password', async function () {
167 const fields = { ...baseCorrectParams, password: 'bla' }
168
169 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
170 })
171
172 it('Should fail with a too long password', async function () {
173 const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
174
175 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
176 })
177
178 it('Should fail with empty password and no smtp configured', async function () {
179 const fields = { ...baseCorrectParams, password: '' }
180
181 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
182 })
183
184 it('Should succeed with no password on a server with smtp enabled', async function () {
185 this.timeout(20000)
186
187 await killallServers([ server ])
188
189 const config = {
190 ...overrideConfig,
191
192 smtp: {
193 hostname: 'localhost',
194 port: emailPort
195 }
196 }
197 await server.run(config)
198
199 const fields = {
200 ...baseCorrectParams,
201
202 password: '',
203 username: 'create_password',
204 email: 'create_password@example.com'
205 }
206
207 await makePostBodyRequest({
208 url: server.url,
209 path: path,
210 token: server.accessToken,
211 fields,
212 expectedStatus: HttpStatusCode.OK_200
213 })
214 })
215
216 it('Should fail with invalid admin flags', async function () {
217 const fields = { ...baseCorrectParams, adminFlags: 'toto' }
218
219 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
220 })
221
222 it('Should fail with an non authenticated user', async function () {
223 await makePostBodyRequest({
224 url: server.url,
225 path,
226 token: 'super token',
227 fields: baseCorrectParams,
228 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
229 })
230 })
231
232 it('Should fail if we add a user with the same username', async function () {
233 const fields = { ...baseCorrectParams, username: 'user1' }
234
235 await makePostBodyRequest({
236 url: server.url,
237 path,
238 token: server.accessToken,
239 fields,
240 expectedStatus: HttpStatusCode.CONFLICT_409
241 })
242 })
243
244 it('Should fail if we add a user with the same email', async function () {
245 const fields = { ...baseCorrectParams, email: 'user1@example.com' }
246
247 await makePostBodyRequest({
248 url: server.url,
249 path,
250 token: server.accessToken,
251 fields,
252 expectedStatus: HttpStatusCode.CONFLICT_409
253 })
254 })
255
256 it('Should fail without a videoQuota', async function () {
257 const fields = omit(baseCorrectParams, 'videoQuota')
258
259 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
260 })
261
262 it('Should fail without a videoQuotaDaily', async function () {
263 const fields = omit(baseCorrectParams, 'videoQuotaDaily')
264
265 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
266 })
267
268 it('Should fail with an invalid videoQuota', async function () {
269 const fields = { ...baseCorrectParams, videoQuota: -5 }
270
271 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
272 })
273
274 it('Should fail with an invalid videoQuotaDaily', async function () {
275 const fields = { ...baseCorrectParams, videoQuotaDaily: -7 }
276
277 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
278 })
279
280 it('Should fail without a user role', async function () {
281 const fields = omit(baseCorrectParams, 'role')
282
283 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
284 })
285
286 it('Should fail with an invalid user role', async function () {
287 const fields = { ...baseCorrectParams, role: 88989 }
288
289 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
290 })
291
292 it('Should fail with a "peertube" username', async function () {
293 const fields = { ...baseCorrectParams, username: 'peertube' }
294
295 await makePostBodyRequest({
296 url: server.url,
297 path,
298 token: server.accessToken,
299 fields,
300 expectedStatus: HttpStatusCode.CONFLICT_409
301 })
302 })
303
304 it('Should fail to create a moderator or an admin with a moderator', async function () {
305 for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
306 const fields = { ...baseCorrectParams, role }
307
308 await makePostBodyRequest({
309 url: server.url,
310 path,
311 token: moderatorToken,
312 fields,
313 expectedStatus: HttpStatusCode.FORBIDDEN_403
314 })
315 }
316 })
317
318 it('Should succeed to create a user with a moderator', async function () {
319 const fields = { ...baseCorrectParams, username: 'a4656', email: 'a4656@example.com', role: UserRole.USER }
320
321 await makePostBodyRequest({
322 url: server.url,
323 path,
324 token: moderatorToken,
325 fields,
326 expectedStatus: HttpStatusCode.OK_200
327 })
328 })
329
330 it('Should succeed with the correct params', async function () {
331 await makePostBodyRequest({
332 url: server.url,
333 path,
334 token: server.accessToken,
335 fields: baseCorrectParams,
336 expectedStatus: HttpStatusCode.OK_200
337 })
338 })
339
340 it('Should fail with a non admin user', async function () {
341 const user = { username: 'user1' }
342 userToken = await server.login.getAccessToken(user)
343
344 const fields = {
345 username: 'user3',
346 email: 'test@example.com',
347 password: 'my super password',
348 videoQuota: 42000000
349 }
350 await makePostBodyRequest({ url: server.url, path, token: userToken, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
351 })
352 })
353
354 describe('When updating my account', function () {
355
356 it('Should fail with an invalid email attribute', async function () {
357 const fields = {
358 email: 'blabla'
359 }
360
361 await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
362 })
363
364 it('Should fail with a too small password', async function () {
365 const fields = {
366 currentPassword: 'password',
367 password: 'bla'
368 }
369
370 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
371 })
372
373 it('Should fail with a too long password', async function () {
374 const fields = {
375 currentPassword: 'password',
376 password: 'super'.repeat(61)
377 }
378
379 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
380 })
381
382 it('Should fail without the current password', async function () {
383 const fields = {
384 currentPassword: 'password',
385 password: 'super'.repeat(61)
386 }
387
388 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
389 })
390
391 it('Should fail with an invalid current password', async function () {
392 const fields = {
393 currentPassword: 'my super password fail',
394 password: 'super'.repeat(61)
395 }
396
397 await makePutBodyRequest({
398 url: server.url,
399 path: path + 'me',
400 token: userToken,
401 fields,
402 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
403 })
404 })
405
406 it('Should fail with an invalid NSFW policy attribute', async function () {
407 const fields = {
408 nsfwPolicy: 'hello'
409 }
410
411 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
412 })
413
414 it('Should fail with an invalid autoPlayVideo attribute', async function () {
415 const fields = {
416 autoPlayVideo: -1
417 }
418
419 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
420 })
421
422 it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
423 const fields = {
424 autoPlayNextVideo: -1
425 }
426
427 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
428 })
429
430 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
431 const fields = {
432 videosHistoryEnabled: -1
433 }
434
435 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
436 })
437
438 it('Should fail with an non authenticated user', async function () {
439 const fields = {
440 currentPassword: 'password',
441 password: 'my super password'
442 }
443
444 await makePutBodyRequest({
445 url: server.url,
446 path: path + 'me',
447 token: 'super token',
448 fields,
449 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
450 })
451 })
452
453 it('Should fail with a too long description', async function () {
454 const fields = {
455 description: 'super'.repeat(201)
456 }
457
458 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
459 })
460
461 it('Should fail with an invalid videoLanguages attribute', async function () {
462 {
463 const fields = {
464 videoLanguages: 'toto'
465 }
466
467 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
468 }
469
470 {
471 const languages = []
472 for (let i = 0; i < 1000; i++) {
473 languages.push('fr')
474 }
475
476 const fields = {
477 videoLanguages: languages
478 }
479
480 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
481 }
482 })
483
484 it('Should fail with an invalid theme', async function () {
485 const fields = { theme: 'invalid' }
486 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
487 })
488
489 it('Should fail with an unknown theme', async function () {
490 const fields = { theme: 'peertube-theme-unknown' }
491 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
492 })
493
494 it('Should fail with invalid no modal attributes', async function () {
495 const keys = [
496 'noInstanceConfigWarningModal',
497 'noAccountSetupWarningModal',
498 'noWelcomeModal'
499 ]
500
501 for (const key of keys) {
502 const fields = {
503 [key]: -1
504 }
505
506 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
507 }
508 })
509
510 it('Should succeed to change password with the correct params', async function () {
511 const fields = {
512 currentPassword: 'password',
513 password: 'my super password',
514 nsfwPolicy: 'blur',
515 autoPlayVideo: false,
516 email: 'super_email@example.com',
517 theme: 'default',
518 noInstanceConfigWarningModal: true,
519 noWelcomeModal: true,
520 noAccountSetupWarningModal: true
521 }
522
523 await makePutBodyRequest({
524 url: server.url,
525 path: path + 'me',
526 token: userToken,
527 fields,
528 expectedStatus: HttpStatusCode.NO_CONTENT_204
529 })
530 })
531
532 it('Should succeed without password change with the correct params', async function () {
533 const fields = {
534 nsfwPolicy: 'blur',
535 autoPlayVideo: false
536 }
537
538 await makePutBodyRequest({
539 url: server.url,
540 path: path + 'me',
541 token: userToken,
542 fields,
543 expectedStatus: HttpStatusCode.NO_CONTENT_204
544 })
545 })
546 })
547
548 describe('When updating my avatar', function () {
549 it('Should fail without an incorrect input file', async function () {
550 const fields = {}
551 const attaches = {
552 avatarfile: buildAbsoluteFixturePath('video_short.mp4')
553 }
554 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
555 })
556
557 it('Should fail with a big file', async function () {
558 const fields = {}
559 const attaches = {
560 avatarfile: buildAbsoluteFixturePath('avatar-big.png')
561 }
562 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
563 })
564
565 it('Should fail with an unauthenticated user', async function () {
566 const fields = {}
567 const attaches = {
568 avatarfile: buildAbsoluteFixturePath('avatar.png')
569 }
570 await makeUploadRequest({
571 url: server.url,
572 path: path + '/me/avatar/pick',
573 fields,
574 attaches,
575 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
576 })
577 })
578
579 it('Should succeed with the correct params', async function () {
580 const fields = {}
581 const attaches = {
582 avatarfile: buildAbsoluteFixturePath('avatar.png')
583 }
584 await makeUploadRequest({
585 url: server.url,
586 path: path + '/me/avatar/pick',
587 token: server.accessToken,
588 fields,
589 attaches,
590 expectedStatus: HttpStatusCode.OK_200
591 })
592 })
593 })
594
595 describe('When managing my scoped tokens', function () {
596
597 it('Should fail to get my scoped tokens with an non authenticated user', async function () {
598 await server.users.getMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
599 })
600
601 it('Should fail to get my scoped tokens with a bad token', async function () {
602 await server.users.getMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
603
604 })
605
606 it('Should succeed to get my scoped tokens', async function () {
607 await server.users.getMyScopedTokens()
608 })
609
610 it('Should fail to renew my scoped tokens with an non authenticated user', async function () {
611 await server.users.renewMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
612 })
613
614 it('Should fail to renew my scoped tokens with a bad token', async function () {
615 await server.users.renewMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
616 })
617
618 it('Should succeed to renew my scoped tokens', async function () {
619 await server.users.renewMyScopedTokens()
620 })
621 })
622
623 describe('When getting a user', function () {
624
625 it('Should fail with an non authenticated user', async function () {
626 await makeGetRequest({
627 url: server.url,
628 path: path + userId,
629 token: 'super token',
630 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
631 })
632 })
633
634 it('Should fail with a non admin user', async function () {
635 await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
636 })
637
638 it('Should succeed with the correct params', async function () {
639 await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
640 })
641 })
642
643 describe('When updating a user', function () {
644
645 it('Should fail with an invalid email attribute', async function () {
646 const fields = {
647 email: 'blabla'
648 }
649
650 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
651 })
652
653 it('Should fail with an invalid emailVerified attribute', async function () {
654 const fields = {
655 emailVerified: 'yes'
656 }
657
658 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
659 })
660
661 it('Should fail with an invalid videoQuota attribute', async function () {
662 const fields = {
663 videoQuota: -90
664 }
665
666 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
667 })
668
669 it('Should fail with an invalid user role attribute', async function () {
670 const fields = {
671 role: 54878
672 }
673
674 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
675 })
676
677 it('Should fail with a too small password', async function () {
678 const fields = {
679 currentPassword: 'password',
680 password: 'bla'
681 }
682
683 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
684 })
685
686 it('Should fail with a too long password', async function () {
687 const fields = {
688 currentPassword: 'password',
689 password: 'super'.repeat(61)
690 }
691
692 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
693 })
694
695 it('Should fail with an non authenticated user', async function () {
696 const fields = {
697 videoQuota: 42
698 }
699
700 await makePutBodyRequest({
701 url: server.url,
702 path: path + userId,
703 token: 'super token',
704 fields,
705 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
706 })
707 })
708
709 it('Should fail when updating root role', async function () {
710 const fields = {
711 role: UserRole.MODERATOR
712 }
713
714 await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
715 })
716
717 it('Should fail with invalid admin flags', async function () {
718 const fields = { adminFlags: 'toto' }
719
720 await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
721 })
722
723 it('Should fail to update an admin with a moderator', async function () {
724 const fields = {
725 videoQuota: 42
726 }
727
728 await makePutBodyRequest({
729 url: server.url,
730 path: path + moderatorId,
731 token: moderatorToken,
732 fields,
733 expectedStatus: HttpStatusCode.FORBIDDEN_403
734 })
735 })
736
737 it('Should succeed to update a user with a moderator', async function () {
738 const fields = {
739 videoQuota: 42
740 }
741
742 await makePutBodyRequest({
743 url: server.url,
744 path: path + userId,
745 token: moderatorToken,
746 fields,
747 expectedStatus: HttpStatusCode.NO_CONTENT_204
748 })
749 })
750
751 it('Should succeed with the correct params', async function () {
752 const fields = {
753 email: 'email@example.com',
754 emailVerified: true,
755 videoQuota: 42,
756 role: UserRole.USER
757 }
758
759 await makePutBodyRequest({
760 url: server.url,
761 path: path + userId,
762 token: server.accessToken,
763 fields,
764 expectedStatus: HttpStatusCode.NO_CONTENT_204
765 })
766 })
767 })
768
769 describe('When getting my information', function () {
770 it('Should fail with a non authenticated user', async function () {
771 await server.users.getMyInfo({ token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
772 })
773
774 it('Should success with the correct parameters', async function () {
775 await server.users.getMyInfo({ token: userToken })
776 })
777 })
778
779 describe('When getting my video rating', function () {
780 let command: UsersCommand
781
782 before(function () {
783 command = server.users
784 })
785
786 it('Should fail with a non authenticated user', async function () {
787 await command.getMyRating({ token: 'fake_token', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
788 })
789
790 it('Should fail with an incorrect video uuid', async function () {
791 await command.getMyRating({ videoId: 'blabla', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
792 })
793
794 it('Should fail with an unknown video', async function () {
795 await command.getMyRating({ videoId: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
796 })
797
798 it('Should succeed with the correct parameters', async function () {
799 await command.getMyRating({ videoId: video.id })
800 await command.getMyRating({ videoId: video.uuid })
801 await command.getMyRating({ videoId: video.shortUUID })
802 })
803 })
804
805 describe('When retrieving my global ratings', function () {
806 const path = '/api/v1/accounts/user1/ratings'
807
808 it('Should fail with a bad start pagination', async function () {
809 await checkBadStartPagination(server.url, path, userToken)
810 })
811
812 it('Should fail with a bad count pagination', async function () {
813 await checkBadCountPagination(server.url, path, userToken)
814 })
815
816 it('Should fail with an incorrect sort', async function () {
817 await checkBadSortPagination(server.url, path, userToken)
818 })
819
820 it('Should fail with a unauthenticated user', async function () {
821 await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
822 })
823
824 it('Should fail with a another user', async function () {
825 await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
826 })
827
828 it('Should fail with a bad type', async function () {
829 await makeGetRequest({
830 url: server.url,
831 path,
832 token: userToken,
833 query: { rating: 'toto ' },
834 expectedStatus: HttpStatusCode.BAD_REQUEST_400
835 })
836 })
837
838 it('Should succeed with the correct params', async function () {
839 await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
840 })
841 })
842
843 describe('When getting my global followers', function () {
844 const path = '/api/v1/accounts/user1/followers'
845
846 it('Should fail with a bad start pagination', async function () {
847 await checkBadStartPagination(server.url, path, userToken)
848 })
849
850 it('Should fail with a bad count pagination', async function () {
851 await checkBadCountPagination(server.url, path, userToken)
852 })
853
854 it('Should fail with an incorrect sort', async function () {
855 await checkBadSortPagination(server.url, path, userToken)
856 })
857
858 it('Should fail with a unauthenticated user', async function () {
859 await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
860 })
861
862 it('Should fail with a another user', async function () {
863 await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
864 })
865
866 it('Should succeed with the correct params', async function () {
867 await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
868 })
869 })
870
871 describe('When blocking/unblocking/removing user', function () {
872
873 it('Should fail with an incorrect id', async function () {
874 const options = { userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
875
876 await server.users.remove(options)
877 await server.users.banUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
878 await server.users.unbanUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
879 })
880
881 it('Should fail with the root user', async function () {
882 const options = { userId: rootId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
883
884 await server.users.remove(options)
885 await server.users.banUser(options)
886 await server.users.unbanUser(options)
887 })
888
889 it('Should return 404 with a non existing id', async function () {
890 const options = { userId: 4545454, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
891
892 await server.users.remove(options)
893 await server.users.banUser(options)
894 await server.users.unbanUser(options)
895 })
896
897 it('Should fail with a non admin user', async function () {
898 const options = { userId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
899
900 await server.users.remove(options)
901 await server.users.banUser(options)
902 await server.users.unbanUser(options)
903 })
904
905 it('Should fail on a moderator with a moderator', async function () {
906 const options = { userId: moderatorId, token: moderatorToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
907
908 await server.users.remove(options)
909 await server.users.banUser(options)
910 await server.users.unbanUser(options)
911 })
912
913 it('Should succeed on a user with a moderator', async function () {
914 const options = { userId, token: moderatorToken }
915
916 await server.users.banUser(options)
917 await server.users.unbanUser(options)
918 })
919 })
920
921 describe('When deleting our account', function () {
922 it('Should fail with with the root account', async function () {
923 await server.users.deleteMe({ expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
924 })
925 }) 36 })
926 37
927 describe('When registering a new user', function () { 38 describe('When registering a new user', function () {
@@ -1081,9 +192,11 @@ describe('Test users API validators', function () {
1081 }) 192 })
1082 193
1083 describe('When registering multiple users on a server with users limit', function () { 194 describe('When registering multiple users on a server with users limit', function () {
195
1084 it('Should fail when after 3 registrations', async function () { 196 it('Should fail when after 3 registrations', async function () {
1085 await server.users.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 197 await server.users.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
1086 }) 198 })
199
1087 }) 200 })
1088 201
1089 describe('When asking a password reset', function () { 202 describe('When asking a password reset', function () {
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts
index b49367be6..d1d192238 100644
--- a/server/tests/api/users/user-subscriptions.ts
+++ b/server/tests/api/users/user-subscriptions.ts
@@ -390,6 +390,8 @@ describe('Test users subscriptions', function () {
390 }) 390 })
391 391
392 expect(total).to.equal(3) 392 expect(total).to.equal(3)
393 expect(data).to.have.lengthOf(3)
394
393 expect(data[0].following.host).to.equal(servers[2].host) 395 expect(data[0].following.host).to.equal(servers[2].host)
394 expect(data[0].following.name).to.equal('user3_channel') 396 expect(data[0].following.name).to.equal('user3_channel')
395 expect(data[0].follower.host).to.equal(servers[0].host) 397 expect(data[0].follower.host).to.equal(servers[0].host)
@@ -416,6 +418,8 @@ describe('Test users subscriptions', function () {
416 }) 418 })
417 419
418 expect(total).to.equal(3) 420 expect(total).to.equal(3)
421 expect(data).to.have.lengthOf(1)
422
419 expect(data[0].following.host).to.equal(servers[2].host) 423 expect(data[0].following.host).to.equal(servers[2].host)
420 expect(data[0].following.name).to.equal('user3_channel2') 424 expect(data[0].following.name).to.equal('user3_channel2')
421 expect(data[0].follower.host).to.equal(servers[2].host) 425 expect(data[0].follower.host).to.equal(servers[2].host)
@@ -432,6 +436,8 @@ describe('Test users subscriptions', function () {
432 }) 436 })
433 437
434 expect(total).to.equal(3) 438 expect(total).to.equal(3)
439 expect(data).to.have.lengthOf(1)
440
435 expect(data[0].following.host).to.equal(servers[2].host) 441 expect(data[0].following.host).to.equal(servers[2].host)
436 expect(data[0].following.name).to.equal('user3_channel') 442 expect(data[0].following.name).to.equal('user3_channel')
437 expect(data[0].follower.host).to.equal(servers[2].host) 443 expect(data[0].follower.host).to.equal(servers[2].host)
@@ -447,6 +453,8 @@ describe('Test users subscriptions', function () {
447 }) 453 })
448 454
449 expect(total).to.equal(1) 455 expect(total).to.equal(1)
456 expect(data).to.have.lengthOf(1)
457
450 expect(data[0].following.host).to.equal(servers[2].host) 458 expect(data[0].following.host).to.equal(servers[2].host)
451 expect(data[0].following.name).to.equal('user3_channel') 459 expect(data[0].following.name).to.equal('user3_channel')
452 expect(data[0].follower.host).to.equal(servers[0].host) 460 expect(data[0].follower.host).to.equal(servers[0].host)
@@ -465,6 +473,8 @@ describe('Test users subscriptions', function () {
465 }) 473 })
466 474
467 expect(total).to.equal(2) 475 expect(total).to.equal(2)
476 expect(data).to.have.lengthOf(2)
477
468 expect(data[0].following.host).to.equal(servers[2].host) 478 expect(data[0].following.host).to.equal(servers[2].host)
469 expect(data[0].following.name).to.equal('user3_channel') 479 expect(data[0].following.name).to.equal('user3_channel')
470 expect(data[0].follower.host).to.equal(servers[0].host) 480 expect(data[0].follower.host).to.equal(servers[0].host)
@@ -486,6 +496,8 @@ describe('Test users subscriptions', function () {
486 }) 496 })
487 497
488 expect(total).to.equal(2) 498 expect(total).to.equal(2)
499 expect(data).to.have.lengthOf(1)
500
489 expect(data[0].following.host).to.equal(servers[2].host) 501 expect(data[0].following.host).to.equal(servers[2].host)
490 expect(data[0].following.name).to.equal('user3_channel') 502 expect(data[0].following.name).to.equal('user3_channel')
491 expect(data[0].follower.host).to.equal(servers[2].host) 503 expect(data[0].follower.host).to.equal(servers[2].host)
@@ -502,10 +514,12 @@ describe('Test users subscriptions', function () {
502 }) 514 })
503 515
504 expect(total).to.equal(2) 516 expect(total).to.equal(2)
517 expect(data).to.have.lengthOf(1)
518
505 expect(data[0].following.host).to.equal(servers[2].host) 519 expect(data[0].following.host).to.equal(servers[2].host)
506 expect(data[0].following.name).to.equal('user3_channel') 520 expect(data[0].following.name).to.equal('user3_channel')
507 expect(data[0].follower.host).to.equal(servers[0].host) 521 expect(data[0].follower.host).to.equal(servers[0].host)
508 expect(data[0].follower.name).to.equal('root') 522 expect(data[0].follower.name).to.equal('user1')
509 } 523 }
510 524
511 { 525 {
@@ -517,6 +531,8 @@ describe('Test users subscriptions', function () {
517 }) 531 })
518 532
519 expect(total).to.equal(1) 533 expect(total).to.equal(1)
534 expect(data).to.have.lengthOf(1)
535
520 expect(data[0].following.host).to.equal(servers[2].host) 536 expect(data[0].following.host).to.equal(servers[2].host)
521 expect(data[0].following.name).to.equal('user3_channel') 537 expect(data[0].following.name).to.equal('user3_channel')
522 expect(data[0].follower.host).to.equal(servers[0].host) 538 expect(data[0].follower.host).to.equal(servers[0].host)