diff options
author | Chocobozzz <me@florianbigard.com> | 2023-01-19 09:28:29 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2023-01-19 13:53:40 +0100 |
commit | b379759f55a35837b803a3b988674972db2903d1 (patch) | |
tree | 895d556973fea9be21492fb60aec2ff7767f5b18 | |
parent | 3e5716dd3a5b0db4a1db327714247da687419f92 (diff) | |
download | PeerTube-b379759f55a35837b803a3b988674972db2903d1.tar.gz PeerTube-b379759f55a35837b803a3b988674972db2903d1.tar.zst PeerTube-b379759f55a35837b803a3b988674972db2903d1.zip |
Add signup approval API tests
30 files changed, 1418 insertions, 452 deletions
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts index 3415625ca..93a3f3eb9 100644 --- a/server/tests/api/check-params/config.ts +++ b/server/tests/api/check-params/config.ts | |||
@@ -79,6 +79,7 @@ describe('Test config API validators', function () { | |||
79 | signup: { | 79 | signup: { |
80 | enabled: false, | 80 | enabled: false, |
81 | limit: 5, | 81 | limit: 5, |
82 | requiresApproval: false, | ||
82 | requiresEmailVerification: false, | 83 | requiresEmailVerification: false, |
83 | minimumAge: 16 | 84 | minimumAge: 16 |
84 | }, | 85 | }, |
@@ -313,6 +314,7 @@ describe('Test config API validators', function () { | |||
313 | signup: { | 314 | signup: { |
314 | enabled: true, | 315 | enabled: true, |
315 | limit: 5, | 316 | limit: 5, |
317 | requiresApproval: true, | ||
316 | requiresEmailVerification: true | 318 | requiresEmailVerification: true |
317 | } | 319 | } |
318 | } | 320 | } |
diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts index 7968ef802..f0f8819b9 100644 --- a/server/tests/api/check-params/contact-form.ts +++ b/server/tests/api/check-params/contact-form.ts | |||
@@ -2,7 +2,14 @@ | |||
2 | 2 | ||
3 | import { MockSmtpServer } from '@server/tests/shared' | 3 | import { MockSmtpServer } from '@server/tests/shared' |
4 | import { HttpStatusCode } from '@shared/models' | 4 | import { HttpStatusCode } from '@shared/models' |
5 | import { cleanupTests, ContactFormCommand, createSingleServer, killallServers, PeerTubeServer } from '@shared/server-commands' | 5 | import { |
6 | cleanupTests, | ||
7 | ConfigCommand, | ||
8 | ContactFormCommand, | ||
9 | createSingleServer, | ||
10 | killallServers, | ||
11 | PeerTubeServer | ||
12 | } from '@shared/server-commands' | ||
6 | 13 | ||
7 | describe('Test contact form API validators', function () { | 14 | describe('Test contact form API validators', function () { |
8 | let server: PeerTubeServer | 15 | let server: PeerTubeServer |
@@ -38,7 +45,7 @@ describe('Test contact form API validators', function () { | |||
38 | await killallServers([ server ]) | 45 | await killallServers([ server ]) |
39 | 46 | ||
40 | // Contact form is disabled | 47 | // Contact form is disabled |
41 | await server.run({ smtp: { hostname: '127.0.0.1', port: emailPort }, contact_form: { enabled: false } }) | 48 | await server.run({ ...ConfigCommand.getEmailOverrideConfig(emailPort), contact_form: { enabled: false } }) |
42 | await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 }) | 49 | await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 }) |
43 | }) | 50 | }) |
44 | 51 | ||
@@ -48,7 +55,7 @@ describe('Test contact form API validators', function () { | |||
48 | await killallServers([ server ]) | 55 | await killallServers([ server ]) |
49 | 56 | ||
50 | // Email & contact form enabled | 57 | // Email & contact form enabled |
51 | await server.run({ smtp: { hostname: '127.0.0.1', port: emailPort } }) | 58 | await server.run(ConfigCommand.getEmailOverrideConfig(emailPort)) |
52 | 59 | ||
53 | await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 60 | await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
54 | await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 61 | await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts index 961093bb5..ddbcb42f8 100644 --- a/server/tests/api/check-params/index.ts +++ b/server/tests/api/check-params/index.ts | |||
@@ -15,6 +15,7 @@ import './metrics' | |||
15 | import './my-user' | 15 | import './my-user' |
16 | import './plugins' | 16 | import './plugins' |
17 | import './redundancy' | 17 | import './redundancy' |
18 | import './registrations' | ||
18 | import './search' | 19 | import './search' |
19 | import './services' | 20 | import './services' |
20 | import './transcoding' | 21 | import './transcoding' |
@@ -23,7 +24,7 @@ import './upload-quota' | |||
23 | import './user-notifications' | 24 | import './user-notifications' |
24 | import './user-subscriptions' | 25 | import './user-subscriptions' |
25 | import './users-admin' | 26 | import './users-admin' |
26 | import './users' | 27 | import './users-emails' |
27 | import './video-blacklist' | 28 | import './video-blacklist' |
28 | import './video-captions' | 29 | import './video-captions' |
29 | import './video-channel-syncs' | 30 | import './video-channel-syncs' |
diff --git a/server/tests/api/check-params/registrations.ts b/server/tests/api/check-params/registrations.ts new file mode 100644 index 000000000..9f0462378 --- /dev/null +++ b/server/tests/api/check-params/registrations.ts | |||
@@ -0,0 +1,402 @@ | |||
1 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared' | ||
2 | import { omit } from '@shared/core-utils' | ||
3 | import { HttpStatusCode, UserRole } from '@shared/models' | ||
4 | import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' | ||
5 | |||
6 | describe('Test registrations API validators', function () { | ||
7 | let server: PeerTubeServer | ||
8 | let userToken: string | ||
9 | let moderatorToken: string | ||
10 | |||
11 | // --------------------------------------------------------------- | ||
12 | |||
13 | before(async function () { | ||
14 | this.timeout(30000) | ||
15 | |||
16 | server = await createSingleServer(1) | ||
17 | |||
18 | await setAccessTokensToServers([ server ]) | ||
19 | await server.config.enableSignup(false); | ||
20 | |||
21 | ({ token: moderatorToken } = await server.users.generate('moderator', UserRole.MODERATOR)); | ||
22 | ({ token: userToken } = await server.users.generate('user', UserRole.USER)) | ||
23 | }) | ||
24 | |||
25 | describe('Register', function () { | ||
26 | const registrationPath = '/api/v1/users/register' | ||
27 | const registrationRequestPath = '/api/v1/users/registrations/request' | ||
28 | |||
29 | const baseCorrectParams = { | ||
30 | username: 'user3', | ||
31 | displayName: 'super user', | ||
32 | email: 'test3@example.com', | ||
33 | password: 'my super password', | ||
34 | registrationReason: 'my super registration reason' | ||
35 | } | ||
36 | |||
37 | describe('When registering a new user or requesting user registration', function () { | ||
38 | |||
39 | async function check (fields: any, expectedStatus = HttpStatusCode.BAD_REQUEST_400) { | ||
40 | await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus }) | ||
41 | await makePostBodyRequest({ url: server.url, path: registrationRequestPath, fields, expectedStatus }) | ||
42 | } | ||
43 | |||
44 | it('Should fail with a too small username', async function () { | ||
45 | const fields = { ...baseCorrectParams, username: '' } | ||
46 | |||
47 | await check(fields) | ||
48 | }) | ||
49 | |||
50 | it('Should fail with a too long username', async function () { | ||
51 | const fields = { ...baseCorrectParams, username: 'super'.repeat(50) } | ||
52 | |||
53 | await check(fields) | ||
54 | }) | ||
55 | |||
56 | it('Should fail with an incorrect username', async function () { | ||
57 | const fields = { ...baseCorrectParams, username: 'my username' } | ||
58 | |||
59 | await check(fields) | ||
60 | }) | ||
61 | |||
62 | it('Should fail with a missing email', async function () { | ||
63 | const fields = omit(baseCorrectParams, [ 'email' ]) | ||
64 | |||
65 | await check(fields) | ||
66 | }) | ||
67 | |||
68 | it('Should fail with an invalid email', async function () { | ||
69 | const fields = { ...baseCorrectParams, email: 'test_example.com' } | ||
70 | |||
71 | await check(fields) | ||
72 | }) | ||
73 | |||
74 | it('Should fail with a too small password', async function () { | ||
75 | const fields = { ...baseCorrectParams, password: 'bla' } | ||
76 | |||
77 | await check(fields) | ||
78 | }) | ||
79 | |||
80 | it('Should fail with a too long password', async function () { | ||
81 | const fields = { ...baseCorrectParams, password: 'super'.repeat(61) } | ||
82 | |||
83 | await check(fields) | ||
84 | }) | ||
85 | |||
86 | it('Should fail if we register a user with the same username', async function () { | ||
87 | const fields = { ...baseCorrectParams, username: 'root' } | ||
88 | |||
89 | await check(fields, HttpStatusCode.CONFLICT_409) | ||
90 | }) | ||
91 | |||
92 | it('Should fail with a "peertube" username', async function () { | ||
93 | const fields = { ...baseCorrectParams, username: 'peertube' } | ||
94 | |||
95 | await check(fields, HttpStatusCode.CONFLICT_409) | ||
96 | }) | ||
97 | |||
98 | it('Should fail if we register a user with the same email', async function () { | ||
99 | const fields = { ...baseCorrectParams, email: 'admin' + server.internalServerNumber + '@example.com' } | ||
100 | |||
101 | await check(fields, HttpStatusCode.CONFLICT_409) | ||
102 | }) | ||
103 | |||
104 | it('Should fail with a bad display name', async function () { | ||
105 | const fields = { ...baseCorrectParams, displayName: 'a'.repeat(150) } | ||
106 | |||
107 | await check(fields) | ||
108 | }) | ||
109 | |||
110 | it('Should fail with a bad channel name', async function () { | ||
111 | const fields = { ...baseCorrectParams, channel: { name: '[]azf', displayName: 'toto' } } | ||
112 | |||
113 | await check(fields) | ||
114 | }) | ||
115 | |||
116 | it('Should fail with a bad channel display name', async function () { | ||
117 | const fields = { ...baseCorrectParams, channel: { name: 'toto', displayName: '' } } | ||
118 | |||
119 | await check(fields) | ||
120 | }) | ||
121 | |||
122 | it('Should fail with a channel name that is the same as username', async function () { | ||
123 | const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } } | ||
124 | const fields = { ...baseCorrectParams, ...source } | ||
125 | |||
126 | await check(fields) | ||
127 | }) | ||
128 | |||
129 | it('Should fail with an existing channel', async function () { | ||
130 | const attributes = { name: 'existing_channel', displayName: 'hello', description: 'super description' } | ||
131 | await server.channels.create({ attributes }) | ||
132 | |||
133 | const fields = { ...baseCorrectParams, channel: { name: 'existing_channel', displayName: 'toto' } } | ||
134 | |||
135 | await check(fields, HttpStatusCode.CONFLICT_409) | ||
136 | }) | ||
137 | |||
138 | it('Should fail on a server with registration disabled', async function () { | ||
139 | this.timeout(60000) | ||
140 | |||
141 | await server.config.updateCustomSubConfig({ | ||
142 | newConfig: { | ||
143 | signup: { | ||
144 | enabled: false | ||
145 | } | ||
146 | } | ||
147 | }) | ||
148 | |||
149 | await server.registrations.register({ username: 'user4', expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
150 | await server.registrations.requestRegistration({ | ||
151 | username: 'user4', | ||
152 | registrationReason: 'reason', | ||
153 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
154 | }) | ||
155 | }) | ||
156 | |||
157 | it('Should fail if the user limit is reached', async function () { | ||
158 | this.timeout(60000) | ||
159 | |||
160 | const { total } = await server.users.list() | ||
161 | |||
162 | await server.config.updateCustomSubConfig({ newConfig: { signup: { limit: total } } }) | ||
163 | |||
164 | await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
165 | await server.registrations.requestRegistration({ | ||
166 | username: 'user42', | ||
167 | registrationReason: 'reason', | ||
168 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
169 | }) | ||
170 | }) | ||
171 | }) | ||
172 | |||
173 | describe('On direct registration', function () { | ||
174 | |||
175 | it('Should succeed with the correct params', async function () { | ||
176 | await server.config.enableSignup(false) | ||
177 | |||
178 | const fields = { | ||
179 | username: 'user_direct_1', | ||
180 | displayName: 'super user direct 1', | ||
181 | email: 'user_direct_1@example.com', | ||
182 | password: 'my super password', | ||
183 | channel: { name: 'super_user_direct_1_channel', displayName: 'super user direct 1 channel' } | ||
184 | } | ||
185 | |||
186 | await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus: HttpStatusCode.NO_CONTENT_204 }) | ||
187 | }) | ||
188 | |||
189 | it('Should fail if the instance requires approval', async function () { | ||
190 | this.timeout(60000) | ||
191 | |||
192 | await server.config.enableSignup(true) | ||
193 | await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
194 | }) | ||
195 | }) | ||
196 | |||
197 | describe('On registration request', function () { | ||
198 | |||
199 | before(async function () { | ||
200 | this.timeout(60000) | ||
201 | |||
202 | await server.config.enableSignup(true) | ||
203 | }) | ||
204 | |||
205 | it('Should fail with an invalid registration reason', async function () { | ||
206 | for (const registrationReason of [ '', 't', 't'.repeat(5000) ]) { | ||
207 | await server.registrations.requestRegistration({ | ||
208 | username: 'user_request_1', | ||
209 | registrationReason, | ||
210 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
211 | }) | ||
212 | } | ||
213 | }) | ||
214 | |||
215 | it('Should succeed with the correct params', async function () { | ||
216 | await server.registrations.requestRegistration({ | ||
217 | username: 'user_request_2', | ||
218 | registrationReason: 'tt', | ||
219 | channel: { | ||
220 | displayName: 'my user request 2 channel', | ||
221 | name: 'user_request_2_channel' | ||
222 | } | ||
223 | }) | ||
224 | }) | ||
225 | |||
226 | it('Should fail if the user is already awaiting registration approval', async function () { | ||
227 | await server.registrations.requestRegistration({ | ||
228 | username: 'user_request_2', | ||
229 | registrationReason: 'tt', | ||
230 | channel: { | ||
231 | displayName: 'my user request 42 channel', | ||
232 | name: 'user_request_42_channel' | ||
233 | }, | ||
234 | expectedStatus: HttpStatusCode.CONFLICT_409 | ||
235 | }) | ||
236 | }) | ||
237 | |||
238 | it('Should fail if the channel is already awaiting registration approval', async function () { | ||
239 | await server.registrations.requestRegistration({ | ||
240 | username: 'user42', | ||
241 | registrationReason: 'tt', | ||
242 | channel: { | ||
243 | displayName: 'my user request 2 channel', | ||
244 | name: 'user_request_2_channel' | ||
245 | }, | ||
246 | expectedStatus: HttpStatusCode.CONFLICT_409 | ||
247 | }) | ||
248 | }) | ||
249 | |||
250 | it('Should fail if the instance does not require approval', async function () { | ||
251 | this.timeout(60000) | ||
252 | |||
253 | await server.config.enableSignup(false) | ||
254 | |||
255 | await server.registrations.requestRegistration({ | ||
256 | username: 'user42', | ||
257 | registrationReason: 'toto', | ||
258 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
259 | }) | ||
260 | }) | ||
261 | }) | ||
262 | }) | ||
263 | |||
264 | describe('Registrations accept/reject', function () { | ||
265 | let id1: number | ||
266 | let id2: number | ||
267 | |||
268 | before(async function () { | ||
269 | this.timeout(60000) | ||
270 | |||
271 | await server.config.enableSignup(true); | ||
272 | |||
273 | ({ id: id1 } = await server.registrations.requestRegistration({ username: 'request_2', registrationReason: 'toto' })); | ||
274 | ({ id: id2 } = await server.registrations.requestRegistration({ username: 'request_3', registrationReason: 'toto' })) | ||
275 | }) | ||
276 | |||
277 | it('Should fail to accept/reject registration without token', async function () { | ||
278 | const options = { id: id1, moderationResponse: 'tt', token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 } | ||
279 | await server.registrations.accept(options) | ||
280 | await server.registrations.reject(options) | ||
281 | }) | ||
282 | |||
283 | it('Should fail to accept/reject registration with a non moderator user', async function () { | ||
284 | const options = { id: id1, moderationResponse: 'tt', token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 } | ||
285 | await server.registrations.accept(options) | ||
286 | await server.registrations.reject(options) | ||
287 | }) | ||
288 | |||
289 | it('Should fail to accept/reject registration with a bad registration id', async function () { | ||
290 | { | ||
291 | const options = { id: 't' as any, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 } | ||
292 | await server.registrations.accept(options) | ||
293 | await server.registrations.reject(options) | ||
294 | } | ||
295 | |||
296 | { | ||
297 | const options = { id: 42, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 } | ||
298 | await server.registrations.accept(options) | ||
299 | await server.registrations.reject(options) | ||
300 | } | ||
301 | }) | ||
302 | |||
303 | it('Should fail to accept/reject registration with a bad moderation resposne', async function () { | ||
304 | for (const moderationResponse of [ '', 't', 't'.repeat(5000) ]) { | ||
305 | const options = { id: id1, moderationResponse, token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 } | ||
306 | await server.registrations.accept(options) | ||
307 | await server.registrations.reject(options) | ||
308 | } | ||
309 | }) | ||
310 | |||
311 | it('Should succeed to accept a registration', async function () { | ||
312 | await server.registrations.accept({ id: id1, moderationResponse: 'tt', token: moderatorToken }) | ||
313 | }) | ||
314 | |||
315 | it('Should succeed to reject a registration', async function () { | ||
316 | await server.registrations.reject({ id: id2, moderationResponse: 'tt', token: moderatorToken }) | ||
317 | }) | ||
318 | |||
319 | it('Should fail to accept/reject a registration that was already accepted/rejected', async function () { | ||
320 | for (const id of [ id1, id2 ]) { | ||
321 | const options = { id, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.CONFLICT_409 } | ||
322 | await server.registrations.accept(options) | ||
323 | await server.registrations.reject(options) | ||
324 | } | ||
325 | }) | ||
326 | }) | ||
327 | |||
328 | describe('Registrations deletion', function () { | ||
329 | let id1: number | ||
330 | let id2: number | ||
331 | let id3: number | ||
332 | |||
333 | before(async function () { | ||
334 | ({ id: id1 } = await server.registrations.requestRegistration({ username: 'request_4', registrationReason: 'toto' })); | ||
335 | ({ id: id2 } = await server.registrations.requestRegistration({ username: 'request_5', registrationReason: 'toto' })); | ||
336 | ({ id: id3 } = await server.registrations.requestRegistration({ username: 'request_6', registrationReason: 'toto' })) | ||
337 | |||
338 | await server.registrations.accept({ id: id2, moderationResponse: 'tt' }) | ||
339 | await server.registrations.reject({ id: id3, moderationResponse: 'tt' }) | ||
340 | }) | ||
341 | |||
342 | it('Should fail to delete registration without token', async function () { | ||
343 | await server.registrations.delete({ id: id1, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
344 | }) | ||
345 | |||
346 | it('Should fail to delete registration with a non moderator user', async function () { | ||
347 | await server.registrations.delete({ id: id1, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
348 | }) | ||
349 | |||
350 | it('Should fail to delete registration with a bad registration id', async function () { | ||
351 | await server.registrations.delete({ id: 't' as any, token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | ||
352 | await server.registrations.delete({ id: 42, token: moderatorToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
353 | }) | ||
354 | |||
355 | it('Should succeed with the correct params', async function () { | ||
356 | await server.registrations.delete({ id: id1, token: moderatorToken }) | ||
357 | await server.registrations.delete({ id: id2, token: moderatorToken }) | ||
358 | await server.registrations.delete({ id: id3, token: moderatorToken }) | ||
359 | }) | ||
360 | }) | ||
361 | |||
362 | describe('Listing registrations', function () { | ||
363 | const path = '/api/v1/users/registrations' | ||
364 | |||
365 | it('Should fail with a bad start pagination', async function () { | ||
366 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
367 | }) | ||
368 | |||
369 | it('Should fail with a bad count pagination', async function () { | ||
370 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
371 | }) | ||
372 | |||
373 | it('Should fail with an incorrect sort', async function () { | ||
374 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
375 | }) | ||
376 | |||
377 | it('Should fail with a non authenticated user', async function () { | ||
378 | await server.registrations.list({ | ||
379 | token: null, | ||
380 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | ||
381 | }) | ||
382 | }) | ||
383 | |||
384 | it('Should fail with a non admin user', async function () { | ||
385 | await server.registrations.list({ | ||
386 | token: userToken, | ||
387 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
388 | }) | ||
389 | }) | ||
390 | |||
391 | it('Should succeed with the correct params', async function () { | ||
392 | await server.registrations.list({ | ||
393 | token: moderatorToken, | ||
394 | search: 'toto' | ||
395 | }) | ||
396 | }) | ||
397 | }) | ||
398 | |||
399 | after(async function () { | ||
400 | await cleanupTests([ server ]) | ||
401 | }) | ||
402 | }) | ||
diff --git a/server/tests/api/check-params/upload-quota.ts b/server/tests/api/check-params/upload-quota.ts index 70e6f4af9..fdc711bd5 100644 --- a/server/tests/api/check-params/upload-quota.ts +++ b/server/tests/api/check-params/upload-quota.ts | |||
@@ -42,7 +42,7 @@ describe('Test upload quota', function () { | |||
42 | this.timeout(30000) | 42 | this.timeout(30000) |
43 | 43 | ||
44 | const user = { username: 'registered' + randomInt(1, 1500), password: 'password' } | 44 | const user = { username: 'registered' + randomInt(1, 1500), password: 'password' } |
45 | await server.users.register(user) | 45 | await server.registrations.register(user) |
46 | const userToken = await server.login.getAccessToken(user) | 46 | const userToken = await server.login.getAccessToken(user) |
47 | 47 | ||
48 | const attributes = { fixture: 'video_short2.webm' } | 48 | const attributes = { fixture: 'video_short2.webm' } |
@@ -57,7 +57,7 @@ describe('Test upload quota', function () { | |||
57 | this.timeout(30000) | 57 | this.timeout(30000) |
58 | 58 | ||
59 | const user = { username: 'registered' + randomInt(1, 1500), password: 'password' } | 59 | const user = { username: 'registered' + randomInt(1, 1500), password: 'password' } |
60 | await server.users.register(user) | 60 | await server.registrations.register(user) |
61 | const userToken = await server.login.getAccessToken(user) | 61 | const userToken = await server.login.getAccessToken(user) |
62 | 62 | ||
63 | const attributes = { fixture: 'video_short2.webm' } | 63 | const attributes = { fixture: 'video_short2.webm' } |
diff --git a/server/tests/api/check-params/users-admin.ts b/server/tests/api/check-params/users-admin.ts index 7ba709c4a..be2496bb4 100644 --- a/server/tests/api/check-params/users-admin.ts +++ b/server/tests/api/check-params/users-admin.ts | |||
@@ -5,6 +5,7 @@ import { omit } from '@shared/core-utils' | |||
5 | import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models' | 5 | import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models' |
6 | import { | 6 | import { |
7 | cleanupTests, | 7 | cleanupTests, |
8 | ConfigCommand, | ||
8 | createSingleServer, | 9 | createSingleServer, |
9 | killallServers, | 10 | killallServers, |
10 | makeGetRequest, | 11 | makeGetRequest, |
@@ -156,13 +157,7 @@ describe('Test users admin API validators', function () { | |||
156 | 157 | ||
157 | await killallServers([ server ]) | 158 | await killallServers([ server ]) |
158 | 159 | ||
159 | const config = { | 160 | await server.run(ConfigCommand.getEmailOverrideConfig(emailPort)) |
160 | smtp: { | ||
161 | hostname: '127.0.0.1', | ||
162 | port: emailPort | ||
163 | } | ||
164 | } | ||
165 | await server.run(config) | ||
166 | 161 | ||
167 | const fields = { | 162 | const fields = { |
168 | ...baseCorrectParams, | 163 | ...baseCorrectParams, |
diff --git a/server/tests/api/check-params/users-emails.ts b/server/tests/api/check-params/users-emails.ts new file mode 100644 index 000000000..8cfb1d15f --- /dev/null +++ b/server/tests/api/check-params/users-emails.ts | |||
@@ -0,0 +1,119 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | import { MockSmtpServer } from '@server/tests/shared' | ||
3 | import { HttpStatusCode, UserRole } from '@shared/models' | ||
4 | import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' | ||
5 | |||
6 | describe('Test users API validators', function () { | ||
7 | let server: PeerTubeServer | ||
8 | |||
9 | // --------------------------------------------------------------- | ||
10 | |||
11 | before(async function () { | ||
12 | this.timeout(30000) | ||
13 | |||
14 | server = await createSingleServer(1, { | ||
15 | rates_limit: { | ||
16 | ask_send_email: { | ||
17 | max: 10 | ||
18 | } | ||
19 | } | ||
20 | }) | ||
21 | |||
22 | await setAccessTokensToServers([ server ]) | ||
23 | await server.config.enableSignup(true) | ||
24 | |||
25 | await server.users.generate('moderator2', UserRole.MODERATOR) | ||
26 | |||
27 | await server.registrations.requestRegistration({ | ||
28 | username: 'request1', | ||
29 | registrationReason: 'tt' | ||
30 | }) | ||
31 | }) | ||
32 | |||
33 | describe('When asking a password reset', function () { | ||
34 | const path = '/api/v1/users/ask-reset-password' | ||
35 | |||
36 | it('Should fail with a missing email', async function () { | ||
37 | const fields = {} | ||
38 | |||
39 | await makePostBodyRequest({ url: server.url, path, fields }) | ||
40 | }) | ||
41 | |||
42 | it('Should fail with an invalid email', async function () { | ||
43 | const fields = { email: 'hello' } | ||
44 | |||
45 | await makePostBodyRequest({ url: server.url, path, fields }) | ||
46 | }) | ||
47 | |||
48 | it('Should success with the correct params', async function () { | ||
49 | const fields = { email: 'admin@example.com' } | ||
50 | |||
51 | await makePostBodyRequest({ | ||
52 | url: server.url, | ||
53 | path, | ||
54 | fields, | ||
55 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
56 | }) | ||
57 | }) | ||
58 | }) | ||
59 | |||
60 | describe('When asking for an account verification email', function () { | ||
61 | const path = '/api/v1/users/ask-send-verify-email' | ||
62 | |||
63 | it('Should fail with a missing email', async function () { | ||
64 | const fields = {} | ||
65 | |||
66 | await makePostBodyRequest({ url: server.url, path, fields }) | ||
67 | }) | ||
68 | |||
69 | it('Should fail with an invalid email', async function () { | ||
70 | const fields = { email: 'hello' } | ||
71 | |||
72 | await makePostBodyRequest({ url: server.url, path, fields }) | ||
73 | }) | ||
74 | |||
75 | it('Should succeed with the correct params', async function () { | ||
76 | const fields = { email: 'admin@example.com' } | ||
77 | |||
78 | await makePostBodyRequest({ | ||
79 | url: server.url, | ||
80 | path, | ||
81 | fields, | ||
82 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
83 | }) | ||
84 | }) | ||
85 | }) | ||
86 | |||
87 | describe('When asking for a registration verification email', function () { | ||
88 | const path = '/api/v1/users/registrations/ask-send-verify-email' | ||
89 | |||
90 | it('Should fail with a missing email', async function () { | ||
91 | const fields = {} | ||
92 | |||
93 | await makePostBodyRequest({ url: server.url, path, fields }) | ||
94 | }) | ||
95 | |||
96 | it('Should fail with an invalid email', async function () { | ||
97 | const fields = { email: 'hello' } | ||
98 | |||
99 | await makePostBodyRequest({ url: server.url, path, fields }) | ||
100 | }) | ||
101 | |||
102 | it('Should succeed with the correct params', async function () { | ||
103 | const fields = { email: 'request1@example.com' } | ||
104 | |||
105 | await makePostBodyRequest({ | ||
106 | url: server.url, | ||
107 | path, | ||
108 | fields, | ||
109 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
110 | }) | ||
111 | }) | ||
112 | }) | ||
113 | |||
114 | after(async function () { | ||
115 | MockSmtpServer.Instance.kill() | ||
116 | |||
117 | await cleanupTests([ server ]) | ||
118 | }) | ||
119 | }) | ||
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts deleted file mode 100644 index 7acfd8c2c..000000000 --- a/server/tests/api/check-params/users.ts +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | import { MockSmtpServer } from '@server/tests/shared' | ||
3 | import { omit } from '@shared/core-utils' | ||
4 | import { HttpStatusCode, UserRole } from '@shared/models' | ||
5 | import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' | ||
6 | |||
7 | describe('Test users API validators', function () { | ||
8 | const path = '/api/v1/users/' | ||
9 | let server: PeerTubeServer | ||
10 | let serverWithRegistrationDisabled: PeerTubeServer | ||
11 | |||
12 | // --------------------------------------------------------------- | ||
13 | |||
14 | before(async function () { | ||
15 | this.timeout(30000) | ||
16 | |||
17 | const res = await Promise.all([ | ||
18 | createSingleServer(1, { signup: { limit: 3 } }), | ||
19 | createSingleServer(2) | ||
20 | ]) | ||
21 | |||
22 | server = res[0] | ||
23 | serverWithRegistrationDisabled = res[1] | ||
24 | |||
25 | await setAccessTokensToServers([ server ]) | ||
26 | |||
27 | await server.users.generate('moderator2', UserRole.MODERATOR) | ||
28 | }) | ||
29 | |||
30 | describe('When registering a new user', function () { | ||
31 | const registrationPath = path + '/register' | ||
32 | const baseCorrectParams = { | ||
33 | username: 'user3', | ||
34 | displayName: 'super user', | ||
35 | email: 'test3@example.com', | ||
36 | password: 'my super password' | ||
37 | } | ||
38 | |||
39 | it('Should fail with a too small username', async function () { | ||
40 | const fields = { ...baseCorrectParams, username: '' } | ||
41 | |||
42 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
43 | }) | ||
44 | |||
45 | it('Should fail with a too long username', async function () { | ||
46 | const fields = { ...baseCorrectParams, username: 'super'.repeat(50) } | ||
47 | |||
48 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
49 | }) | ||
50 | |||
51 | it('Should fail with an incorrect username', async function () { | ||
52 | const fields = { ...baseCorrectParams, username: 'my username' } | ||
53 | |||
54 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
55 | }) | ||
56 | |||
57 | it('Should fail with a missing email', async function () { | ||
58 | const fields = omit(baseCorrectParams, [ 'email' ]) | ||
59 | |||
60 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
61 | }) | ||
62 | |||
63 | it('Should fail with an invalid email', async function () { | ||
64 | const fields = { ...baseCorrectParams, email: 'test_example.com' } | ||
65 | |||
66 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
67 | }) | ||
68 | |||
69 | it('Should fail with a too small password', async function () { | ||
70 | const fields = { ...baseCorrectParams, password: 'bla' } | ||
71 | |||
72 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
73 | }) | ||
74 | |||
75 | it('Should fail with a too long password', async function () { | ||
76 | const fields = { ...baseCorrectParams, password: 'super'.repeat(61) } | ||
77 | |||
78 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
79 | }) | ||
80 | |||
81 | it('Should fail if we register a user with the same username', async function () { | ||
82 | const fields = { ...baseCorrectParams, username: 'root' } | ||
83 | |||
84 | await makePostBodyRequest({ | ||
85 | url: server.url, | ||
86 | path: registrationPath, | ||
87 | token: server.accessToken, | ||
88 | fields, | ||
89 | expectedStatus: HttpStatusCode.CONFLICT_409 | ||
90 | }) | ||
91 | }) | ||
92 | |||
93 | it('Should fail with a "peertube" username', async function () { | ||
94 | const fields = { ...baseCorrectParams, username: 'peertube' } | ||
95 | |||
96 | await makePostBodyRequest({ | ||
97 | url: server.url, | ||
98 | path: registrationPath, | ||
99 | token: server.accessToken, | ||
100 | fields, | ||
101 | expectedStatus: HttpStatusCode.CONFLICT_409 | ||
102 | }) | ||
103 | }) | ||
104 | |||
105 | it('Should fail if we register a user with the same email', async function () { | ||
106 | const fields = { ...baseCorrectParams, email: 'admin' + server.internalServerNumber + '@example.com' } | ||
107 | |||
108 | await makePostBodyRequest({ | ||
109 | url: server.url, | ||
110 | path: registrationPath, | ||
111 | token: server.accessToken, | ||
112 | fields, | ||
113 | expectedStatus: HttpStatusCode.CONFLICT_409 | ||
114 | }) | ||
115 | }) | ||
116 | |||
117 | it('Should fail with a bad display name', async function () { | ||
118 | const fields = { ...baseCorrectParams, displayName: 'a'.repeat(150) } | ||
119 | |||
120 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
121 | }) | ||
122 | |||
123 | it('Should fail with a bad channel name', async function () { | ||
124 | const fields = { ...baseCorrectParams, channel: { name: '[]azf', displayName: 'toto' } } | ||
125 | |||
126 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
127 | }) | ||
128 | |||
129 | it('Should fail with a bad channel display name', async function () { | ||
130 | const fields = { ...baseCorrectParams, channel: { name: 'toto', displayName: '' } } | ||
131 | |||
132 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
133 | }) | ||
134 | |||
135 | it('Should fail with a channel name that is the same as username', async function () { | ||
136 | const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } } | ||
137 | const fields = { ...baseCorrectParams, ...source } | ||
138 | |||
139 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | ||
140 | }) | ||
141 | |||
142 | it('Should fail with an existing channel', async function () { | ||
143 | const attributes = { name: 'existing_channel', displayName: 'hello', description: 'super description' } | ||
144 | await server.channels.create({ attributes }) | ||
145 | |||
146 | const fields = { ...baseCorrectParams, channel: { name: 'existing_channel', displayName: 'toto' } } | ||
147 | |||
148 | await makePostBodyRequest({ | ||
149 | url: server.url, | ||
150 | path: registrationPath, | ||
151 | token: server.accessToken, | ||
152 | fields, | ||
153 | expectedStatus: HttpStatusCode.CONFLICT_409 | ||
154 | }) | ||
155 | }) | ||
156 | |||
157 | it('Should succeed with the correct params', async function () { | ||
158 | const fields = { ...baseCorrectParams, channel: { name: 'super_channel', displayName: 'toto' } } | ||
159 | |||
160 | await makePostBodyRequest({ | ||
161 | url: server.url, | ||
162 | path: registrationPath, | ||
163 | token: server.accessToken, | ||
164 | fields, | ||
165 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
166 | }) | ||
167 | }) | ||
168 | |||
169 | it('Should fail on a server with registration disabled', async function () { | ||
170 | const fields = { | ||
171 | username: 'user4', | ||
172 | email: 'test4@example.com', | ||
173 | password: 'my super password 4' | ||
174 | } | ||
175 | |||
176 | await makePostBodyRequest({ | ||
177 | url: serverWithRegistrationDisabled.url, | ||
178 | path: registrationPath, | ||
179 | token: serverWithRegistrationDisabled.accessToken, | ||
180 | fields, | ||
181 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
182 | }) | ||
183 | }) | ||
184 | }) | ||
185 | |||
186 | describe('When registering multiple users on a server with users limit', function () { | ||
187 | |||
188 | it('Should fail when after 3 registrations', async function () { | ||
189 | await server.users.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
190 | }) | ||
191 | |||
192 | }) | ||
193 | |||
194 | describe('When asking a password reset', function () { | ||
195 | const path = '/api/v1/users/ask-reset-password' | ||
196 | |||
197 | it('Should fail with a missing email', async function () { | ||
198 | const fields = {} | ||
199 | |||
200 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
201 | }) | ||
202 | |||
203 | it('Should fail with an invalid email', async function () { | ||
204 | const fields = { email: 'hello' } | ||
205 | |||
206 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
207 | }) | ||
208 | |||
209 | it('Should success with the correct params', async function () { | ||
210 | const fields = { email: 'admin@example.com' } | ||
211 | |||
212 | await makePostBodyRequest({ | ||
213 | url: server.url, | ||
214 | path, | ||
215 | token: server.accessToken, | ||
216 | fields, | ||
217 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
218 | }) | ||
219 | }) | ||
220 | }) | ||
221 | |||
222 | describe('When asking for an account verification email', function () { | ||
223 | const path = '/api/v1/users/ask-send-verify-email' | ||
224 | |||
225 | it('Should fail with a missing email', async function () { | ||
226 | const fields = {} | ||
227 | |||
228 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
229 | }) | ||
230 | |||
231 | it('Should fail with an invalid email', async function () { | ||
232 | const fields = { email: 'hello' } | ||
233 | |||
234 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
235 | }) | ||
236 | |||
237 | it('Should succeed with the correct params', async function () { | ||
238 | const fields = { email: 'admin@example.com' } | ||
239 | |||
240 | await makePostBodyRequest({ | ||
241 | url: server.url, | ||
242 | path, | ||
243 | token: server.accessToken, | ||
244 | fields, | ||
245 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
246 | }) | ||
247 | }) | ||
248 | }) | ||
249 | |||
250 | after(async function () { | ||
251 | MockSmtpServer.Instance.kill() | ||
252 | |||
253 | await cleanupTests([ server, serverWithRegistrationDisabled ]) | ||
254 | }) | ||
255 | }) | ||
diff --git a/server/tests/api/notifications/index.ts b/server/tests/api/notifications/index.ts index 8caa30a3d..c0216b74f 100644 --- a/server/tests/api/notifications/index.ts +++ b/server/tests/api/notifications/index.ts | |||
@@ -2,4 +2,5 @@ import './admin-notifications' | |||
2 | import './comments-notifications' | 2 | import './comments-notifications' |
3 | import './moderation-notifications' | 3 | import './moderation-notifications' |
4 | import './notifications-api' | 4 | import './notifications-api' |
5 | import './registrations-notifications' | ||
5 | import './user-notifications' | 6 | import './user-notifications' |
diff --git a/server/tests/api/notifications/moderation-notifications.ts b/server/tests/api/notifications/moderation-notifications.ts index c7b9b5fb0..bb11a08aa 100644 --- a/server/tests/api/notifications/moderation-notifications.ts +++ b/server/tests/api/notifications/moderation-notifications.ts | |||
@@ -11,7 +11,6 @@ import { | |||
11 | checkNewInstanceFollower, | 11 | checkNewInstanceFollower, |
12 | checkNewVideoAbuseForModerators, | 12 | checkNewVideoAbuseForModerators, |
13 | checkNewVideoFromSubscription, | 13 | checkNewVideoFromSubscription, |
14 | checkUserRegistered, | ||
15 | checkVideoAutoBlacklistForModerators, | 14 | checkVideoAutoBlacklistForModerators, |
16 | checkVideoIsPublished, | 15 | checkVideoIsPublished, |
17 | MockInstancesIndex, | 16 | MockInstancesIndex, |
@@ -327,32 +326,6 @@ describe('Test moderation notifications', function () { | |||
327 | }) | 326 | }) |
328 | }) | 327 | }) |
329 | 328 | ||
330 | describe('New registration', function () { | ||
331 | let baseParams: CheckerBaseParams | ||
332 | |||
333 | before(() => { | ||
334 | baseParams = { | ||
335 | server: servers[0], | ||
336 | emails, | ||
337 | socketNotifications: adminNotifications, | ||
338 | token: servers[0].accessToken | ||
339 | } | ||
340 | }) | ||
341 | |||
342 | it('Should send a notification only to moderators when a user registers on the instance', async function () { | ||
343 | this.timeout(10000) | ||
344 | |||
345 | await servers[0].users.register({ username: 'user_45' }) | ||
346 | |||
347 | await waitJobs(servers) | ||
348 | |||
349 | await checkUserRegistered({ ...baseParams, username: 'user_45', checkType: 'presence' }) | ||
350 | |||
351 | const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } } | ||
352 | await checkUserRegistered({ ...baseParams, ...userOverride, username: 'user_45', checkType: 'absence' }) | ||
353 | }) | ||
354 | }) | ||
355 | |||
356 | describe('New instance follows', function () { | 329 | describe('New instance follows', function () { |
357 | const instanceIndexServer = new MockInstancesIndex() | 330 | const instanceIndexServer = new MockInstancesIndex() |
358 | let config: any | 331 | let config: any |
diff --git a/server/tests/api/notifications/registrations-notifications.ts b/server/tests/api/notifications/registrations-notifications.ts new file mode 100644 index 000000000..b5a7c2bb5 --- /dev/null +++ b/server/tests/api/notifications/registrations-notifications.ts | |||
@@ -0,0 +1,88 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { | ||
4 | CheckerBaseParams, | ||
5 | checkRegistrationRequest, | ||
6 | checkUserRegistered, | ||
7 | MockSmtpServer, | ||
8 | prepareNotificationsTest | ||
9 | } from '@server/tests/shared' | ||
10 | import { UserNotification } from '@shared/models' | ||
11 | import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands' | ||
12 | |||
13 | describe('Test registrations notifications', function () { | ||
14 | let server: PeerTubeServer | ||
15 | let userToken1: string | ||
16 | |||
17 | let userNotifications: UserNotification[] = [] | ||
18 | let adminNotifications: UserNotification[] = [] | ||
19 | let emails: object[] = [] | ||
20 | |||
21 | let baseParams: CheckerBaseParams | ||
22 | |||
23 | before(async function () { | ||
24 | this.timeout(50000) | ||
25 | |||
26 | const res = await prepareNotificationsTest(1) | ||
27 | |||
28 | server = res.servers[0] | ||
29 | emails = res.emails | ||
30 | userToken1 = res.userAccessToken | ||
31 | adminNotifications = res.adminNotifications | ||
32 | userNotifications = res.userNotifications | ||
33 | |||
34 | baseParams = { | ||
35 | server, | ||
36 | emails, | ||
37 | socketNotifications: adminNotifications, | ||
38 | token: server.accessToken | ||
39 | } | ||
40 | }) | ||
41 | |||
42 | describe('New direct registration for moderators', function () { | ||
43 | |||
44 | before(async function () { | ||
45 | await server.config.enableSignup(false) | ||
46 | }) | ||
47 | |||
48 | it('Should send a notification only to moderators when a user registers on the instance', async function () { | ||
49 | this.timeout(50000) | ||
50 | |||
51 | await server.registrations.register({ username: 'user_10' }) | ||
52 | |||
53 | await waitJobs([ server ]) | ||
54 | |||
55 | await checkUserRegistered({ ...baseParams, username: 'user_10', checkType: 'presence' }) | ||
56 | |||
57 | const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } } | ||
58 | await checkUserRegistered({ ...baseParams, ...userOverride, username: 'user_10', checkType: 'absence' }) | ||
59 | }) | ||
60 | }) | ||
61 | |||
62 | describe('New registration request for moderators', function () { | ||
63 | |||
64 | before(async function () { | ||
65 | await server.config.enableSignup(true) | ||
66 | }) | ||
67 | |||
68 | it('Should send a notification on new registration request', async function () { | ||
69 | this.timeout(50000) | ||
70 | |||
71 | const registrationReason = 'my reason' | ||
72 | await server.registrations.requestRegistration({ username: 'user_11', registrationReason }) | ||
73 | |||
74 | await waitJobs([ server ]) | ||
75 | |||
76 | await checkRegistrationRequest({ ...baseParams, username: 'user_11', registrationReason, checkType: 'presence' }) | ||
77 | |||
78 | const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } } | ||
79 | await checkRegistrationRequest({ ...baseParams, ...userOverride, username: 'user_11', registrationReason, checkType: 'absence' }) | ||
80 | }) | ||
81 | }) | ||
82 | |||
83 | after(async function () { | ||
84 | MockSmtpServer.Instance.kill() | ||
85 | |||
86 | await cleanupTests([ server ]) | ||
87 | }) | ||
88 | }) | ||
diff --git a/server/tests/api/server/config-defaults.ts b/server/tests/api/server/config-defaults.ts index 4fa37d0e2..d3b3a2447 100644 --- a/server/tests/api/server/config-defaults.ts +++ b/server/tests/api/server/config-defaults.ts | |||
@@ -149,7 +149,7 @@ describe('Test config defaults', function () { | |||
149 | }) | 149 | }) |
150 | 150 | ||
151 | it('Should register a user with this default setting', async function () { | 151 | it('Should register a user with this default setting', async function () { |
152 | await server.users.register({ username: 'user_p2p_2' }) | 152 | await server.registrations.register({ username: 'user_p2p_2' }) |
153 | 153 | ||
154 | const userToken = await server.login.getAccessToken('user_p2p_2') | 154 | const userToken = await server.login.getAccessToken('user_p2p_2') |
155 | 155 | ||
@@ -194,7 +194,7 @@ describe('Test config defaults', function () { | |||
194 | }) | 194 | }) |
195 | 195 | ||
196 | it('Should register a user with this default setting', async function () { | 196 | it('Should register a user with this default setting', async function () { |
197 | await server.users.register({ username: 'user_p2p_4' }) | 197 | await server.registrations.register({ username: 'user_p2p_4' }) |
198 | 198 | ||
199 | const userToken = await server.login.getAccessToken('user_p2p_4') | 199 | const userToken = await server.login.getAccessToken('user_p2p_4') |
200 | 200 | ||
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index 22446fe0c..b91519660 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -50,6 +50,7 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) { | |||
50 | expect(data.signup.enabled).to.be.true | 50 | expect(data.signup.enabled).to.be.true |
51 | expect(data.signup.limit).to.equal(4) | 51 | expect(data.signup.limit).to.equal(4) |
52 | expect(data.signup.minimumAge).to.equal(16) | 52 | expect(data.signup.minimumAge).to.equal(16) |
53 | expect(data.signup.requiresApproval).to.be.false | ||
53 | expect(data.signup.requiresEmailVerification).to.be.false | 54 | expect(data.signup.requiresEmailVerification).to.be.false |
54 | 55 | ||
55 | expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com') | 56 | expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com') |
@@ -152,6 +153,7 @@ function checkUpdatedConfig (data: CustomConfig) { | |||
152 | 153 | ||
153 | expect(data.signup.enabled).to.be.false | 154 | expect(data.signup.enabled).to.be.false |
154 | expect(data.signup.limit).to.equal(5) | 155 | expect(data.signup.limit).to.equal(5) |
156 | expect(data.signup.requiresApproval).to.be.false | ||
155 | expect(data.signup.requiresEmailVerification).to.be.false | 157 | expect(data.signup.requiresEmailVerification).to.be.false |
156 | expect(data.signup.minimumAge).to.equal(10) | 158 | expect(data.signup.minimumAge).to.equal(10) |
157 | 159 | ||
@@ -285,6 +287,7 @@ const newCustomConfig: CustomConfig = { | |||
285 | signup: { | 287 | signup: { |
286 | enabled: false, | 288 | enabled: false, |
287 | limit: 5, | 289 | limit: 5, |
290 | requiresApproval: false, | ||
288 | requiresEmailVerification: false, | 291 | requiresEmailVerification: false, |
289 | minimumAge: 10 | 292 | minimumAge: 10 |
290 | }, | 293 | }, |
@@ -468,9 +471,9 @@ describe('Test config', function () { | |||
468 | this.timeout(5000) | 471 | this.timeout(5000) |
469 | 472 | ||
470 | await Promise.all([ | 473 | await Promise.all([ |
471 | server.users.register({ username: 'user1' }), | 474 | server.registrations.register({ username: 'user1' }), |
472 | server.users.register({ username: 'user2' }), | 475 | server.registrations.register({ username: 'user2' }), |
473 | server.users.register({ username: 'user3' }) | 476 | server.registrations.register({ username: 'user3' }) |
474 | ]) | 477 | ]) |
475 | 478 | ||
476 | const data = await server.config.getConfig() | 479 | const data = await server.config.getConfig() |
diff --git a/server/tests/api/server/contact-form.ts b/server/tests/api/server/contact-form.ts index 325218008..dd971203a 100644 --- a/server/tests/api/server/contact-form.ts +++ b/server/tests/api/server/contact-form.ts | |||
@@ -6,6 +6,7 @@ import { wait } from '@shared/core-utils' | |||
6 | import { HttpStatusCode } from '@shared/models' | 6 | import { HttpStatusCode } from '@shared/models' |
7 | import { | 7 | import { |
8 | cleanupTests, | 8 | cleanupTests, |
9 | ConfigCommand, | ||
9 | ContactFormCommand, | 10 | ContactFormCommand, |
10 | createSingleServer, | 11 | createSingleServer, |
11 | PeerTubeServer, | 12 | PeerTubeServer, |
@@ -23,13 +24,7 @@ describe('Test contact form', function () { | |||
23 | 24 | ||
24 | const port = await MockSmtpServer.Instance.collectEmails(emails) | 25 | const port = await MockSmtpServer.Instance.collectEmails(emails) |
25 | 26 | ||
26 | const overrideConfig = { | 27 | server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(port)) |
27 | smtp: { | ||
28 | hostname: '127.0.0.1', | ||
29 | port | ||
30 | } | ||
31 | } | ||
32 | server = await createSingleServer(1, overrideConfig) | ||
33 | await setAccessTokensToServers([ server ]) | 28 | await setAccessTokensToServers([ server ]) |
34 | 29 | ||
35 | command = server.contactForm | 30 | command = server.contactForm |
diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts index 4ab5463fe..db7aa65bd 100644 --- a/server/tests/api/server/email.ts +++ b/server/tests/api/server/email.ts | |||
@@ -3,7 +3,14 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { MockSmtpServer } from '@server/tests/shared' | 4 | import { MockSmtpServer } from '@server/tests/shared' |
5 | import { HttpStatusCode } from '@shared/models' | 5 | import { HttpStatusCode } from '@shared/models' |
6 | import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands' | 6 | import { |
7 | cleanupTests, | ||
8 | ConfigCommand, | ||
9 | createSingleServer, | ||
10 | PeerTubeServer, | ||
11 | setAccessTokensToServers, | ||
12 | waitJobs | ||
13 | } from '@shared/server-commands' | ||
7 | 14 | ||
8 | describe('Test emails', function () { | 15 | describe('Test emails', function () { |
9 | let server: PeerTubeServer | 16 | let server: PeerTubeServer |
@@ -24,21 +31,15 @@ describe('Test emails', function () { | |||
24 | username: 'user_1', | 31 | username: 'user_1', |
25 | password: 'super_password' | 32 | password: 'super_password' |
26 | } | 33 | } |
27 | let emailPort: number | ||
28 | 34 | ||
29 | before(async function () { | 35 | before(async function () { |
30 | this.timeout(50000) | 36 | this.timeout(50000) |
31 | 37 | ||
32 | emailPort = await MockSmtpServer.Instance.collectEmails(emails) | 38 | const emailPort = await MockSmtpServer.Instance.collectEmails(emails) |
39 | server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(emailPort)) | ||
33 | 40 | ||
34 | const overrideConfig = { | ||
35 | smtp: { | ||
36 | hostname: '127.0.0.1', | ||
37 | port: emailPort | ||
38 | } | ||
39 | } | ||
40 | server = await createSingleServer(1, overrideConfig) | ||
41 | await setAccessTokensToServers([ server ]) | 41 | await setAccessTokensToServers([ server ]) |
42 | await server.config.enableSignup(true) | ||
42 | 43 | ||
43 | { | 44 | { |
44 | const created = await server.users.create({ username: user.username, password: user.password }) | 45 | const created = await server.users.create({ username: user.username, password: user.password }) |
@@ -322,6 +323,62 @@ describe('Test emails', function () { | |||
322 | }) | 323 | }) |
323 | }) | 324 | }) |
324 | 325 | ||
326 | describe('When verifying a registration email', function () { | ||
327 | let registrationId: number | ||
328 | let registrationIdEmail: number | ||
329 | |||
330 | before(async function () { | ||
331 | const { id } = await server.registrations.requestRegistration({ | ||
332 | username: 'request_1', | ||
333 | email: 'request_1@example.com', | ||
334 | registrationReason: 'tt' | ||
335 | }) | ||
336 | registrationId = id | ||
337 | }) | ||
338 | |||
339 | it('Should ask to send the verification email', async function () { | ||
340 | this.timeout(10000) | ||
341 | |||
342 | await server.registrations.askSendVerifyEmail({ email: 'request_1@example.com' }) | ||
343 | |||
344 | await waitJobs(server) | ||
345 | expect(emails).to.have.lengthOf(9) | ||
346 | |||
347 | const email = emails[8] | ||
348 | |||
349 | expect(email['from'][0]['name']).equal('PeerTube') | ||
350 | expect(email['from'][0]['address']).equal('test-admin@127.0.0.1') | ||
351 | expect(email['to'][0]['address']).equal('request_1@example.com') | ||
352 | expect(email['subject']).contains('Verify') | ||
353 | |||
354 | const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text']) | ||
355 | expect(verificationStringMatches).not.to.be.null | ||
356 | |||
357 | verificationString = verificationStringMatches[1] | ||
358 | expect(verificationString).to.not.be.undefined | ||
359 | expect(verificationString).to.have.length.above(2) | ||
360 | |||
361 | const registrationIdMatches = /registrationId=([0-9]+)/.exec(email['text']) | ||
362 | expect(registrationIdMatches).not.to.be.null | ||
363 | |||
364 | registrationIdEmail = parseInt(registrationIdMatches[1], 10) | ||
365 | |||
366 | expect(registrationId).to.equal(registrationIdEmail) | ||
367 | }) | ||
368 | |||
369 | it('Should not verify the email with an invalid verification string', async function () { | ||
370 | await server.registrations.verifyEmail({ | ||
371 | registrationId: registrationIdEmail, | ||
372 | verificationString: verificationString + 'b', | ||
373 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
374 | }) | ||
375 | }) | ||
376 | |||
377 | it('Should verify the email', async function () { | ||
378 | await server.registrations.verifyEmail({ registrationId: registrationIdEmail, verificationString }) | ||
379 | }) | ||
380 | }) | ||
381 | |||
325 | after(async function () { | 382 | after(async function () { |
326 | MockSmtpServer.Instance.kill() | 383 | MockSmtpServer.Instance.kill() |
327 | 384 | ||
diff --git a/server/tests/api/server/reverse-proxy.ts b/server/tests/api/server/reverse-proxy.ts index d882f0bde..11c96c4b5 100644 --- a/server/tests/api/server/reverse-proxy.ts +++ b/server/tests/api/server/reverse-proxy.ts | |||
@@ -106,13 +106,13 @@ describe('Test application behind a reverse proxy', function () { | |||
106 | it('Should rate limit signup', async function () { | 106 | it('Should rate limit signup', async function () { |
107 | for (let i = 0; i < 10; i++) { | 107 | for (let i = 0; i < 10; i++) { |
108 | try { | 108 | try { |
109 | await server.users.register({ username: 'test' + i }) | 109 | await server.registrations.register({ username: 'test' + i }) |
110 | } catch { | 110 | } catch { |
111 | // empty | 111 | // empty |
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | await server.users.register({ username: 'test42', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 }) | 115 | await server.registrations.register({ username: 'test42', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 }) |
116 | }) | 116 | }) |
117 | 117 | ||
118 | it('Should not rate limit failed signup', async function () { | 118 | it('Should not rate limit failed signup', async function () { |
@@ -121,10 +121,10 @@ describe('Test application behind a reverse proxy', function () { | |||
121 | await wait(7000) | 121 | await wait(7000) |
122 | 122 | ||
123 | for (let i = 0; i < 3; i++) { | 123 | for (let i = 0; i < 3; i++) { |
124 | await server.users.register({ username: 'test' + i, expectedStatus: HttpStatusCode.CONFLICT_409 }) | 124 | await server.registrations.register({ username: 'test' + i, expectedStatus: HttpStatusCode.CONFLICT_409 }) |
125 | } | 125 | } |
126 | 126 | ||
127 | await server.users.register({ username: 'test43', expectedStatus: HttpStatusCode.NO_CONTENT_204 }) | 127 | await server.registrations.register({ username: 'test43', expectedStatus: HttpStatusCode.NO_CONTENT_204 }) |
128 | 128 | ||
129 | }) | 129 | }) |
130 | 130 | ||
diff --git a/server/tests/api/users/index.ts b/server/tests/api/users/index.ts index 0313845ef..a4443a8ec 100644 --- a/server/tests/api/users/index.ts +++ b/server/tests/api/users/index.ts | |||
@@ -1,7 +1,8 @@ | |||
1 | import './oauth' | 1 | import './oauth' |
2 | import './registrations`' | ||
2 | import './two-factor' | 3 | import './two-factor' |
3 | import './user-subscriptions' | 4 | import './user-subscriptions' |
4 | import './user-videos' | 5 | import './user-videos' |
5 | import './users' | 6 | import './users' |
6 | import './users-multiple-servers' | 7 | import './users-multiple-servers' |
7 | import './users-verification' | 8 | import './users-email-verification' |
diff --git a/server/tests/api/users/registrations.ts b/server/tests/api/users/registrations.ts new file mode 100644 index 000000000..a9e1114e8 --- /dev/null +++ b/server/tests/api/users/registrations.ts | |||
@@ -0,0 +1,379 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { MockSmtpServer } from '@server/tests/shared' | ||
5 | import { UserRegistrationState, UserRole } from '@shared/models' | ||
6 | import { | ||
7 | cleanupTests, | ||
8 | ConfigCommand, | ||
9 | createSingleServer, | ||
10 | PeerTubeServer, | ||
11 | setAccessTokensToServers, | ||
12 | waitJobs | ||
13 | } from '@shared/server-commands' | ||
14 | |||
15 | describe('Test registrations', function () { | ||
16 | let server: PeerTubeServer | ||
17 | |||
18 | const emails: object[] = [] | ||
19 | let emailPort: number | ||
20 | |||
21 | before(async function () { | ||
22 | this.timeout(30000) | ||
23 | |||
24 | emailPort = await MockSmtpServer.Instance.collectEmails(emails) | ||
25 | |||
26 | server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(emailPort)) | ||
27 | |||
28 | await setAccessTokensToServers([ server ]) | ||
29 | await server.config.enableSignup(false) | ||
30 | }) | ||
31 | |||
32 | describe('Direct registrations of a new user', function () { | ||
33 | let user1Token: string | ||
34 | |||
35 | it('Should register a new user', async function () { | ||
36 | const user = { displayName: 'super user 1', username: 'user_1', password: 'my super password' } | ||
37 | const channel = { name: 'my_user_1_channel', displayName: 'my channel rocks' } | ||
38 | |||
39 | await server.registrations.register({ ...user, channel }) | ||
40 | }) | ||
41 | |||
42 | it('Should be able to login with this registered user', async function () { | ||
43 | const user1 = { username: 'user_1', password: 'my super password' } | ||
44 | |||
45 | user1Token = await server.login.getAccessToken(user1) | ||
46 | }) | ||
47 | |||
48 | it('Should have the correct display name', async function () { | ||
49 | const user = await server.users.getMyInfo({ token: user1Token }) | ||
50 | expect(user.account.displayName).to.equal('super user 1') | ||
51 | }) | ||
52 | |||
53 | it('Should have the correct video quota', async function () { | ||
54 | const user = await server.users.getMyInfo({ token: user1Token }) | ||
55 | expect(user.videoQuota).to.equal(5 * 1024 * 1024) | ||
56 | }) | ||
57 | |||
58 | it('Should have created the channel', async function () { | ||
59 | const { displayName } = await server.channels.get({ channelName: 'my_user_1_channel' }) | ||
60 | |||
61 | expect(displayName).to.equal('my channel rocks') | ||
62 | }) | ||
63 | |||
64 | it('Should remove me', async function () { | ||
65 | { | ||
66 | const { data } = await server.users.list() | ||
67 | expect(data.find(u => u.username === 'user_1')).to.not.be.undefined | ||
68 | } | ||
69 | |||
70 | await server.users.deleteMe({ token: user1Token }) | ||
71 | |||
72 | { | ||
73 | const { data } = await server.users.list() | ||
74 | expect(data.find(u => u.username === 'user_1')).to.be.undefined | ||
75 | } | ||
76 | }) | ||
77 | }) | ||
78 | |||
79 | describe('Registration requests', function () { | ||
80 | let id2: number | ||
81 | let id3: number | ||
82 | let id4: number | ||
83 | |||
84 | let user2Token: string | ||
85 | let user3Token: string | ||
86 | |||
87 | before(async function () { | ||
88 | this.timeout(60000) | ||
89 | |||
90 | await server.config.enableSignup(true) | ||
91 | |||
92 | { | ||
93 | const { id } = await server.registrations.requestRegistration({ | ||
94 | username: 'user4', | ||
95 | registrationReason: 'registration reason 4' | ||
96 | }) | ||
97 | |||
98 | id4 = id | ||
99 | } | ||
100 | }) | ||
101 | |||
102 | it('Should request a registration without a channel', async function () { | ||
103 | { | ||
104 | const { id } = await server.registrations.requestRegistration({ | ||
105 | username: 'user2', | ||
106 | displayName: 'my super user 2', | ||
107 | email: 'user2@example.com', | ||
108 | password: 'user2password', | ||
109 | registrationReason: 'registration reason 2' | ||
110 | }) | ||
111 | |||
112 | id2 = id | ||
113 | } | ||
114 | }) | ||
115 | |||
116 | it('Should request a registration with a channel', async function () { | ||
117 | const { id } = await server.registrations.requestRegistration({ | ||
118 | username: 'user3', | ||
119 | displayName: 'my super user 3', | ||
120 | channel: { | ||
121 | displayName: 'my user 3 channel', | ||
122 | name: 'super_user3_channel' | ||
123 | }, | ||
124 | email: 'user3@example.com', | ||
125 | password: 'user3password', | ||
126 | registrationReason: 'registration reason 3' | ||
127 | }) | ||
128 | |||
129 | id3 = id | ||
130 | }) | ||
131 | |||
132 | it('Should list these registration requests', async function () { | ||
133 | { | ||
134 | const { total, data } = await server.registrations.list({ sort: '-createdAt' }) | ||
135 | expect(total).to.equal(3) | ||
136 | expect(data).to.have.lengthOf(3) | ||
137 | |||
138 | { | ||
139 | expect(data[0].id).to.equal(id3) | ||
140 | expect(data[0].username).to.equal('user3') | ||
141 | expect(data[0].accountDisplayName).to.equal('my super user 3') | ||
142 | |||
143 | expect(data[0].channelDisplayName).to.equal('my user 3 channel') | ||
144 | expect(data[0].channelHandle).to.equal('super_user3_channel') | ||
145 | |||
146 | expect(data[0].createdAt).to.exist | ||
147 | expect(data[0].updatedAt).to.exist | ||
148 | |||
149 | expect(data[0].email).to.equal('user3@example.com') | ||
150 | expect(data[0].emailVerified).to.be.null | ||
151 | |||
152 | expect(data[0].moderationResponse).to.be.null | ||
153 | expect(data[0].registrationReason).to.equal('registration reason 3') | ||
154 | expect(data[0].state.id).to.equal(UserRegistrationState.PENDING) | ||
155 | expect(data[0].state.label).to.equal('Pending') | ||
156 | expect(data[0].user).to.be.null | ||
157 | } | ||
158 | |||
159 | { | ||
160 | expect(data[1].id).to.equal(id2) | ||
161 | expect(data[1].username).to.equal('user2') | ||
162 | expect(data[1].accountDisplayName).to.equal('my super user 2') | ||
163 | |||
164 | expect(data[1].channelDisplayName).to.be.null | ||
165 | expect(data[1].channelHandle).to.be.null | ||
166 | |||
167 | expect(data[1].createdAt).to.exist | ||
168 | expect(data[1].updatedAt).to.exist | ||
169 | |||
170 | expect(data[1].email).to.equal('user2@example.com') | ||
171 | expect(data[1].emailVerified).to.be.null | ||
172 | |||
173 | expect(data[1].moderationResponse).to.be.null | ||
174 | expect(data[1].registrationReason).to.equal('registration reason 2') | ||
175 | expect(data[1].state.id).to.equal(UserRegistrationState.PENDING) | ||
176 | expect(data[1].state.label).to.equal('Pending') | ||
177 | expect(data[1].user).to.be.null | ||
178 | } | ||
179 | |||
180 | { | ||
181 | expect(data[2].username).to.equal('user4') | ||
182 | } | ||
183 | } | ||
184 | |||
185 | { | ||
186 | const { total, data } = await server.registrations.list({ count: 1, start: 1, sort: 'createdAt' }) | ||
187 | |||
188 | expect(total).to.equal(3) | ||
189 | expect(data).to.have.lengthOf(1) | ||
190 | expect(data[0].id).to.equal(id2) | ||
191 | } | ||
192 | |||
193 | { | ||
194 | const { total, data } = await server.registrations.list({ search: 'user3' }) | ||
195 | expect(total).to.equal(1) | ||
196 | expect(data).to.have.lengthOf(1) | ||
197 | expect(data[0].id).to.equal(id3) | ||
198 | } | ||
199 | }) | ||
200 | |||
201 | it('Should reject a registration request', async function () { | ||
202 | await server.registrations.reject({ id: id4, moderationResponse: 'I do not want id 4 on this instance' }) | ||
203 | }) | ||
204 | |||
205 | it('Should have sent an email to the user explanining the registration has been rejected', async function () { | ||
206 | this.timeout(50000) | ||
207 | |||
208 | await waitJobs([ server ]) | ||
209 | |||
210 | const email = emails.find(e => e['to'][0]['address'] === 'user4@example.com') | ||
211 | expect(email).to.exist | ||
212 | |||
213 | expect(email['subject']).to.contain('been rejected') | ||
214 | expect(email['text']).to.contain('been rejected') | ||
215 | expect(email['text']).to.contain('I do not want id 4 on this instance') | ||
216 | }) | ||
217 | |||
218 | it('Should accept registration requests', async function () { | ||
219 | await server.registrations.accept({ id: id2, moderationResponse: 'Welcome id 2' }) | ||
220 | await server.registrations.accept({ id: id3, moderationResponse: 'Welcome id 3' }) | ||
221 | }) | ||
222 | |||
223 | it('Should have sent an email to the user explanining the registration has been accepted', async function () { | ||
224 | this.timeout(50000) | ||
225 | |||
226 | await waitJobs([ server ]) | ||
227 | |||
228 | { | ||
229 | const email = emails.find(e => e['to'][0]['address'] === 'user2@example.com') | ||
230 | expect(email).to.exist | ||
231 | |||
232 | expect(email['subject']).to.contain('been accepted') | ||
233 | expect(email['text']).to.contain('been accepted') | ||
234 | expect(email['text']).to.contain('Welcome id 2') | ||
235 | } | ||
236 | |||
237 | { | ||
238 | const email = emails.find(e => e['to'][0]['address'] === 'user3@example.com') | ||
239 | expect(email).to.exist | ||
240 | |||
241 | expect(email['subject']).to.contain('been accepted') | ||
242 | expect(email['text']).to.contain('been accepted') | ||
243 | expect(email['text']).to.contain('Welcome id 3') | ||
244 | } | ||
245 | }) | ||
246 | |||
247 | it('Should login with these users', async function () { | ||
248 | user2Token = await server.login.getAccessToken({ username: 'user2', password: 'user2password' }) | ||
249 | user3Token = await server.login.getAccessToken({ username: 'user3', password: 'user3password' }) | ||
250 | }) | ||
251 | |||
252 | it('Should have created the appropriate attributes for user 2', async function () { | ||
253 | const me = await server.users.getMyInfo({ token: user2Token }) | ||
254 | |||
255 | expect(me.username).to.equal('user2') | ||
256 | expect(me.account.displayName).to.equal('my super user 2') | ||
257 | expect(me.videoQuota).to.equal(5 * 1024 * 1024) | ||
258 | expect(me.videoChannels[0].name).to.equal('user2_channel') | ||
259 | expect(me.videoChannels[0].displayName).to.equal('Main user2 channel') | ||
260 | expect(me.role.id).to.equal(UserRole.USER) | ||
261 | expect(me.email).to.equal('user2@example.com') | ||
262 | }) | ||
263 | |||
264 | it('Should have created the appropriate attributes for user 3', async function () { | ||
265 | const me = await server.users.getMyInfo({ token: user3Token }) | ||
266 | |||
267 | expect(me.username).to.equal('user3') | ||
268 | expect(me.account.displayName).to.equal('my super user 3') | ||
269 | expect(me.videoQuota).to.equal(5 * 1024 * 1024) | ||
270 | expect(me.videoChannels[0].name).to.equal('super_user3_channel') | ||
271 | expect(me.videoChannels[0].displayName).to.equal('my user 3 channel') | ||
272 | expect(me.role.id).to.equal(UserRole.USER) | ||
273 | expect(me.email).to.equal('user3@example.com') | ||
274 | }) | ||
275 | |||
276 | it('Should list these accepted/rejected registration requests', async function () { | ||
277 | const { data } = await server.registrations.list({ sort: 'createdAt' }) | ||
278 | const { data: users } = await server.users.list() | ||
279 | |||
280 | { | ||
281 | expect(data[0].id).to.equal(id4) | ||
282 | expect(data[0].state.id).to.equal(UserRegistrationState.REJECTED) | ||
283 | expect(data[0].state.label).to.equal('Rejected') | ||
284 | |||
285 | expect(data[0].moderationResponse).to.equal('I do not want id 4 on this instance') | ||
286 | expect(data[0].user).to.be.null | ||
287 | |||
288 | expect(users.find(u => u.username === 'user4')).to.not.exist | ||
289 | } | ||
290 | |||
291 | { | ||
292 | expect(data[1].id).to.equal(id2) | ||
293 | expect(data[1].state.id).to.equal(UserRegistrationState.ACCEPTED) | ||
294 | expect(data[1].state.label).to.equal('Accepted') | ||
295 | |||
296 | expect(data[1].moderationResponse).to.equal('Welcome id 2') | ||
297 | expect(data[1].user).to.exist | ||
298 | |||
299 | const user2 = users.find(u => u.username === 'user2') | ||
300 | expect(data[1].user.id).to.equal(user2.id) | ||
301 | } | ||
302 | |||
303 | { | ||
304 | expect(data[2].id).to.equal(id3) | ||
305 | expect(data[2].state.id).to.equal(UserRegistrationState.ACCEPTED) | ||
306 | expect(data[2].state.label).to.equal('Accepted') | ||
307 | |||
308 | expect(data[2].moderationResponse).to.equal('Welcome id 3') | ||
309 | expect(data[2].user).to.exist | ||
310 | |||
311 | const user3 = users.find(u => u.username === 'user3') | ||
312 | expect(data[2].user.id).to.equal(user3.id) | ||
313 | } | ||
314 | }) | ||
315 | |||
316 | it('Shoulde delete a registration', async function () { | ||
317 | await server.registrations.delete({ id: id2 }) | ||
318 | await server.registrations.delete({ id: id3 }) | ||
319 | |||
320 | const { total, data } = await server.registrations.list() | ||
321 | expect(total).to.equal(1) | ||
322 | expect(data).to.have.lengthOf(1) | ||
323 | expect(data[0].id).to.equal(id4) | ||
324 | |||
325 | const { data: users } = await server.users.list() | ||
326 | |||
327 | for (const username of [ 'user2', 'user3' ]) { | ||
328 | expect(users.find(u => u.username === username)).to.exist | ||
329 | } | ||
330 | }) | ||
331 | |||
332 | it('Should request a registration without a channel, that will conflict with an already existing channel', async function () { | ||
333 | let id1: number | ||
334 | let id2: number | ||
335 | |||
336 | { | ||
337 | const { id } = await server.registrations.requestRegistration({ | ||
338 | registrationReason: 'tt', | ||
339 | username: 'user5', | ||
340 | password: 'user5password', | ||
341 | channel: { | ||
342 | displayName: 'channel 6', | ||
343 | name: 'user6_channel' | ||
344 | } | ||
345 | }) | ||
346 | |||
347 | id1 = id | ||
348 | } | ||
349 | |||
350 | { | ||
351 | const { id } = await server.registrations.requestRegistration({ | ||
352 | registrationReason: 'tt', | ||
353 | username: 'user6', | ||
354 | password: 'user6password' | ||
355 | }) | ||
356 | |||
357 | id2 = id | ||
358 | } | ||
359 | |||
360 | await server.registrations.accept({ id: id1, moderationResponse: 'tt' }) | ||
361 | await server.registrations.accept({ id: id2, moderationResponse: 'tt' }) | ||
362 | |||
363 | const user5Token = await server.login.getAccessToken('user5', 'user5password') | ||
364 | const user6Token = await server.login.getAccessToken('user6', 'user6password') | ||
365 | |||
366 | const user5 = await server.users.getMyInfo({ token: user5Token }) | ||
367 | const user6 = await server.users.getMyInfo({ token: user6Token }) | ||
368 | |||
369 | expect(user5.videoChannels[0].name).to.equal('user6_channel') | ||
370 | expect(user6.videoChannels[0].name).to.equal('user6_channel-1') | ||
371 | }) | ||
372 | }) | ||
373 | |||
374 | after(async function () { | ||
375 | MockSmtpServer.Instance.kill() | ||
376 | |||
377 | await cleanupTests([ server ]) | ||
378 | }) | ||
379 | }) | ||
diff --git a/server/tests/api/users/users-verification.ts b/server/tests/api/users/users-email-verification.ts index 19a8df9e1..cb84dc758 100644 --- a/server/tests/api/users/users-verification.ts +++ b/server/tests/api/users/users-email-verification.ts | |||
@@ -3,9 +3,16 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { MockSmtpServer } from '@server/tests/shared' | 4 | import { MockSmtpServer } from '@server/tests/shared' |
5 | import { HttpStatusCode } from '@shared/models' | 5 | import { HttpStatusCode } from '@shared/models' |
6 | import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands' | 6 | import { |
7 | 7 | cleanupTests, | |
8 | describe('Test users account verification', function () { | 8 | ConfigCommand, |
9 | createSingleServer, | ||
10 | PeerTubeServer, | ||
11 | setAccessTokensToServers, | ||
12 | waitJobs | ||
13 | } from '@shared/server-commands' | ||
14 | |||
15 | describe('Test users email verification', function () { | ||
9 | let server: PeerTubeServer | 16 | let server: PeerTubeServer |
10 | let userId: number | 17 | let userId: number |
11 | let userAccessToken: string | 18 | let userAccessToken: string |
@@ -25,14 +32,7 @@ describe('Test users account verification', function () { | |||
25 | this.timeout(30000) | 32 | this.timeout(30000) |
26 | 33 | ||
27 | const port = await MockSmtpServer.Instance.collectEmails(emails) | 34 | const port = await MockSmtpServer.Instance.collectEmails(emails) |
28 | 35 | server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(port)) | |
29 | const overrideConfig = { | ||
30 | smtp: { | ||
31 | hostname: '127.0.0.1', | ||
32 | port | ||
33 | } | ||
34 | } | ||
35 | server = await createSingleServer(1, overrideConfig) | ||
36 | 36 | ||
37 | await setAccessTokensToServers([ server ]) | 37 | await setAccessTokensToServers([ server ]) |
38 | }) | 38 | }) |
@@ -40,17 +40,18 @@ describe('Test users account verification', function () { | |||
40 | it('Should register user and send verification email if verification required', async function () { | 40 | it('Should register user and send verification email if verification required', async function () { |
41 | this.timeout(30000) | 41 | this.timeout(30000) |
42 | 42 | ||
43 | await server.config.updateCustomSubConfig({ | 43 | await server.config.updateExistingSubConfig({ |
44 | newConfig: { | 44 | newConfig: { |
45 | signup: { | 45 | signup: { |
46 | enabled: true, | 46 | enabled: true, |
47 | requiresApproval: false, | ||
47 | requiresEmailVerification: true, | 48 | requiresEmailVerification: true, |
48 | limit: 10 | 49 | limit: 10 |
49 | } | 50 | } |
50 | } | 51 | } |
51 | }) | 52 | }) |
52 | 53 | ||
53 | await server.users.register(user1) | 54 | await server.registrations.register(user1) |
54 | 55 | ||
55 | await waitJobs(server) | 56 | await waitJobs(server) |
56 | expectedEmailsLength++ | 57 | expectedEmailsLength++ |
@@ -127,17 +128,15 @@ describe('Test users account verification', function () { | |||
127 | 128 | ||
128 | it('Should register user not requiring email verification if setting not enabled', async function () { | 129 | it('Should register user not requiring email verification if setting not enabled', async function () { |
129 | this.timeout(5000) | 130 | this.timeout(5000) |
130 | await server.config.updateCustomSubConfig({ | 131 | await server.config.updateExistingSubConfig({ |
131 | newConfig: { | 132 | newConfig: { |
132 | signup: { | 133 | signup: { |
133 | enabled: true, | 134 | requiresEmailVerification: false |
134 | requiresEmailVerification: false, | ||
135 | limit: 10 | ||
136 | } | 135 | } |
137 | } | 136 | } |
138 | }) | 137 | }) |
139 | 138 | ||
140 | await server.users.register(user2) | 139 | await server.registrations.register(user2) |
141 | 140 | ||
142 | await waitJobs(server) | 141 | await waitJobs(server) |
143 | expect(emails).to.have.lengthOf(expectedEmailsLength) | 142 | expect(emails).to.have.lengthOf(expectedEmailsLength) |
@@ -152,9 +151,7 @@ describe('Test users account verification', function () { | |||
152 | await server.config.updateCustomSubConfig({ | 151 | await server.config.updateCustomSubConfig({ |
153 | newConfig: { | 152 | newConfig: { |
154 | signup: { | 153 | signup: { |
155 | enabled: true, | 154 | requiresEmailVerification: true |
156 | requiresEmailVerification: true, | ||
157 | limit: 10 | ||
158 | } | 155 | } |
159 | } | 156 | } |
160 | }) | 157 | }) |
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 93e2e489a..f1e170971 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts | |||
@@ -429,56 +429,6 @@ describe('Test users', function () { | |||
429 | }) | 429 | }) |
430 | }) | 430 | }) |
431 | 431 | ||
432 | describe('Registering a new user', function () { | ||
433 | let user15AccessToken: string | ||
434 | |||
435 | it('Should register a new user', async function () { | ||
436 | const user = { displayName: 'super user 15', username: 'user_15', password: 'my super password' } | ||
437 | const channel = { name: 'my_user_15_channel', displayName: 'my channel rocks' } | ||
438 | |||
439 | await server.users.register({ ...user, channel }) | ||
440 | }) | ||
441 | |||
442 | it('Should be able to login with this registered user', async function () { | ||
443 | const user15 = { | ||
444 | username: 'user_15', | ||
445 | password: 'my super password' | ||
446 | } | ||
447 | |||
448 | user15AccessToken = await server.login.getAccessToken(user15) | ||
449 | }) | ||
450 | |||
451 | it('Should have the correct display name', async function () { | ||
452 | const user = await server.users.getMyInfo({ token: user15AccessToken }) | ||
453 | expect(user.account.displayName).to.equal('super user 15') | ||
454 | }) | ||
455 | |||
456 | it('Should have the correct video quota', async function () { | ||
457 | const user = await server.users.getMyInfo({ token: user15AccessToken }) | ||
458 | expect(user.videoQuota).to.equal(5 * 1024 * 1024) | ||
459 | }) | ||
460 | |||
461 | it('Should have created the channel', async function () { | ||
462 | const { displayName } = await server.channels.get({ channelName: 'my_user_15_channel' }) | ||
463 | |||
464 | expect(displayName).to.equal('my channel rocks') | ||
465 | }) | ||
466 | |||
467 | it('Should remove me', async function () { | ||
468 | { | ||
469 | const { data } = await server.users.list() | ||
470 | expect(data.find(u => u.username === 'user_15')).to.not.be.undefined | ||
471 | } | ||
472 | |||
473 | await server.users.deleteMe({ token: user15AccessToken }) | ||
474 | |||
475 | { | ||
476 | const { data } = await server.users.list() | ||
477 | expect(data.find(u => u.username === 'user_15')).to.be.undefined | ||
478 | } | ||
479 | }) | ||
480 | }) | ||
481 | |||
482 | describe('User blocking', function () { | 432 | describe('User blocking', function () { |
483 | let user16Id: number | 433 | let user16Id: number |
484 | let user16AccessToken: string | 434 | let user16AccessToken: string |
diff --git a/server/tests/external-plugins/akismet.ts b/server/tests/external-plugins/akismet.ts index 974bf0011..e964bf0c2 100644 --- a/server/tests/external-plugins/akismet.ts +++ b/server/tests/external-plugins/akismet.ts | |||
@@ -138,14 +138,14 @@ describe('Official plugin Akismet', function () { | |||
138 | }) | 138 | }) |
139 | 139 | ||
140 | it('Should allow signup', async function () { | 140 | it('Should allow signup', async function () { |
141 | await servers[0].users.register({ | 141 | await servers[0].registrations.register({ |
142 | username: 'user1', | 142 | username: 'user1', |
143 | displayName: 'user 1' | 143 | displayName: 'user 1' |
144 | }) | 144 | }) |
145 | }) | 145 | }) |
146 | 146 | ||
147 | it('Should detect a signup as SPAM', async function () { | 147 | it('Should detect a signup as SPAM', async function () { |
148 | await servers[0].users.register({ | 148 | await servers[0].registrations.register({ |
149 | username: 'user2', | 149 | username: 'user2', |
150 | displayName: 'user 2', | 150 | displayName: 'user 2', |
151 | email: 'akismet-guaranteed-spam@example.com', | 151 | email: 'akismet-guaranteed-spam@example.com', |
diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js index 19ba9f278..5b4d34f15 100644 --- a/server/tests/fixtures/peertube-plugin-test/main.js +++ b/server/tests/fixtures/peertube-plugin-test/main.js | |||
@@ -226,16 +226,29 @@ async function register ({ registerHook, registerSetting, settingsManager, stora | |||
226 | } | 226 | } |
227 | }) | 227 | }) |
228 | 228 | ||
229 | registerHook({ | 229 | { |
230 | target: 'filter:api.user.signup.allowed.result', | 230 | registerHook({ |
231 | handler: (result, params) => { | 231 | target: 'filter:api.user.signup.allowed.result', |
232 | if (params && params.body && params.body.email && params.body.email.includes('jma')) { | 232 | handler: (result, params) => { |
233 | return { allowed: false, errorMessage: 'No jma' } | 233 | if (params && params.body && params.body.email && params.body.email.includes('jma 1')) { |
234 | return { allowed: false, errorMessage: 'No jma 1' } | ||
235 | } | ||
236 | |||
237 | return result | ||
234 | } | 238 | } |
239 | }) | ||
235 | 240 | ||
236 | return result | 241 | registerHook({ |
237 | } | 242 | target: 'filter:api.user.request-signup.allowed.result', |
238 | }) | 243 | handler: (result, params) => { |
244 | if (params && params.body && params.body.email && params.body.email.includes('jma 2')) { | ||
245 | return { allowed: false, errorMessage: 'No jma 2' } | ||
246 | } | ||
247 | |||
248 | return result | ||
249 | } | ||
250 | }) | ||
251 | } | ||
239 | 252 | ||
240 | registerHook({ | 253 | registerHook({ |
241 | target: 'filter:api.download.torrent.allowed.result', | 254 | target: 'filter:api.download.torrent.allowed.result', |
diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts index 36f8052c0..a266ae7f1 100644 --- a/server/tests/plugins/action-hooks.ts +++ b/server/tests/plugins/action-hooks.ts | |||
@@ -153,7 +153,7 @@ describe('Test plugin action hooks', function () { | |||
153 | let userId: number | 153 | let userId: number |
154 | 154 | ||
155 | it('Should run action:api.user.registered', async function () { | 155 | it('Should run action:api.user.registered', async function () { |
156 | await servers[0].users.register({ username: 'registered_user' }) | 156 | await servers[0].registrations.register({ username: 'registered_user' }) |
157 | 157 | ||
158 | await checkHook('action:api.user.registered') | 158 | await checkHook('action:api.user.registered') |
159 | }) | 159 | }) |
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts index 6724b3bf8..37eef6cf3 100644 --- a/server/tests/plugins/filter-hooks.ts +++ b/server/tests/plugins/filter-hooks.ts | |||
@@ -1,7 +1,15 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { HttpStatusCode, VideoDetails, VideoImportState, VideoPlaylist, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models' | 4 | import { |
5 | HttpStatusCode, | ||
6 | PeerTubeProblemDocument, | ||
7 | VideoDetails, | ||
8 | VideoImportState, | ||
9 | VideoPlaylist, | ||
10 | VideoPlaylistPrivacy, | ||
11 | VideoPrivacy | ||
12 | } from '@shared/models' | ||
5 | import { | 13 | import { |
6 | cleanupTests, | 14 | cleanupTests, |
7 | createMultipleServers, | 15 | createMultipleServers, |
@@ -408,23 +416,52 @@ describe('Test plugin filter hooks', function () { | |||
408 | 416 | ||
409 | describe('Should run filter:api.user.signup.allowed.result', function () { | 417 | describe('Should run filter:api.user.signup.allowed.result', function () { |
410 | 418 | ||
419 | before(async function () { | ||
420 | await servers[0].config.updateExistingSubConfig({ newConfig: { signup: { requiresApproval: false } } }) | ||
421 | }) | ||
422 | |||
411 | it('Should run on config endpoint', async function () { | 423 | it('Should run on config endpoint', async function () { |
412 | const body = await servers[0].config.getConfig() | 424 | const body = await servers[0].config.getConfig() |
413 | expect(body.signup.allowed).to.be.true | 425 | expect(body.signup.allowed).to.be.true |
414 | }) | 426 | }) |
415 | 427 | ||
416 | it('Should allow a signup', async function () { | 428 | it('Should allow a signup', async function () { |
417 | await servers[0].users.register({ username: 'john', password: 'password' }) | 429 | await servers[0].registrations.register({ username: 'john1' }) |
418 | }) | 430 | }) |
419 | 431 | ||
420 | it('Should not allow a signup', async function () { | 432 | it('Should not allow a signup', async function () { |
421 | const res = await servers[0].users.register({ | 433 | const res = await servers[0].registrations.register({ |
422 | username: 'jma', | 434 | username: 'jma 1', |
423 | password: 'password', | 435 | expectedStatus: HttpStatusCode.FORBIDDEN_403 |
436 | }) | ||
437 | |||
438 | expect(res.body.error).to.equal('No jma 1') | ||
439 | }) | ||
440 | }) | ||
441 | |||
442 | describe('Should run filter:api.user.request-signup.allowed.result', function () { | ||
443 | |||
444 | before(async function () { | ||
445 | await servers[0].config.updateExistingSubConfig({ newConfig: { signup: { requiresApproval: true } } }) | ||
446 | }) | ||
447 | |||
448 | it('Should run on config endpoint', async function () { | ||
449 | const body = await servers[0].config.getConfig() | ||
450 | expect(body.signup.allowed).to.be.true | ||
451 | }) | ||
452 | |||
453 | it('Should allow a signup request', async function () { | ||
454 | await servers[0].registrations.requestRegistration({ username: 'john2', registrationReason: 'tt' }) | ||
455 | }) | ||
456 | |||
457 | it('Should not allow a signup request', async function () { | ||
458 | const body = await servers[0].registrations.requestRegistration({ | ||
459 | username: 'jma 2', | ||
460 | registrationReason: 'tt', | ||
424 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | 461 | expectedStatus: HttpStatusCode.FORBIDDEN_403 |
425 | }) | 462 | }) |
426 | 463 | ||
427 | expect(res.body.error).to.equal('No jma') | 464 | expect((body as unknown as PeerTubeProblemDocument).error).to.equal('No jma 2') |
428 | }) | 465 | }) |
429 | }) | 466 | }) |
430 | 467 | ||
diff --git a/server/tests/shared/notifications.ts b/server/tests/shared/notifications.ts index e600bd6b2..6c0688d5a 100644 --- a/server/tests/shared/notifications.ts +++ b/server/tests/shared/notifications.ts | |||
@@ -11,6 +11,7 @@ import { | |||
11 | UserNotificationType | 11 | UserNotificationType |
12 | } from '@shared/models' | 12 | } from '@shared/models' |
13 | import { | 13 | import { |
14 | ConfigCommand, | ||
14 | createMultipleServers, | 15 | createMultipleServers, |
15 | doubleFollow, | 16 | doubleFollow, |
16 | PeerTubeServer, | 17 | PeerTubeServer, |
@@ -173,6 +174,8 @@ async function checkMyVideoImportIsFinished (options: CheckerBaseParams & { | |||
173 | await checkNotification({ ...options, notificationChecker, emailNotificationFinder }) | 174 | await checkNotification({ ...options, notificationChecker, emailNotificationFinder }) |
174 | } | 175 | } |
175 | 176 | ||
177 | // --------------------------------------------------------------------------- | ||
178 | |||
176 | async function checkUserRegistered (options: CheckerBaseParams & { | 179 | async function checkUserRegistered (options: CheckerBaseParams & { |
177 | username: string | 180 | username: string |
178 | checkType: CheckerType | 181 | checkType: CheckerType |
@@ -201,6 +204,36 @@ async function checkUserRegistered (options: CheckerBaseParams & { | |||
201 | await checkNotification({ ...options, notificationChecker, emailNotificationFinder }) | 204 | await checkNotification({ ...options, notificationChecker, emailNotificationFinder }) |
202 | } | 205 | } |
203 | 206 | ||
207 | async function checkRegistrationRequest (options: CheckerBaseParams & { | ||
208 | username: string | ||
209 | registrationReason: string | ||
210 | checkType: CheckerType | ||
211 | }) { | ||
212 | const { username, registrationReason } = options | ||
213 | const notificationType = UserNotificationType.NEW_USER_REGISTRATION_REQUEST | ||
214 | |||
215 | function notificationChecker (notification: UserNotification, checkType: CheckerType) { | ||
216 | if (checkType === 'presence') { | ||
217 | expect(notification).to.not.be.undefined | ||
218 | expect(notification.type).to.equal(notificationType) | ||
219 | |||
220 | expect(notification.registration.username).to.equal(username) | ||
221 | } else { | ||
222 | expect(notification).to.satisfy(n => n.type !== notificationType || n.registration.username !== username) | ||
223 | } | ||
224 | } | ||
225 | |||
226 | function emailNotificationFinder (email: object) { | ||
227 | const text: string = email['text'] | ||
228 | |||
229 | return text.includes(' wants to register ') && text.includes(username) && text.includes(registrationReason) | ||
230 | } | ||
231 | |||
232 | await checkNotification({ ...options, notificationChecker, emailNotificationFinder }) | ||
233 | } | ||
234 | |||
235 | // --------------------------------------------------------------------------- | ||
236 | |||
204 | async function checkNewActorFollow (options: CheckerBaseParams & { | 237 | async function checkNewActorFollow (options: CheckerBaseParams & { |
205 | followType: 'channel' | 'account' | 238 | followType: 'channel' | 'account' |
206 | followerName: string | 239 | followerName: string |
@@ -673,10 +706,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an | |||
673 | const port = await MockSmtpServer.Instance.collectEmails(emails) | 706 | const port = await MockSmtpServer.Instance.collectEmails(emails) |
674 | 707 | ||
675 | const overrideConfig = { | 708 | const overrideConfig = { |
676 | smtp: { | 709 | ...ConfigCommand.getEmailOverrideConfig(port), |
677 | hostname: '127.0.0.1', | 710 | |
678 | port | ||
679 | }, | ||
680 | signup: { | 711 | signup: { |
681 | limit: 20 | 712 | limit: 20 |
682 | } | 713 | } |
@@ -735,7 +766,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an | |||
735 | userAccessToken, | 766 | userAccessToken, |
736 | emails, | 767 | emails, |
737 | servers, | 768 | servers, |
738 | channelId | 769 | channelId, |
770 | baseOverrideConfig: overrideConfig | ||
739 | } | 771 | } |
740 | } | 772 | } |
741 | 773 | ||
@@ -765,7 +797,8 @@ export { | |||
765 | checkNewAccountAbuseForModerators, | 797 | checkNewAccountAbuseForModerators, |
766 | checkNewPeerTubeVersion, | 798 | checkNewPeerTubeVersion, |
767 | checkNewPluginVersion, | 799 | checkNewPluginVersion, |
768 | checkVideoStudioEditionIsFinished | 800 | checkVideoStudioEditionIsFinished, |
801 | checkRegistrationRequest | ||
769 | } | 802 | } |
770 | 803 | ||
771 | // --------------------------------------------------------------------------- | 804 | // --------------------------------------------------------------------------- |
diff --git a/shared/server-commands/server/config-command.ts b/shared/server-commands/server/config-command.ts index 1c2315ed1..51267b85b 100644 --- a/shared/server-commands/server/config-command.ts +++ b/shared/server-commands/server/config-command.ts | |||
@@ -18,6 +18,33 @@ export class ConfigCommand extends AbstractCommand { | |||
18 | } | 18 | } |
19 | } | 19 | } |
20 | 20 | ||
21 | // --------------------------------------------------------------------------- | ||
22 | |||
23 | static getEmailOverrideConfig (emailPort: number) { | ||
24 | return { | ||
25 | smtp: { | ||
26 | hostname: '127.0.0.1', | ||
27 | port: emailPort | ||
28 | } | ||
29 | } | ||
30 | } | ||
31 | |||
32 | // --------------------------------------------------------------------------- | ||
33 | |||
34 | enableSignup (requiresApproval: boolean) { | ||
35 | return this.updateExistingSubConfig({ | ||
36 | newConfig: { | ||
37 | signup: { | ||
38 | enabled: true, | ||
39 | requiresApproval, | ||
40 | limit: -1 | ||
41 | } | ||
42 | } | ||
43 | }) | ||
44 | } | ||
45 | |||
46 | // --------------------------------------------------------------------------- | ||
47 | |||
21 | disableImports () { | 48 | disableImports () { |
22 | return this.setImportsEnabled(false) | 49 | return this.setImportsEnabled(false) |
23 | } | 50 | } |
@@ -44,6 +71,16 @@ export class ConfigCommand extends AbstractCommand { | |||
44 | }) | 71 | }) |
45 | } | 72 | } |
46 | 73 | ||
74 | // --------------------------------------------------------------------------- | ||
75 | |||
76 | enableChannelSync () { | ||
77 | return this.setChannelSyncEnabled(true) | ||
78 | } | ||
79 | |||
80 | disableChannelSync () { | ||
81 | return this.setChannelSyncEnabled(false) | ||
82 | } | ||
83 | |||
47 | private setChannelSyncEnabled (enabled: boolean) { | 84 | private setChannelSyncEnabled (enabled: boolean) { |
48 | return this.updateExistingSubConfig({ | 85 | return this.updateExistingSubConfig({ |
49 | newConfig: { | 86 | newConfig: { |
@@ -56,13 +93,7 @@ export class ConfigCommand extends AbstractCommand { | |||
56 | }) | 93 | }) |
57 | } | 94 | } |
58 | 95 | ||
59 | enableChannelSync () { | 96 | // --------------------------------------------------------------------------- |
60 | return this.setChannelSyncEnabled(true) | ||
61 | } | ||
62 | |||
63 | disableChannelSync () { | ||
64 | return this.setChannelSyncEnabled(false) | ||
65 | } | ||
66 | 97 | ||
67 | enableLive (options: { | 98 | enableLive (options: { |
68 | allowReplay?: boolean | 99 | allowReplay?: boolean |
@@ -142,6 +173,8 @@ export class ConfigCommand extends AbstractCommand { | |||
142 | }) | 173 | }) |
143 | } | 174 | } |
144 | 175 | ||
176 | // --------------------------------------------------------------------------- | ||
177 | |||
145 | enableStudio () { | 178 | enableStudio () { |
146 | return this.updateExistingSubConfig({ | 179 | return this.updateExistingSubConfig({ |
147 | newConfig: { | 180 | newConfig: { |
@@ -152,6 +185,8 @@ export class ConfigCommand extends AbstractCommand { | |||
152 | }) | 185 | }) |
153 | } | 186 | } |
154 | 187 | ||
188 | // --------------------------------------------------------------------------- | ||
189 | |||
155 | getConfig (options: OverrideCommandOptions = {}) { | 190 | getConfig (options: OverrideCommandOptions = {}) { |
156 | const path = '/api/v1/config' | 191 | const path = '/api/v1/config' |
157 | 192 | ||
@@ -304,6 +339,7 @@ export class ConfigCommand extends AbstractCommand { | |||
304 | signup: { | 339 | signup: { |
305 | enabled: false, | 340 | enabled: false, |
306 | limit: 5, | 341 | limit: 5, |
342 | requiresApproval: true, | ||
307 | requiresEmailVerification: false, | 343 | requiresEmailVerification: false, |
308 | minimumAge: 16 | 344 | minimumAge: 16 |
309 | }, | 345 | }, |
diff --git a/shared/server-commands/server/server.ts b/shared/server-commands/server/server.ts index ae1395a74..793fae3a8 100644 --- a/shared/server-commands/server/server.ts +++ b/shared/server-commands/server/server.ts | |||
@@ -18,6 +18,7 @@ import { | |||
18 | BlocklistCommand, | 18 | BlocklistCommand, |
19 | LoginCommand, | 19 | LoginCommand, |
20 | NotificationsCommand, | 20 | NotificationsCommand, |
21 | RegistrationsCommand, | ||
21 | SubscriptionsCommand, | 22 | SubscriptionsCommand, |
22 | TwoFactorCommand, | 23 | TwoFactorCommand, |
23 | UsersCommand | 24 | UsersCommand |
@@ -147,6 +148,7 @@ export class PeerTubeServer { | |||
147 | views?: ViewsCommand | 148 | views?: ViewsCommand |
148 | twoFactor?: TwoFactorCommand | 149 | twoFactor?: TwoFactorCommand |
149 | videoToken?: VideoTokenCommand | 150 | videoToken?: VideoTokenCommand |
151 | registrations?: RegistrationsCommand | ||
150 | 152 | ||
151 | constructor (options: { serverNumber: number } | { url: string }) { | 153 | constructor (options: { serverNumber: number } | { url: string }) { |
152 | if ((options as any).url) { | 154 | if ((options as any).url) { |
@@ -430,5 +432,6 @@ export class PeerTubeServer { | |||
430 | this.views = new ViewsCommand(this) | 432 | this.views = new ViewsCommand(this) |
431 | this.twoFactor = new TwoFactorCommand(this) | 433 | this.twoFactor = new TwoFactorCommand(this) |
432 | this.videoToken = new VideoTokenCommand(this) | 434 | this.videoToken = new VideoTokenCommand(this) |
435 | this.registrations = new RegistrationsCommand(this) | ||
433 | } | 436 | } |
434 | } | 437 | } |
diff --git a/shared/server-commands/users/index.ts b/shared/server-commands/users/index.ts index 1afc02dc1..404756539 100644 --- a/shared/server-commands/users/index.ts +++ b/shared/server-commands/users/index.ts | |||
@@ -4,6 +4,7 @@ export * from './blocklist-command' | |||
4 | export * from './login' | 4 | export * from './login' |
5 | export * from './login-command' | 5 | export * from './login-command' |
6 | export * from './notifications-command' | 6 | export * from './notifications-command' |
7 | export * from './registrations-command' | ||
7 | export * from './subscriptions-command' | 8 | export * from './subscriptions-command' |
8 | export * from './two-factor-command' | 9 | export * from './two-factor-command' |
9 | export * from './users-command' | 10 | export * from './users-command' |
diff --git a/shared/server-commands/users/registrations-command.ts b/shared/server-commands/users/registrations-command.ts new file mode 100644 index 000000000..4e97571f4 --- /dev/null +++ b/shared/server-commands/users/registrations-command.ts | |||
@@ -0,0 +1,157 @@ | |||
1 | import { pick } from '@shared/core-utils' | ||
2 | import { HttpStatusCode, ResultList, UserRegistration, UserRegistrationRequest } from '@shared/models' | ||
3 | import { unwrapBody } from '../requests' | ||
4 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | ||
5 | |||
6 | export class RegistrationsCommand extends AbstractCommand { | ||
7 | |||
8 | register (options: OverrideCommandOptions & Partial<UserRegistrationRequest> & Pick<UserRegistrationRequest, 'username'>) { | ||
9 | const { password = 'password', email = options.username + '@example.com' } = options | ||
10 | const path = '/api/v1/users/register' | ||
11 | |||
12 | return this.postBodyRequest({ | ||
13 | ...options, | ||
14 | |||
15 | path, | ||
16 | fields: { | ||
17 | ...pick(options, [ 'username', 'displayName', 'channel' ]), | ||
18 | |||
19 | password, | ||
20 | |||
21 | }, | ||
22 | implicitToken: false, | ||
23 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
24 | }) | ||
25 | } | ||
26 | |||
27 | requestRegistration ( | ||
28 | options: OverrideCommandOptions & Partial<UserRegistrationRequest> & Pick<UserRegistrationRequest, 'username' | 'registrationReason'> | ||
29 | ) { | ||
30 | const { password = 'password', email = options.username + '@example.com' } = options | ||
31 | const path = '/api/v1/users/registrations/request' | ||
32 | |||
33 | return unwrapBody<UserRegistration>(this.postBodyRequest({ | ||
34 | ...options, | ||
35 | |||
36 | path, | ||
37 | fields: { | ||
38 | ...pick(options, [ 'username', 'displayName', 'channel', 'registrationReason' ]), | ||
39 | |||
40 | password, | ||
41 | |||
42 | }, | ||
43 | implicitToken: false, | ||
44 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
45 | })) | ||
46 | } | ||
47 | |||
48 | // --------------------------------------------------------------------------- | ||
49 | |||
50 | accept (options: OverrideCommandOptions & { | ||
51 | id: number | ||
52 | moderationResponse: string | ||
53 | }) { | ||
54 | const { id, moderationResponse } = options | ||
55 | const path = '/api/v1/users/registrations/' + id + '/accept' | ||
56 | |||
57 | return this.postBodyRequest({ | ||
58 | ...options, | ||
59 | |||
60 | path, | ||
61 | fields: { moderationResponse }, | ||
62 | implicitToken: true, | ||
63 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
64 | }) | ||
65 | } | ||
66 | |||
67 | reject (options: OverrideCommandOptions & { | ||
68 | id: number | ||
69 | moderationResponse: string | ||
70 | }) { | ||
71 | const { id, moderationResponse } = options | ||
72 | const path = '/api/v1/users/registrations/' + id + '/reject' | ||
73 | |||
74 | return this.postBodyRequest({ | ||
75 | ...options, | ||
76 | |||
77 | path, | ||
78 | fields: { moderationResponse }, | ||
79 | implicitToken: true, | ||
80 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
81 | }) | ||
82 | } | ||
83 | |||
84 | // --------------------------------------------------------------------------- | ||
85 | |||
86 | delete (options: OverrideCommandOptions & { | ||
87 | id: number | ||
88 | }) { | ||
89 | const { id } = options | ||
90 | const path = '/api/v1/users/registrations/' + id | ||
91 | |||
92 | return this.deleteRequest({ | ||
93 | ...options, | ||
94 | |||
95 | path, | ||
96 | implicitToken: true, | ||
97 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
98 | }) | ||
99 | } | ||
100 | |||
101 | // --------------------------------------------------------------------------- | ||
102 | |||
103 | list (options: OverrideCommandOptions & { | ||
104 | start?: number | ||
105 | count?: number | ||
106 | sort?: string | ||
107 | search?: string | ||
108 | } = {}) { | ||
109 | const path = '/api/v1/users/registrations' | ||
110 | |||
111 | return this.getRequestBody<ResultList<UserRegistration>>({ | ||
112 | ...options, | ||
113 | |||
114 | path, | ||
115 | query: pick(options, [ 'start', 'count', 'sort', 'search' ]), | ||
116 | implicitToken: true, | ||
117 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
118 | }) | ||
119 | } | ||
120 | |||
121 | // --------------------------------------------------------------------------- | ||
122 | |||
123 | askSendVerifyEmail (options: OverrideCommandOptions & { | ||
124 | email: string | ||
125 | }) { | ||
126 | const { email } = options | ||
127 | const path = '/api/v1/users/registrations/ask-send-verify-email' | ||
128 | |||
129 | return this.postBodyRequest({ | ||
130 | ...options, | ||
131 | |||
132 | path, | ||
133 | fields: { email }, | ||
134 | implicitToken: false, | ||
135 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
136 | }) | ||
137 | } | ||
138 | |||
139 | verifyEmail (options: OverrideCommandOptions & { | ||
140 | registrationId: number | ||
141 | verificationString: string | ||
142 | }) { | ||
143 | const { registrationId, verificationString } = options | ||
144 | const path = '/api/v1/users/registrations/' + registrationId + '/verify-email' | ||
145 | |||
146 | return this.postBodyRequest({ | ||
147 | ...options, | ||
148 | |||
149 | path, | ||
150 | fields: { | ||
151 | verificationString | ||
152 | }, | ||
153 | implicitToken: false, | ||
154 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
155 | }) | ||
156 | } | ||
157 | } | ||
diff --git a/shared/server-commands/users/users-command.ts b/shared/server-commands/users/users-command.ts index 811b9685b..8a42fafc8 100644 --- a/shared/server-commands/users/users-command.ts +++ b/shared/server-commands/users/users-command.ts | |||
@@ -214,35 +214,6 @@ export class UsersCommand extends AbstractCommand { | |||
214 | return this.server.login.getAccessToken({ username, password }) | 214 | return this.server.login.getAccessToken({ username, password }) |
215 | } | 215 | } |
216 | 216 | ||
217 | register (options: OverrideCommandOptions & { | ||
218 | username: string | ||
219 | password?: string | ||
220 | displayName?: string | ||
221 | email?: string | ||
222 | channel?: { | ||
223 | name: string | ||
224 | displayName: string | ||
225 | } | ||
226 | }) { | ||
227 | const { username, password = 'password', displayName, channel, email = username + '@example.com' } = options | ||
228 | const path = '/api/v1/users/register' | ||
229 | |||
230 | return this.postBodyRequest({ | ||
231 | ...options, | ||
232 | |||
233 | path, | ||
234 | fields: { | ||
235 | username, | ||
236 | password, | ||
237 | email, | ||
238 | displayName, | ||
239 | channel | ||
240 | }, | ||
241 | implicitToken: false, | ||
242 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
243 | }) | ||
244 | } | ||
245 | |||
246 | // --------------------------------------------------------------------------- | 217 | // --------------------------------------------------------------------------- |
247 | 218 | ||
248 | getMyInfo (options: OverrideCommandOptions = {}) { | 219 | getMyInfo (options: OverrideCommandOptions = {}) { |