diff options
author | Chocobozzz <me@florianbigard.com> | 2021-07-13 14:23:01 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-07-20 15:27:18 +0200 |
commit | 7926c5f9b3ffcabb1ffb0dcfa5e48b8e0b88fbc0 (patch) | |
tree | 7a166515e4d57a06eb3c08be569f106ed049988b /shared | |
parent | d0a0fa429d4651710ed951a3c11af0219e408964 (diff) | |
download | PeerTube-7926c5f9b3ffcabb1ffb0dcfa5e48b8e0b88fbc0.tar.gz PeerTube-7926c5f9b3ffcabb1ffb0dcfa5e48b8e0b88fbc0.tar.zst PeerTube-7926c5f9b3ffcabb1ffb0dcfa5e48b8e0b88fbc0.zip |
Introduce user command
Diffstat (limited to 'shared')
-rw-r--r-- | shared/extra-utils/server/servers.ts | 4 | ||||
-rw-r--r-- | shared/extra-utils/users/index.ts | 1 | ||||
-rw-r--r-- | shared/extra-utils/users/login-command.ts | 12 | ||||
-rw-r--r-- | shared/extra-utils/users/notifications.ts | 18 | ||||
-rw-r--r-- | shared/extra-utils/users/users-command.ts | 414 | ||||
-rw-r--r-- | shared/extra-utils/users/users.ts | 400 | ||||
-rw-r--r-- | shared/extra-utils/videos/channels.ts | 6 | ||||
-rw-r--r-- | shared/extra-utils/videos/videos.ts | 4 | ||||
-rw-r--r-- | shared/models/users/index.ts | 1 | ||||
-rw-r--r-- | shared/models/users/user-create-result.model.ts | 7 |
10 files changed, 443 insertions, 424 deletions
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts index 4d9599680..b6d597c5d 100644 --- a/shared/extra-utils/server/servers.ts +++ b/shared/extra-utils/server/servers.ts | |||
@@ -16,7 +16,7 @@ import { AbusesCommand } from '../moderation' | |||
16 | import { OverviewsCommand } from '../overviews' | 16 | import { OverviewsCommand } from '../overviews' |
17 | import { SearchCommand } from '../search' | 17 | import { SearchCommand } from '../search' |
18 | import { SocketIOCommand } from '../socket' | 18 | import { SocketIOCommand } from '../socket' |
19 | import { AccountsCommand, BlocklistCommand, LoginCommand, NotificationsCommand, SubscriptionsCommand } from '../users' | 19 | import { AccountsCommand, BlocklistCommand, LoginCommand, NotificationsCommand, SubscriptionsCommand, UsersCommand } from '../users' |
20 | import { | 20 | import { |
21 | BlacklistCommand, | 21 | BlacklistCommand, |
22 | CaptionsCommand, | 22 | CaptionsCommand, |
@@ -127,6 +127,7 @@ interface ServerInfo { | |||
127 | notificationsCommand?: NotificationsCommand | 127 | notificationsCommand?: NotificationsCommand |
128 | serversCommand?: ServersCommand | 128 | serversCommand?: ServersCommand |
129 | loginCommand?: LoginCommand | 129 | loginCommand?: LoginCommand |
130 | usersCommand?: UsersCommand | ||
130 | } | 131 | } |
131 | 132 | ||
132 | function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) { | 133 | function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) { |
@@ -359,6 +360,7 @@ function assignCommands (server: ServerInfo) { | |||
359 | server.notificationsCommand = new NotificationsCommand(server) | 360 | server.notificationsCommand = new NotificationsCommand(server) |
360 | server.serversCommand = new ServersCommand(server) | 361 | server.serversCommand = new ServersCommand(server) |
361 | server.loginCommand = new LoginCommand(server) | 362 | server.loginCommand = new LoginCommand(server) |
363 | server.usersCommand = new UsersCommand(server) | ||
362 | } | 364 | } |
363 | 365 | ||
364 | async function reRunServer (server: ServerInfo, configOverride?: any) { | 366 | async function reRunServer (server: ServerInfo, configOverride?: any) { |
diff --git a/shared/extra-utils/users/index.ts b/shared/extra-utils/users/index.ts index b200ae705..e6107afa5 100644 --- a/shared/extra-utils/users/index.ts +++ b/shared/extra-utils/users/index.ts | |||
@@ -6,4 +6,5 @@ export * from './login-command' | |||
6 | export * from './notifications' | 6 | export * from './notifications' |
7 | export * from './notifications-command' | 7 | export * from './notifications-command' |
8 | export * from './subscriptions-command' | 8 | export * from './subscriptions-command' |
9 | export * from './users-command' | ||
9 | export * from './users' | 10 | export * from './users' |
diff --git a/shared/extra-utils/users/login-command.ts b/shared/extra-utils/users/login-command.ts index 8af3531f9..b4e3bb602 100644 --- a/shared/extra-utils/users/login-command.ts +++ b/shared/extra-utils/users/login-command.ts | |||
@@ -7,7 +7,7 @@ export class LoginCommand extends AbstractCommand { | |||
7 | 7 | ||
8 | login (options: OverrideCommandOptions & { | 8 | login (options: OverrideCommandOptions & { |
9 | client?: { id?: string, secret?: string } | 9 | client?: { id?: string, secret?: string } |
10 | user?: { username: string, password: string } | 10 | user?: { username: string, password?: string } |
11 | } = {}) { | 11 | } = {}) { |
12 | const { client = this.server.client, user = this.server.user } = options | 12 | const { client = this.server.client, user = this.server.user } = options |
13 | const path = '/api/v1/users/token' | 13 | const path = '/api/v1/users/token' |
@@ -16,7 +16,7 @@ export class LoginCommand extends AbstractCommand { | |||
16 | client_id: client.id, | 16 | client_id: client.id, |
17 | client_secret: client.secret, | 17 | client_secret: client.secret, |
18 | username: user.username, | 18 | username: user.username, |
19 | password: user.password, | 19 | password: user.password ?? 'password', |
20 | response_type: 'code', | 20 | response_type: 'code', |
21 | grant_type: 'password', | 21 | grant_type: 'password', |
22 | scope: 'upload' | 22 | scope: 'upload' |
@@ -33,10 +33,10 @@ export class LoginCommand extends AbstractCommand { | |||
33 | })) | 33 | })) |
34 | } | 34 | } |
35 | 35 | ||
36 | getAccessToken (arg1?: { username: string, password: string }): Promise<string> | 36 | getAccessToken (arg1?: { username: string, password?: string }): Promise<string> |
37 | getAccessToken (arg1: string, password: string): Promise<string> | 37 | getAccessToken (arg1: string, password?: string): Promise<string> |
38 | async getAccessToken (arg1?: { username: string, password: string } | string, password?: string) { | 38 | async getAccessToken (arg1?: { username: string, password?: string } | string, password?: string) { |
39 | let user: { username: string, password: string } | 39 | let user: { username: string, password?: string } |
40 | 40 | ||
41 | if (!arg1) user = this.server.user | 41 | if (!arg1) user = this.server.user |
42 | else if (typeof arg1 === 'object') user = arg1 | 42 | else if (typeof arg1 === 'object') user = arg1 |
diff --git a/shared/extra-utils/users/notifications.ts b/shared/extra-utils/users/notifications.ts index 79cb6f617..0af7d8a18 100644 --- a/shared/extra-utils/users/notifications.ts +++ b/shared/extra-utils/users/notifications.ts | |||
@@ -8,7 +8,6 @@ import { MockSmtpServer } from '../mock-servers/mock-email' | |||
8 | import { doubleFollow } from '../server/follows' | 8 | import { doubleFollow } from '../server/follows' |
9 | import { flushAndRunMultipleServers, ServerInfo } from '../server/servers' | 9 | import { flushAndRunMultipleServers, ServerInfo } from '../server/servers' |
10 | import { setAccessTokensToServers } from './login' | 10 | import { setAccessTokensToServers } from './login' |
11 | import { createUser, getMyUserInformation } from './users' | ||
12 | 11 | ||
13 | function getAllNotificationsSettings (): UserNotificationSetting { | 12 | function getAllNotificationsSettings (): UserNotificationSetting { |
14 | return { | 13 | return { |
@@ -651,17 +650,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an | |||
651 | await doubleFollow(servers[0], servers[1]) | 650 | await doubleFollow(servers[0], servers[1]) |
652 | } | 651 | } |
653 | 652 | ||
654 | const user = { | 653 | const user = { username: 'user_1', password: 'super password' } |
655 | username: 'user_1', | 654 | await servers[0].usersCommand.create({ ...user, videoQuota: 10 * 1000 * 1000 }) |
656 | password: 'super password' | ||
657 | } | ||
658 | await createUser({ | ||
659 | url: servers[0].url, | ||
660 | accessToken: servers[0].accessToken, | ||
661 | username: user.username, | ||
662 | password: user.password, | ||
663 | videoQuota: 10 * 1000 * 1000 | ||
664 | }) | ||
665 | const userAccessToken = await servers[0].loginCommand.getAccessToken(user) | 655 | const userAccessToken = await servers[0].loginCommand.getAccessToken(user) |
666 | 656 | ||
667 | await servers[0].notificationsCommand.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() }) | 657 | await servers[0].notificationsCommand.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() }) |
@@ -685,8 +675,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an | |||
685 | socket.on('new-notification', n => adminNotificationsServer2.push(n)) | 675 | socket.on('new-notification', n => adminNotificationsServer2.push(n)) |
686 | } | 676 | } |
687 | 677 | ||
688 | const resChannel = await getMyUserInformation(servers[0].url, servers[0].accessToken) | 678 | const { videoChannels } = await servers[0].usersCommand.getMyInfo() |
689 | const channelId = resChannel.body.videoChannels[0].id | 679 | const channelId = videoChannels[0].id |
690 | 680 | ||
691 | return { | 681 | return { |
692 | userNotifications, | 682 | userNotifications, |
diff --git a/shared/extra-utils/users/users-command.ts b/shared/extra-utils/users/users-command.ts new file mode 100644 index 000000000..202528b8d --- /dev/null +++ b/shared/extra-utils/users/users-command.ts | |||
@@ -0,0 +1,414 @@ | |||
1 | import { omit, pick } from 'lodash' | ||
2 | import { HttpStatusCode } from '@shared/core-utils' | ||
3 | import { | ||
4 | MyUser, | ||
5 | ResultList, | ||
6 | User, | ||
7 | UserAdminFlag, | ||
8 | UserCreateResult, | ||
9 | UserRole, | ||
10 | UserUpdate, | ||
11 | UserUpdateMe, | ||
12 | UserVideoQuota, | ||
13 | UserVideoRate | ||
14 | } from '@shared/models' | ||
15 | import { ScopedToken } from '@shared/models/users/user-scoped-token' | ||
16 | import { unwrapBody } from '../requests' | ||
17 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | ||
18 | |||
19 | export class UsersCommand extends AbstractCommand { | ||
20 | |||
21 | askResetPassword (options: OverrideCommandOptions & { | ||
22 | email: string | ||
23 | }) { | ||
24 | const { email } = options | ||
25 | const path = '/api/v1/users/ask-reset-password' | ||
26 | |||
27 | return this.postBodyRequest({ | ||
28 | ...options, | ||
29 | |||
30 | path, | ||
31 | fields: { email }, | ||
32 | implicitToken: false, | ||
33 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
34 | }) | ||
35 | } | ||
36 | |||
37 | resetPassword (options: OverrideCommandOptions & { | ||
38 | userId: number | ||
39 | verificationString: string | ||
40 | password: string | ||
41 | }) { | ||
42 | const { userId, verificationString, password } = options | ||
43 | const path = '/api/v1/users/' + userId + '/reset-password' | ||
44 | |||
45 | return this.postBodyRequest({ | ||
46 | ...options, | ||
47 | |||
48 | path, | ||
49 | fields: { password, verificationString }, | ||
50 | implicitToken: false, | ||
51 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
52 | }) | ||
53 | } | ||
54 | |||
55 | // --------------------------------------------------------------------------- | ||
56 | |||
57 | askSendVerifyEmail (options: OverrideCommandOptions & { | ||
58 | email: string | ||
59 | }) { | ||
60 | const { email } = options | ||
61 | const path = '/api/v1/users/ask-send-verify-email' | ||
62 | |||
63 | return this.postBodyRequest({ | ||
64 | ...options, | ||
65 | |||
66 | path, | ||
67 | fields: { email }, | ||
68 | implicitToken: false, | ||
69 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
70 | }) | ||
71 | } | ||
72 | |||
73 | verifyEmail (options: OverrideCommandOptions & { | ||
74 | userId: number | ||
75 | verificationString: string | ||
76 | isPendingEmail?: boolean // default false | ||
77 | }) { | ||
78 | const { userId, verificationString, isPendingEmail = false } = options | ||
79 | const path = '/api/v1/users/' + userId + '/verify-email' | ||
80 | |||
81 | return this.postBodyRequest({ | ||
82 | ...options, | ||
83 | |||
84 | path, | ||
85 | fields: { | ||
86 | verificationString, | ||
87 | isPendingEmail | ||
88 | }, | ||
89 | implicitToken: false, | ||
90 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
91 | }) | ||
92 | } | ||
93 | |||
94 | // --------------------------------------------------------------------------- | ||
95 | |||
96 | banUser (options: OverrideCommandOptions & { | ||
97 | userId: number | ||
98 | reason?: string | ||
99 | }) { | ||
100 | const { userId, reason } = options | ||
101 | const path = '/api/v1/users' + '/' + userId + '/block' | ||
102 | |||
103 | return this.postBodyRequest({ | ||
104 | ...options, | ||
105 | |||
106 | path, | ||
107 | fields: { reason }, | ||
108 | implicitToken: true, | ||
109 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
110 | }) | ||
111 | } | ||
112 | |||
113 | unbanUser (options: OverrideCommandOptions & { | ||
114 | userId: number | ||
115 | }) { | ||
116 | const { userId } = options | ||
117 | const path = '/api/v1/users' + '/' + userId + '/unblock' | ||
118 | |||
119 | return this.postBodyRequest({ | ||
120 | ...options, | ||
121 | |||
122 | path, | ||
123 | implicitToken: true, | ||
124 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
125 | }) | ||
126 | } | ||
127 | |||
128 | // --------------------------------------------------------------------------- | ||
129 | |||
130 | getMyScopedTokens (options: OverrideCommandOptions = {}) { | ||
131 | const path = '/api/v1/users/scoped-tokens' | ||
132 | |||
133 | return this.getRequestBody<ScopedToken>({ | ||
134 | ...options, | ||
135 | |||
136 | path, | ||
137 | implicitToken: true, | ||
138 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
139 | }) | ||
140 | } | ||
141 | |||
142 | renewMyScopedTokens (options: OverrideCommandOptions = {}) { | ||
143 | const path = '/api/v1/users/scoped-tokens' | ||
144 | |||
145 | return this.postBodyRequest({ | ||
146 | ...options, | ||
147 | |||
148 | path, | ||
149 | implicitToken: true, | ||
150 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
151 | }) | ||
152 | } | ||
153 | |||
154 | // --------------------------------------------------------------------------- | ||
155 | |||
156 | create (options: OverrideCommandOptions & { | ||
157 | username: string | ||
158 | password?: string | ||
159 | videoQuota?: number | ||
160 | videoQuotaDaily?: number | ||
161 | role?: UserRole | ||
162 | adminFlags?: UserAdminFlag | ||
163 | }) { | ||
164 | const { | ||
165 | username, | ||
166 | adminFlags, | ||
167 | password = 'password', | ||
168 | videoQuota = 42000000, | ||
169 | videoQuotaDaily = -1, | ||
170 | role = UserRole.USER | ||
171 | } = options | ||
172 | |||
173 | const path = '/api/v1/users' | ||
174 | |||
175 | return unwrapBody<{ user: UserCreateResult }>(this.postBodyRequest({ | ||
176 | ...options, | ||
177 | |||
178 | path, | ||
179 | fields: { | ||
180 | username, | ||
181 | password, | ||
182 | role, | ||
183 | adminFlags, | ||
184 | email: username + '@example.com', | ||
185 | videoQuota, | ||
186 | videoQuotaDaily | ||
187 | }, | ||
188 | implicitToken: true, | ||
189 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
190 | })).then(res => res.user) | ||
191 | } | ||
192 | |||
193 | async generate (username: string) { | ||
194 | const password = 'password' | ||
195 | const user = await this.create({ username, password }) | ||
196 | |||
197 | const token = await this.server.loginCommand.getAccessToken({ username, password }) | ||
198 | |||
199 | const me = await this.getMyInfo({ token }) | ||
200 | |||
201 | return { | ||
202 | token, | ||
203 | userId: user.id, | ||
204 | userChannelId: me.videoChannels[0].id | ||
205 | } | ||
206 | } | ||
207 | |||
208 | async generateUserAndToken (username: string) { | ||
209 | const password = 'password' | ||
210 | await this.create({ username, password }) | ||
211 | |||
212 | return this.server.loginCommand.getAccessToken({ username, password }) | ||
213 | } | ||
214 | |||
215 | register (options: OverrideCommandOptions & { | ||
216 | username: string | ||
217 | password?: string | ||
218 | displayName?: string | ||
219 | channel?: { | ||
220 | name: string | ||
221 | displayName: string | ||
222 | } | ||
223 | }) { | ||
224 | const { username, password = 'password', displayName, channel } = options | ||
225 | const path = '/api/v1/users/register' | ||
226 | |||
227 | return this.postBodyRequest({ | ||
228 | ...options, | ||
229 | |||
230 | path, | ||
231 | fields: { | ||
232 | username, | ||
233 | password, | ||
234 | email: username + '@example.com', | ||
235 | displayName, | ||
236 | channel | ||
237 | }, | ||
238 | implicitToken: false, | ||
239 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
240 | }) | ||
241 | } | ||
242 | |||
243 | // --------------------------------------------------------------------------- | ||
244 | |||
245 | getMyInfo (options: OverrideCommandOptions = {}) { | ||
246 | const path = '/api/v1/users/me' | ||
247 | |||
248 | return this.getRequestBody<MyUser>({ | ||
249 | ...options, | ||
250 | |||
251 | path, | ||
252 | implicitToken: true, | ||
253 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
254 | }) | ||
255 | } | ||
256 | |||
257 | getMyQuotaUsed (options: OverrideCommandOptions = {}) { | ||
258 | const path = '/api/v1/users/me/video-quota-used' | ||
259 | |||
260 | return this.getRequestBody<UserVideoQuota>({ | ||
261 | ...options, | ||
262 | |||
263 | path, | ||
264 | implicitToken: true, | ||
265 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
266 | }) | ||
267 | } | ||
268 | |||
269 | getMyRating (options: OverrideCommandOptions & { | ||
270 | videoId: number | string | ||
271 | }) { | ||
272 | const { videoId } = options | ||
273 | const path = '/api/v1/users/me/videos/' + videoId + '/rating' | ||
274 | |||
275 | return this.getRequestBody<UserVideoRate>({ | ||
276 | ...options, | ||
277 | |||
278 | path, | ||
279 | implicitToken: true, | ||
280 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
281 | }) | ||
282 | } | ||
283 | |||
284 | deleteMe (options: OverrideCommandOptions = {}) { | ||
285 | const path = '/api/v1/users/me' | ||
286 | |||
287 | return this.deleteRequest({ | ||
288 | ...options, | ||
289 | |||
290 | path, | ||
291 | implicitToken: true, | ||
292 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
293 | }) | ||
294 | } | ||
295 | |||
296 | updateMe (options: OverrideCommandOptions & UserUpdateMe) { | ||
297 | const path = '/api/v1/users/me' | ||
298 | |||
299 | const toSend: UserUpdateMe = omit(options, 'url', 'accessToken') | ||
300 | |||
301 | return this.putBodyRequest({ | ||
302 | ...options, | ||
303 | |||
304 | path, | ||
305 | fields: toSend, | ||
306 | implicitToken: true, | ||
307 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
308 | }) | ||
309 | } | ||
310 | |||
311 | updateMyAvatar (options: OverrideCommandOptions & { | ||
312 | fixture: string | ||
313 | }) { | ||
314 | const { fixture } = options | ||
315 | const path = '/api/v1/users/me/avatar/pick' | ||
316 | |||
317 | return this.updateImageRequest({ | ||
318 | ...options, | ||
319 | |||
320 | path, | ||
321 | fixture, | ||
322 | fieldname: 'avatarfile', | ||
323 | |||
324 | implicitToken: true, | ||
325 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
326 | }) | ||
327 | } | ||
328 | |||
329 | // --------------------------------------------------------------------------- | ||
330 | |||
331 | get (options: OverrideCommandOptions & { | ||
332 | userId: number | ||
333 | withStats?: boolean // default false | ||
334 | }) { | ||
335 | const { userId, withStats } = options | ||
336 | const path = '/api/v1/users/' + userId | ||
337 | |||
338 | return this.getRequestBody<User>({ | ||
339 | ...options, | ||
340 | |||
341 | path, | ||
342 | query: { withStats }, | ||
343 | implicitToken: true, | ||
344 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
345 | }) | ||
346 | } | ||
347 | |||
348 | list (options: OverrideCommandOptions & { | ||
349 | start?: number | ||
350 | count?: number | ||
351 | sort?: string | ||
352 | search?: string | ||
353 | blocked?: boolean | ||
354 | } = {}) { | ||
355 | const path = '/api/v1/users' | ||
356 | |||
357 | return this.getRequestBody<ResultList<User>>({ | ||
358 | ...options, | ||
359 | |||
360 | path, | ||
361 | query: pick(options, [ 'start', 'count', 'sort', 'search', 'blocked' ]), | ||
362 | implicitToken: true, | ||
363 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
364 | }) | ||
365 | } | ||
366 | |||
367 | remove (options: OverrideCommandOptions & { | ||
368 | userId: number | ||
369 | }) { | ||
370 | const { userId } = options | ||
371 | const path = '/api/v1/users/' + userId | ||
372 | |||
373 | return this.deleteRequest({ | ||
374 | ...options, | ||
375 | |||
376 | path, | ||
377 | implicitToken: true, | ||
378 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
379 | }) | ||
380 | } | ||
381 | |||
382 | update (options: OverrideCommandOptions & { | ||
383 | userId: number | ||
384 | email?: string | ||
385 | emailVerified?: boolean | ||
386 | videoQuota?: number | ||
387 | videoQuotaDaily?: number | ||
388 | password?: string | ||
389 | adminFlags?: UserAdminFlag | ||
390 | pluginAuth?: string | ||
391 | role?: UserRole | ||
392 | }) { | ||
393 | const path = '/api/v1/users/' + options.userId | ||
394 | |||
395 | const toSend: UserUpdate = {} | ||
396 | if (options.password !== undefined && options.password !== null) toSend.password = options.password | ||
397 | if (options.email !== undefined && options.email !== null) toSend.email = options.email | ||
398 | if (options.emailVerified !== undefined && options.emailVerified !== null) toSend.emailVerified = options.emailVerified | ||
399 | if (options.videoQuota !== undefined && options.videoQuota !== null) toSend.videoQuota = options.videoQuota | ||
400 | if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend.videoQuotaDaily = options.videoQuotaDaily | ||
401 | if (options.role !== undefined && options.role !== null) toSend.role = options.role | ||
402 | if (options.adminFlags !== undefined && options.adminFlags !== null) toSend.adminFlags = options.adminFlags | ||
403 | if (options.pluginAuth !== undefined) toSend.pluginAuth = options.pluginAuth | ||
404 | |||
405 | return this.putBodyRequest({ | ||
406 | ...options, | ||
407 | |||
408 | path, | ||
409 | fields: toSend, | ||
410 | implicitToken: true, | ||
411 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
412 | }) | ||
413 | } | ||
414 | } | ||
diff --git a/shared/extra-utils/users/users.ts b/shared/extra-utils/users/users.ts index 835ad08ba..6cf61d60e 100644 --- a/shared/extra-utils/users/users.ts +++ b/shared/extra-utils/users/users.ts | |||
@@ -1,118 +1,8 @@ | |||
1 | import { omit } from 'lodash' | ||
2 | import * as request from 'supertest' | 1 | import * as request from 'supertest' |
3 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | 2 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' |
4 | import { UserUpdateMe } from '../../models/users' | ||
5 | import { UserAdminFlag } from '../../models/users/user-flag.model' | ||
6 | import { UserRegister } from '../../models/users/user-register.model' | ||
7 | import { UserRole } from '../../models/users/user-role' | ||
8 | import { makeGetRequest, makePostBodyRequest, makePutBodyRequest, updateImageRequest } from '../requests/requests' | ||
9 | import { ServerInfo } from '../server/servers' | ||
10 | 3 | ||
11 | function createUser (parameters: { | 4 | // FIXME: delete once videos does not use it anymore |
12 | url: string | 5 | function xxxgetMyUserInformation (url: string, accessToken: string, specialStatus = HttpStatusCode.OK_200) { |
13 | accessToken: string | ||
14 | username: string | ||
15 | password: string | ||
16 | videoQuota?: number | ||
17 | videoQuotaDaily?: number | ||
18 | role?: UserRole | ||
19 | adminFlags?: UserAdminFlag | ||
20 | specialStatus?: number | ||
21 | }) { | ||
22 | const { | ||
23 | url, | ||
24 | accessToken, | ||
25 | username, | ||
26 | adminFlags, | ||
27 | password = 'password', | ||
28 | videoQuota = 1000000, | ||
29 | videoQuotaDaily = -1, | ||
30 | role = UserRole.USER, | ||
31 | specialStatus = HttpStatusCode.OK_200 | ||
32 | } = parameters | ||
33 | |||
34 | const path = '/api/v1/users' | ||
35 | const body = { | ||
36 | username, | ||
37 | password, | ||
38 | role, | ||
39 | adminFlags, | ||
40 | email: username + '@example.com', | ||
41 | videoQuota, | ||
42 | videoQuotaDaily | ||
43 | } | ||
44 | |||
45 | return request(url) | ||
46 | .post(path) | ||
47 | .set('Accept', 'application/json') | ||
48 | .set('Authorization', 'Bearer ' + accessToken) | ||
49 | .send(body) | ||
50 | .expect(specialStatus) | ||
51 | } | ||
52 | |||
53 | async function generateUser (server: ServerInfo, username: string) { | ||
54 | const password = 'my super password' | ||
55 | const resCreate = await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) | ||
56 | |||
57 | const token = await server.loginCommand.getAccessToken({ username, password }) | ||
58 | |||
59 | const resMe = await getMyUserInformation(server.url, token) | ||
60 | |||
61 | return { | ||
62 | token, | ||
63 | userId: resCreate.body.user.id, | ||
64 | userChannelId: resMe.body.videoChannels[0].id | ||
65 | } | ||
66 | } | ||
67 | |||
68 | async function generateUserAccessToken (server: ServerInfo, username: string) { | ||
69 | const password = 'my super password' | ||
70 | await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) | ||
71 | |||
72 | return server.loginCommand.getAccessToken({ username, password }) | ||
73 | } | ||
74 | |||
75 | function registerUser (url: string, username: string, password: string, specialStatus = HttpStatusCode.NO_CONTENT_204) { | ||
76 | const path = '/api/v1/users/register' | ||
77 | const body = { | ||
78 | username, | ||
79 | password, | ||
80 | email: username + '@example.com' | ||
81 | } | ||
82 | |||
83 | return request(url) | ||
84 | .post(path) | ||
85 | .set('Accept', 'application/json') | ||
86 | .send(body) | ||
87 | .expect(specialStatus) | ||
88 | } | ||
89 | |||
90 | function registerUserWithChannel (options: { | ||
91 | url: string | ||
92 | user: { username: string, password: string, displayName?: string } | ||
93 | channel: { name: string, displayName: string } | ||
94 | }) { | ||
95 | const path = '/api/v1/users/register' | ||
96 | const body: UserRegister = { | ||
97 | username: options.user.username, | ||
98 | password: options.user.password, | ||
99 | email: options.user.username + '@example.com', | ||
100 | channel: options.channel | ||
101 | } | ||
102 | |||
103 | if (options.user.displayName) { | ||
104 | Object.assign(body, { displayName: options.user.displayName }) | ||
105 | } | ||
106 | |||
107 | return makePostBodyRequest({ | ||
108 | url: options.url, | ||
109 | path, | ||
110 | fields: body, | ||
111 | statusCodeExpected: HttpStatusCode.NO_CONTENT_204 | ||
112 | }) | ||
113 | } | ||
114 | |||
115 | function getMyUserInformation (url: string, accessToken: string, specialStatus = HttpStatusCode.OK_200) { | ||
116 | const path = '/api/v1/users/me' | 6 | const path = '/api/v1/users/me' |
117 | 7 | ||
118 | return request(url) | 8 | return request(url) |
@@ -123,292 +13,8 @@ function getMyUserInformation (url: string, accessToken: string, specialStatus = | |||
123 | .expect('Content-Type', /json/) | 13 | .expect('Content-Type', /json/) |
124 | } | 14 | } |
125 | 15 | ||
126 | function getUserScopedTokens (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) { | ||
127 | const path = '/api/v1/users/scoped-tokens' | ||
128 | |||
129 | return makeGetRequest({ | ||
130 | url, | ||
131 | path, | ||
132 | token, | ||
133 | statusCodeExpected | ||
134 | }) | ||
135 | } | ||
136 | |||
137 | function renewUserScopedTokens (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) { | ||
138 | const path = '/api/v1/users/scoped-tokens' | ||
139 | |||
140 | return makePostBodyRequest({ | ||
141 | url, | ||
142 | path, | ||
143 | token, | ||
144 | statusCodeExpected | ||
145 | }) | ||
146 | } | ||
147 | |||
148 | function deleteMe (url: string, accessToken: string, specialStatus = HttpStatusCode.NO_CONTENT_204) { | ||
149 | const path = '/api/v1/users/me' | ||
150 | |||
151 | return request(url) | ||
152 | .delete(path) | ||
153 | .set('Accept', 'application/json') | ||
154 | .set('Authorization', 'Bearer ' + accessToken) | ||
155 | .expect(specialStatus) | ||
156 | } | ||
157 | |||
158 | function getMyUserVideoQuotaUsed (url: string, accessToken: string, specialStatus = HttpStatusCode.OK_200) { | ||
159 | const path = '/api/v1/users/me/video-quota-used' | ||
160 | |||
161 | return request(url) | ||
162 | .get(path) | ||
163 | .set('Accept', 'application/json') | ||
164 | .set('Authorization', 'Bearer ' + accessToken) | ||
165 | .expect(specialStatus) | ||
166 | .expect('Content-Type', /json/) | ||
167 | } | ||
168 | |||
169 | function getUserInformation (url: string, accessToken: string, userId: number, withStats = false) { | ||
170 | const path = '/api/v1/users/' + userId | ||
171 | |||
172 | return request(url) | ||
173 | .get(path) | ||
174 | .query({ withStats }) | ||
175 | .set('Accept', 'application/json') | ||
176 | .set('Authorization', 'Bearer ' + accessToken) | ||
177 | .expect(HttpStatusCode.OK_200) | ||
178 | .expect('Content-Type', /json/) | ||
179 | } | ||
180 | |||
181 | function getMyUserVideoRating (url: string, accessToken: string, videoId: number | string, specialStatus = HttpStatusCode.OK_200) { | ||
182 | const path = '/api/v1/users/me/videos/' + videoId + '/rating' | ||
183 | |||
184 | return request(url) | ||
185 | .get(path) | ||
186 | .set('Accept', 'application/json') | ||
187 | .set('Authorization', 'Bearer ' + accessToken) | ||
188 | .expect(specialStatus) | ||
189 | .expect('Content-Type', /json/) | ||
190 | } | ||
191 | |||
192 | function getUsersList (url: string, accessToken: string) { | ||
193 | const path = '/api/v1/users' | ||
194 | |||
195 | return request(url) | ||
196 | .get(path) | ||
197 | .set('Accept', 'application/json') | ||
198 | .set('Authorization', 'Bearer ' + accessToken) | ||
199 | .expect(HttpStatusCode.OK_200) | ||
200 | .expect('Content-Type', /json/) | ||
201 | } | ||
202 | |||
203 | function getUsersListPaginationAndSort ( | ||
204 | url: string, | ||
205 | accessToken: string, | ||
206 | start: number, | ||
207 | count: number, | ||
208 | sort: string, | ||
209 | search?: string, | ||
210 | blocked?: boolean | ||
211 | ) { | ||
212 | const path = '/api/v1/users' | ||
213 | |||
214 | const query = { | ||
215 | start, | ||
216 | count, | ||
217 | sort, | ||
218 | search, | ||
219 | blocked | ||
220 | } | ||
221 | |||
222 | return request(url) | ||
223 | .get(path) | ||
224 | .query(query) | ||
225 | .set('Accept', 'application/json') | ||
226 | .set('Authorization', 'Bearer ' + accessToken) | ||
227 | .expect(HttpStatusCode.OK_200) | ||
228 | .expect('Content-Type', /json/) | ||
229 | } | ||
230 | |||
231 | function removeUser (url: string, userId: number | string, accessToken: string, expectedStatus = HttpStatusCode.NO_CONTENT_204) { | ||
232 | const path = '/api/v1/users' | ||
233 | |||
234 | return request(url) | ||
235 | .delete(path + '/' + userId) | ||
236 | .set('Accept', 'application/json') | ||
237 | .set('Authorization', 'Bearer ' + accessToken) | ||
238 | .expect(expectedStatus) | ||
239 | } | ||
240 | |||
241 | function blockUser ( | ||
242 | url: string, | ||
243 | userId: number | string, | ||
244 | accessToken: string, | ||
245 | expectedStatus = HttpStatusCode.NO_CONTENT_204, | ||
246 | reason?: string | ||
247 | ) { | ||
248 | const path = '/api/v1/users' | ||
249 | let body: any | ||
250 | if (reason) body = { reason } | ||
251 | |||
252 | return request(url) | ||
253 | .post(path + '/' + userId + '/block') | ||
254 | .send(body) | ||
255 | .set('Accept', 'application/json') | ||
256 | .set('Authorization', 'Bearer ' + accessToken) | ||
257 | .expect(expectedStatus) | ||
258 | } | ||
259 | |||
260 | function unblockUser (url: string, userId: number | string, accessToken: string, expectedStatus = HttpStatusCode.NO_CONTENT_204) { | ||
261 | const path = '/api/v1/users' | ||
262 | |||
263 | return request(url) | ||
264 | .post(path + '/' + userId + '/unblock') | ||
265 | .set('Accept', 'application/json') | ||
266 | .set('Authorization', 'Bearer ' + accessToken) | ||
267 | .expect(expectedStatus) | ||
268 | } | ||
269 | |||
270 | function updateMyUser (options: { url: string, accessToken: string, statusCodeExpected?: HttpStatusCode } & UserUpdateMe) { | ||
271 | const path = '/api/v1/users/me' | ||
272 | |||
273 | const toSend: UserUpdateMe = omit(options, 'url', 'accessToken') | ||
274 | |||
275 | return makePutBodyRequest({ | ||
276 | url: options.url, | ||
277 | path, | ||
278 | token: options.accessToken, | ||
279 | fields: toSend, | ||
280 | statusCodeExpected: options.statusCodeExpected || HttpStatusCode.NO_CONTENT_204 | ||
281 | }) | ||
282 | } | ||
283 | |||
284 | function updateMyAvatar (options: { | ||
285 | url: string | ||
286 | accessToken: string | ||
287 | fixture: string | ||
288 | }) { | ||
289 | const path = '/api/v1/users/me/avatar/pick' | ||
290 | |||
291 | return updateImageRequest({ ...options, path, fieldname: 'avatarfile' }) | ||
292 | } | ||
293 | |||
294 | function updateUser (options: { | ||
295 | url: string | ||
296 | userId: number | ||
297 | accessToken: string | ||
298 | email?: string | ||
299 | emailVerified?: boolean | ||
300 | videoQuota?: number | ||
301 | videoQuotaDaily?: number | ||
302 | password?: string | ||
303 | adminFlags?: UserAdminFlag | ||
304 | pluginAuth?: string | ||
305 | role?: UserRole | ||
306 | }) { | ||
307 | const path = '/api/v1/users/' + options.userId | ||
308 | |||
309 | const toSend = {} | ||
310 | if (options.password !== undefined && options.password !== null) toSend['password'] = options.password | ||
311 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email | ||
312 | if (options.emailVerified !== undefined && options.emailVerified !== null) toSend['emailVerified'] = options.emailVerified | ||
313 | if (options.videoQuota !== undefined && options.videoQuota !== null) toSend['videoQuota'] = options.videoQuota | ||
314 | if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend['videoQuotaDaily'] = options.videoQuotaDaily | ||
315 | if (options.role !== undefined && options.role !== null) toSend['role'] = options.role | ||
316 | if (options.adminFlags !== undefined && options.adminFlags !== null) toSend['adminFlags'] = options.adminFlags | ||
317 | if (options.pluginAuth !== undefined) toSend['pluginAuth'] = options.pluginAuth | ||
318 | |||
319 | return makePutBodyRequest({ | ||
320 | url: options.url, | ||
321 | path, | ||
322 | token: options.accessToken, | ||
323 | fields: toSend, | ||
324 | statusCodeExpected: HttpStatusCode.NO_CONTENT_204 | ||
325 | }) | ||
326 | } | ||
327 | |||
328 | function askResetPassword (url: string, email: string) { | ||
329 | const path = '/api/v1/users/ask-reset-password' | ||
330 | |||
331 | return makePostBodyRequest({ | ||
332 | url, | ||
333 | path, | ||
334 | fields: { email }, | ||
335 | statusCodeExpected: HttpStatusCode.NO_CONTENT_204 | ||
336 | }) | ||
337 | } | ||
338 | |||
339 | function resetPassword ( | ||
340 | url: string, | ||
341 | userId: number, | ||
342 | verificationString: string, | ||
343 | password: string, | ||
344 | statusCodeExpected = HttpStatusCode.NO_CONTENT_204 | ||
345 | ) { | ||
346 | const path = '/api/v1/users/' + userId + '/reset-password' | ||
347 | |||
348 | return makePostBodyRequest({ | ||
349 | url, | ||
350 | path, | ||
351 | fields: { password, verificationString }, | ||
352 | statusCodeExpected | ||
353 | }) | ||
354 | } | ||
355 | |||
356 | function askSendVerifyEmail (url: string, email: string) { | ||
357 | const path = '/api/v1/users/ask-send-verify-email' | ||
358 | |||
359 | return makePostBodyRequest({ | ||
360 | url, | ||
361 | path, | ||
362 | fields: { email }, | ||
363 | statusCodeExpected: HttpStatusCode.NO_CONTENT_204 | ||
364 | }) | ||
365 | } | ||
366 | |||
367 | function verifyEmail ( | ||
368 | url: string, | ||
369 | userId: number, | ||
370 | verificationString: string, | ||
371 | isPendingEmail = false, | ||
372 | statusCodeExpected = HttpStatusCode.NO_CONTENT_204 | ||
373 | ) { | ||
374 | const path = '/api/v1/users/' + userId + '/verify-email' | ||
375 | |||
376 | return makePostBodyRequest({ | ||
377 | url, | ||
378 | path, | ||
379 | fields: { | ||
380 | verificationString, | ||
381 | isPendingEmail | ||
382 | }, | ||
383 | statusCodeExpected | ||
384 | }) | ||
385 | } | ||
386 | |||
387 | // --------------------------------------------------------------------------- | 16 | // --------------------------------------------------------------------------- |
388 | 17 | ||
389 | export { | 18 | export { |
390 | createUser, | 19 | xxxgetMyUserInformation |
391 | registerUser, | ||
392 | getMyUserInformation, | ||
393 | getMyUserVideoRating, | ||
394 | deleteMe, | ||
395 | registerUserWithChannel, | ||
396 | getMyUserVideoQuotaUsed, | ||
397 | getUsersList, | ||
398 | getUsersListPaginationAndSort, | ||
399 | removeUser, | ||
400 | updateUser, | ||
401 | updateMyUser, | ||
402 | getUserInformation, | ||
403 | blockUser, | ||
404 | unblockUser, | ||
405 | askResetPassword, | ||
406 | resetPassword, | ||
407 | renewUserScopedTokens, | ||
408 | updateMyAvatar, | ||
409 | generateUser, | ||
410 | askSendVerifyEmail, | ||
411 | generateUserAccessToken, | ||
412 | verifyEmail, | ||
413 | getUserScopedTokens | ||
414 | } | 20 | } |
diff --git a/shared/extra-utils/videos/channels.ts b/shared/extra-utils/videos/channels.ts index a77543c92..9e7ec565d 100644 --- a/shared/extra-utils/videos/channels.ts +++ b/shared/extra-utils/videos/channels.ts | |||
@@ -1,13 +1,11 @@ | |||
1 | import { User } from '../../models/users/user.model' | ||
2 | import { ServerInfo } from '../server/servers' | 1 | import { ServerInfo } from '../server/servers' |
3 | import { getMyUserInformation } from '../users/users' | ||
4 | 2 | ||
5 | function setDefaultVideoChannel (servers: ServerInfo[]) { | 3 | function setDefaultVideoChannel (servers: ServerInfo[]) { |
6 | const tasks: Promise<any>[] = [] | 4 | const tasks: Promise<any>[] = [] |
7 | 5 | ||
8 | for (const server of servers) { | 6 | for (const server of servers) { |
9 | const p = getMyUserInformation(server.url, server.accessToken) | 7 | const p = server.usersCommand.getMyInfo() |
10 | .then(res => { server.videoChannel = (res.body as User).videoChannels[0] }) | 8 | .then(user => { server.videoChannel = user.videoChannels[0] }) |
11 | 9 | ||
12 | tasks.push(p) | 10 | tasks.push(p) |
13 | } | 11 | } |
diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts index 5dd71ce8b..5e20f8010 100644 --- a/shared/extra-utils/videos/videos.ts +++ b/shared/extra-utils/videos/videos.ts | |||
@@ -17,7 +17,7 @@ import { buildAbsoluteFixturePath, dateIsValid, testImage, wait, webtorrentAdd } | |||
17 | import { makeGetRequest, makePutBodyRequest, makeRawRequest, makeUploadRequest } from '../requests/requests' | 17 | import { makeGetRequest, makePutBodyRequest, makeRawRequest, makeUploadRequest } from '../requests/requests' |
18 | import { waitJobs } from '../server/jobs' | 18 | import { waitJobs } from '../server/jobs' |
19 | import { ServerInfo } from '../server/servers' | 19 | import { ServerInfo } from '../server/servers' |
20 | import { getMyUserInformation } from '../users/users' | 20 | import { xxxgetMyUserInformation } from '../users' |
21 | 21 | ||
22 | loadLanguages() | 22 | loadLanguages() |
23 | 23 | ||
@@ -339,7 +339,7 @@ async function uploadVideo ( | |||
339 | let defaultChannelId = '1' | 339 | let defaultChannelId = '1' |
340 | 340 | ||
341 | try { | 341 | try { |
342 | const res = await getMyUserInformation(url, accessToken) | 342 | const res = await xxxgetMyUserInformation(url, accessToken) |
343 | defaultChannelId = res.body.videoChannels[0].id | 343 | defaultChannelId = res.body.videoChannels[0].id |
344 | } catch (e) { /* empty */ } | 344 | } catch (e) { /* empty */ } |
345 | 345 | ||
diff --git a/shared/models/users/index.ts b/shared/models/users/index.ts index a9d578054..b61a8cd40 100644 --- a/shared/models/users/index.ts +++ b/shared/models/users/index.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | export * from './user-create-result.model' | ||
1 | export * from './user-create.model' | 2 | export * from './user-create.model' |
2 | export * from './user-flag.model' | 3 | export * from './user-flag.model' |
3 | export * from './user-login.model' | 4 | export * from './user-login.model' |
diff --git a/shared/models/users/user-create-result.model.ts b/shared/models/users/user-create-result.model.ts new file mode 100644 index 000000000..835b241ed --- /dev/null +++ b/shared/models/users/user-create-result.model.ts | |||
@@ -0,0 +1,7 @@ | |||
1 | export interface UserCreateResult { | ||
2 | id: number | ||
3 | |||
4 | account: { | ||
5 | id: number | ||
6 | } | ||
7 | } | ||