aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/extra-utils
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-07-13 11:05:15 +0200
committerChocobozzz <me@florianbigard.com>2021-07-20 15:27:18 +0200
commit41d1d075011174e73dccb74006181a92a618d7b4 (patch)
tree4dc1af0e266977f062cf9716837d04de1cdd628d /shared/extra-utils
parent6c5065a011b099618681a37bd77eaa7bd3db752e (diff)
downloadPeerTube-41d1d075011174e73dccb74006181a92a618d7b4.tar.gz
PeerTube-41d1d075011174e73dccb74006181a92a618d7b4.tar.zst
PeerTube-41d1d075011174e73dccb74006181a92a618d7b4.zip
Introduce login command
Diffstat (limited to 'shared/extra-utils')
-rw-r--r--shared/extra-utils/requests/requests.ts4
-rw-r--r--shared/extra-utils/server/clients.ts20
-rw-r--r--shared/extra-utils/server/servers.ts4
-rw-r--r--shared/extra-utils/shared/abstract-command.ts10
-rw-r--r--shared/extra-utils/users/index.ts1
-rw-r--r--shared/extra-utils/users/login-command.ts134
-rw-r--r--shared/extra-utils/users/login.ts120
-rw-r--r--shared/extra-utils/users/notifications.ts4
-rw-r--r--shared/extra-utils/users/users.ts5
9 files changed, 156 insertions, 146 deletions
diff --git a/shared/extra-utils/requests/requests.ts b/shared/extra-utils/requests/requests.ts
index f9d112aca..c5ee63e05 100644
--- a/shared/extra-utils/requests/requests.ts
+++ b/shared/extra-utils/requests/requests.ts
@@ -27,6 +27,7 @@ function makeGetRequest (options: {
27 range?: string 27 range?: string
28 redirects?: number 28 redirects?: number
29 accept?: string 29 accept?: string
30 host?: string
30}) { 31}) {
31 if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400 32 if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400
32 if (options.contentType === undefined) options.contentType = 'application/json' 33 if (options.contentType === undefined) options.contentType = 'application/json'
@@ -38,6 +39,7 @@ function makeGetRequest (options: {
38 if (options.query) req.query(options.query) 39 if (options.query) req.query(options.query)
39 if (options.range) req.set('Range', options.range) 40 if (options.range) req.set('Range', options.range)
40 if (options.accept) req.set('Accept', options.accept) 41 if (options.accept) req.set('Accept', options.accept)
42 if (options.host) req.set('Host', options.host)
41 if (options.redirects) req.redirects(options.redirects) 43 if (options.redirects) req.redirects(options.redirects)
42 44
43 return req.expect(options.statusCodeExpected) 45 return req.expect(options.statusCodeExpected)
@@ -113,6 +115,7 @@ function makePostBodyRequest (options: {
113 path: string 115 path: string
114 token?: string 116 token?: string
115 fields?: { [ fieldName: string ]: any } 117 fields?: { [ fieldName: string ]: any }
118 type?: string
116 statusCodeExpected?: HttpStatusCode 119 statusCodeExpected?: HttpStatusCode
117}) { 120}) {
118 if (!options.fields) options.fields = {} 121 if (!options.fields) options.fields = {}
@@ -123,6 +126,7 @@ function makePostBodyRequest (options: {
123 .set('Accept', 'application/json') 126 .set('Accept', 'application/json')
124 127
125 if (options.token) req.set('Authorization', 'Bearer ' + options.token) 128 if (options.token) req.set('Authorization', 'Bearer ' + options.token)
129 if (options.type) req.type(options.type)
126 130
127 return req.send(options.fields) 131 return req.send(options.fields)
128 .expect(options.statusCodeExpected) 132 .expect(options.statusCodeExpected)
diff --git a/shared/extra-utils/server/clients.ts b/shared/extra-utils/server/clients.ts
deleted file mode 100644
index 894fe4911..000000000
--- a/shared/extra-utils/server/clients.ts
+++ /dev/null
@@ -1,20 +0,0 @@
1import * as request from 'supertest'
2import { URL } from 'url'
3import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
4
5function getClient (url: string) {
6 const path = '/api/v1/oauth-clients/local'
7
8 return request(url)
9 .get(path)
10 .set('Host', new URL(url).host)
11 .set('Accept', 'application/json')
12 .expect(HttpStatusCode.OK_200)
13 .expect('Content-Type', /json/)
14}
15
16// ---------------------------------------------------------------------------
17
18export {
19 getClient
20}
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index f5dc0326f..4d9599680 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -16,7 +16,7 @@ import { AbusesCommand } from '../moderation'
16import { OverviewsCommand } from '../overviews' 16import { OverviewsCommand } from '../overviews'
17import { SearchCommand } from '../search' 17import { SearchCommand } from '../search'
18import { SocketIOCommand } from '../socket' 18import { SocketIOCommand } from '../socket'
19import { AccountsCommand, BlocklistCommand, NotificationsCommand, SubscriptionsCommand } from '../users' 19import { AccountsCommand, BlocklistCommand, LoginCommand, NotificationsCommand, SubscriptionsCommand } from '../users'
20import { 20import {
21 BlacklistCommand, 21 BlacklistCommand,
22 CaptionsCommand, 22 CaptionsCommand,
@@ -126,6 +126,7 @@ interface ServerInfo {
126 sqlCommand?: SQLCommand 126 sqlCommand?: SQLCommand
127 notificationsCommand?: NotificationsCommand 127 notificationsCommand?: NotificationsCommand
128 serversCommand?: ServersCommand 128 serversCommand?: ServersCommand
129 loginCommand?: LoginCommand
129} 130}
130 131
131function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) { 132function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) {
@@ -357,6 +358,7 @@ function assignCommands (server: ServerInfo) {
357 server.sqlCommand = new SQLCommand(server) 358 server.sqlCommand = new SQLCommand(server)
358 server.notificationsCommand = new NotificationsCommand(server) 359 server.notificationsCommand = new NotificationsCommand(server)
359 server.serversCommand = new ServersCommand(server) 360 server.serversCommand = new ServersCommand(server)
361 server.loginCommand = new LoginCommand(server)
360} 362}
361 363
362async function reRunServer (server: ServerInfo, configOverride?: any) { 364async function reRunServer (server: ServerInfo, configOverride?: any) {
diff --git a/shared/extra-utils/shared/abstract-command.ts b/shared/extra-utils/shared/abstract-command.ts
index 4e61554a2..af9ecd926 100644
--- a/shared/extra-utils/shared/abstract-command.ts
+++ b/shared/extra-utils/shared/abstract-command.ts
@@ -33,6 +33,7 @@ interface InternalGetCommandOptions extends InternalCommonCommandOptions {
33 accept?: string 33 accept?: string
34 redirects?: number 34 redirects?: number
35 range?: string 35 range?: string
36 host?: string
36} 37}
37 38
38abstract class AbstractCommand { 39abstract class AbstractCommand {
@@ -78,7 +79,7 @@ abstract class AbstractCommand {
78 } 79 }
79 80
80 protected getRequest (options: InternalGetCommandOptions) { 81 protected getRequest (options: InternalGetCommandOptions) {
81 const { redirects, query, contentType, accept, range } = options 82 const { redirects, query, contentType, accept, range, host } = options
82 83
83 return makeGetRequest({ 84 return makeGetRequest({
84 ...this.buildCommonRequestOptions(options), 85 ...this.buildCommonRequestOptions(options),
@@ -87,6 +88,7 @@ abstract class AbstractCommand {
87 query, 88 query,
88 contentType, 89 contentType,
89 range, 90 range,
91 host,
90 accept 92 accept
91 }) 93 })
92 } 94 }
@@ -109,13 +111,15 @@ abstract class AbstractCommand {
109 111
110 protected postBodyRequest (options: InternalCommonCommandOptions & { 112 protected postBodyRequest (options: InternalCommonCommandOptions & {
111 fields?: { [ fieldName: string ]: any } 113 fields?: { [ fieldName: string ]: any }
114 type?: string
112 }) { 115 }) {
113 const { fields } = options 116 const { type, fields } = options
114 117
115 return makePostBodyRequest({ 118 return makePostBodyRequest({
116 ...this.buildCommonRequestOptions(options), 119 ...this.buildCommonRequestOptions(options),
117 120
118 fields 121 fields,
122 type
119 }) 123 })
120 } 124 }
121 125
diff --git a/shared/extra-utils/users/index.ts b/shared/extra-utils/users/index.ts
index ed166c756..b200ae705 100644
--- a/shared/extra-utils/users/index.ts
+++ b/shared/extra-utils/users/index.ts
@@ -2,6 +2,7 @@ export * from './accounts-command'
2export * from './accounts' 2export * from './accounts'
3export * from './blocklist-command' 3export * from './blocklist-command'
4export * from './login' 4export * from './login'
5export * from './login-command'
5export * from './notifications' 6export * from './notifications'
6export * from './notifications-command' 7export * from './notifications-command'
7export * from './subscriptions-command' 8export * from './subscriptions-command'
diff --git a/shared/extra-utils/users/login-command.ts b/shared/extra-utils/users/login-command.ts
new file mode 100644
index 000000000..97efcb766
--- /dev/null
+++ b/shared/extra-utils/users/login-command.ts
@@ -0,0 +1,134 @@
1import { PeerTubeRequestError } from '@server/helpers/requests'
2import { HttpStatusCode } from '@shared/core-utils'
3import { PeerTubeProblemDocument } from '@shared/models'
4import { unwrapBody } from '../requests'
5import { AbstractCommand, OverrideCommandOptions } from '../shared'
6
7export class LoginCommand extends AbstractCommand {
8
9 login (options: OverrideCommandOptions & {
10 client?: { id?: string, secret?: string }
11 user?: { username: string, password: string }
12 } = {}) {
13 const { client = this.server.client, user = this.server.user } = options
14 const path = '/api/v1/users/token'
15
16 const body = {
17 client_id: client.id,
18 client_secret: client.secret,
19 username: user.username,
20 password: user.password,
21 response_type: 'code',
22 grant_type: 'password',
23 scope: 'upload'
24 }
25
26 return unwrapBody<{ access_token: string, refresh_token: string } & PeerTubeProblemDocument>(this.postBodyRequest({
27 ...options,
28
29 path,
30 type: 'form',
31 fields: body,
32 implicitToken: false,
33 defaultExpectedStatus: HttpStatusCode.OK_200
34 }))
35 }
36
37 getAccessToken (user?: { username: string, password: string }): Promise<string>
38 getAccessToken (username: string, password: string): Promise<string>
39 async getAccessToken (arg1?: { username: string, password: string } | string, password?: string) {
40 let user: { username: string, password: string }
41
42 if (!arg1) user = this.server.user
43 else if (typeof arg1 === 'object') user = arg1
44 else user = { username: arg1, password }
45
46 try {
47 const body = await this.login({ user })
48
49 return body.access_token
50 } catch (err) {
51 throw new Error('Cannot authenticate. Please check your username/password.')
52 }
53 }
54
55 loginUsingExternalToken (options: OverrideCommandOptions & {
56 username: string
57 externalAuthToken: string
58 }) {
59 const { username, externalAuthToken } = options
60 const path = '/api/v1/users/token'
61
62 const body = {
63 client_id: this.server.client.id,
64 client_secret: this.server.client.secret,
65 username: username,
66 response_type: 'code',
67 grant_type: 'password',
68 scope: 'upload',
69 externalAuthToken
70 }
71
72 return this.postBodyRequest({
73 ...options,
74
75 path,
76 type: 'form',
77 fields: body,
78 implicitToken: false,
79 defaultExpectedStatus: HttpStatusCode.OK_200
80 })
81 }
82
83 logout (options: OverrideCommandOptions & {
84 token: string
85 }) {
86 const path = '/api/v1/users/revoke-token'
87
88 return unwrapBody<{ redirectUrl: string }>(this.postBodyRequest({
89 ...options,
90
91 path,
92 type: 'form',
93 implicitToken: false,
94 defaultExpectedStatus: HttpStatusCode.OK_200
95 }))
96 }
97
98 refreshToken (options: OverrideCommandOptions & {
99 refreshToken: string
100 }) {
101 const path = '/api/v1/users/token'
102
103 const body = {
104 client_id: this.server.client.id,
105 client_secret: this.server.client.secret,
106 refresh_token: options.refreshToken,
107 response_type: 'code',
108 grant_type: 'refresh_token'
109 }
110
111 return this.postBodyRequest({
112 ...options,
113
114 path,
115 type: 'form',
116 fields: body,
117 implicitToken: false,
118 defaultExpectedStatus: HttpStatusCode.OK_200
119 })
120 }
121
122 getClient (options: OverrideCommandOptions = {}) {
123 const path = '/api/v1/oauth-clients/local'
124
125 return this.getRequestBody<{ client_id: string, client_secret: string }>({
126 ...options,
127
128 path,
129 host: this.server.host,
130 implicitToken: false,
131 defaultExpectedStatus: HttpStatusCode.OK_200
132 })
133 }
134}
diff --git a/shared/extra-utils/users/login.ts b/shared/extra-utils/users/login.ts
index c14367542..d4ee8e517 100644
--- a/shared/extra-utils/users/login.ts
+++ b/shared/extra-utils/users/login.ts
@@ -1,133 +1,19 @@
1import * as request from 'supertest'
2
3import { ServerInfo } from '../server/servers' 1import { ServerInfo } from '../server/servers'
4import { getClient } from '../server/clients'
5import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
6
7type Client = { id?: string, secret?: string }
8type User = { username: string, password: string }
9type Server = { url?: string, client?: Client, user?: User }
10
11function login (url: string, client: Client, user: User, expectedStatus = HttpStatusCode.OK_200) {
12 const path = '/api/v1/users/token'
13
14 const body = {
15 client_id: client.id,
16 client_secret: client.secret,
17 username: user.username,
18 password: user.password,
19 response_type: 'code',
20 grant_type: 'password',
21 scope: 'upload'
22 }
23
24 return request(url)
25 .post(path)
26 .type('form')
27 .send(body)
28 .expect(expectedStatus)
29}
30
31function logout (url: string, token: string, expectedStatus = HttpStatusCode.OK_200) {
32 const path = '/api/v1/users/revoke-token'
33
34 return request(url)
35 .post(path)
36 .set('Authorization', 'Bearer ' + token)
37 .type('form')
38 .expect(expectedStatus)
39}
40
41async function serverLogin (server: Server) {
42 const res = await login(server.url, server.client, server.user, HttpStatusCode.OK_200)
43
44 return res.body.access_token as string
45}
46
47function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus = HttpStatusCode.OK_200) {
48 const path = '/api/v1/users/token'
49
50 const body = {
51 client_id: server.client.id,
52 client_secret: server.client.secret,
53 refresh_token: refreshToken,
54 response_type: 'code',
55 grant_type: 'refresh_token'
56 }
57
58 return request(server.url)
59 .post(path)
60 .type('form')
61 .send(body)
62 .expect(expectedStatus)
63}
64
65async function userLogin (server: Server, user: User, expectedStatus = HttpStatusCode.OK_200) {
66 const res = await login(server.url, server.client, user, expectedStatus)
67
68 return res.body.access_token as string
69}
70
71async function getAccessToken (url: string, username: string, password: string) {
72 const resClient = await getClient(url)
73 const client = {
74 id: resClient.body.client_id,
75 secret: resClient.body.client_secret
76 }
77
78 const user = { username, password }
79
80 try {
81 const res = await login(url, client, user)
82 return res.body.access_token
83 } catch (err) {
84 throw new Error('Cannot authenticate. Please check your username/password.')
85 }
86}
87 2
88function setAccessTokensToServers (servers: ServerInfo[]) { 3function setAccessTokensToServers (servers: ServerInfo[]) {
89 const tasks: Promise<any>[] = [] 4 const tasks: Promise<any>[] = []
90 5
91 for (const server of servers) { 6 for (const server of servers) {
92 const p = serverLogin(server).then(t => { server.accessToken = t }) 7 const p = server.loginCommand.getAccessToken()
8 .then(t => { server.accessToken = t })
93 tasks.push(p) 9 tasks.push(p)
94 } 10 }
95 11
96 return Promise.all(tasks) 12 return Promise.all(tasks)
97} 13}
98 14
99function loginUsingExternalToken (server: Server, username: string, externalAuthToken: string, expectedStatus = HttpStatusCode.OK_200) {
100 const path = '/api/v1/users/token'
101
102 const body = {
103 client_id: server.client.id,
104 client_secret: server.client.secret,
105 username: username,
106 response_type: 'code',
107 grant_type: 'password',
108 scope: 'upload',
109 externalAuthToken
110 }
111
112 return request(server.url)
113 .post(path)
114 .type('form')
115 .send(body)
116 .expect(expectedStatus)
117}
118
119// --------------------------------------------------------------------------- 15// ---------------------------------------------------------------------------
120 16
121export { 17export {
122 login, 18 setAccessTokensToServers
123 logout,
124 serverLogin,
125 refreshToken,
126 userLogin,
127 getAccessToken,
128 setAccessTokensToServers,
129 Server,
130 Client,
131 User,
132 loginUsingExternalToken
133} 19}
diff --git a/shared/extra-utils/users/notifications.ts b/shared/extra-utils/users/notifications.ts
index 81f0729fa..79cb6f617 100644
--- a/shared/extra-utils/users/notifications.ts
+++ b/shared/extra-utils/users/notifications.ts
@@ -7,7 +7,7 @@ import { UserNotification, UserNotificationSetting, UserNotificationSettingValue
7import { MockSmtpServer } from '../mock-servers/mock-email' 7import { MockSmtpServer } from '../mock-servers/mock-email'
8import { doubleFollow } from '../server/follows' 8import { doubleFollow } from '../server/follows'
9import { flushAndRunMultipleServers, ServerInfo } from '../server/servers' 9import { flushAndRunMultipleServers, ServerInfo } from '../server/servers'
10import { setAccessTokensToServers, userLogin } from './login' 10import { setAccessTokensToServers } from './login'
11import { createUser, getMyUserInformation } from './users' 11import { createUser, getMyUserInformation } from './users'
12 12
13function getAllNotificationsSettings (): UserNotificationSetting { 13function getAllNotificationsSettings (): UserNotificationSetting {
@@ -662,7 +662,7 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
662 password: user.password, 662 password: user.password,
663 videoQuota: 10 * 1000 * 1000 663 videoQuota: 10 * 1000 * 1000
664 }) 664 })
665 const userAccessToken = await userLogin(servers[0], user) 665 const userAccessToken = await servers[0].loginCommand.getAccessToken(user)
666 666
667 await servers[0].notificationsCommand.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() }) 667 await servers[0].notificationsCommand.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() })
668 await servers[0].notificationsCommand.updateMySettings({ settings: getAllNotificationsSettings() }) 668 await servers[0].notificationsCommand.updateMySettings({ settings: getAllNotificationsSettings() })
diff --git a/shared/extra-utils/users/users.ts b/shared/extra-utils/users/users.ts
index 0f15962ad..835ad08ba 100644
--- a/shared/extra-utils/users/users.ts
+++ b/shared/extra-utils/users/users.ts
@@ -7,7 +7,6 @@ import { UserRegister } from '../../models/users/user-register.model'
7import { UserRole } from '../../models/users/user-role' 7import { UserRole } from '../../models/users/user-role'
8import { makeGetRequest, makePostBodyRequest, makePutBodyRequest, updateImageRequest } from '../requests/requests' 8import { makeGetRequest, makePostBodyRequest, makePutBodyRequest, updateImageRequest } from '../requests/requests'
9import { ServerInfo } from '../server/servers' 9import { ServerInfo } from '../server/servers'
10import { userLogin } from './login'
11 10
12function createUser (parameters: { 11function createUser (parameters: {
13 url: string 12 url: string
@@ -55,7 +54,7 @@ async function generateUser (server: ServerInfo, username: string) {
55 const password = 'my super password' 54 const password = 'my super password'
56 const resCreate = await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) 55 const resCreate = await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
57 56
58 const token = await userLogin(server, { username, password }) 57 const token = await server.loginCommand.getAccessToken({ username, password })
59 58
60 const resMe = await getMyUserInformation(server.url, token) 59 const resMe = await getMyUserInformation(server.url, token)
61 60
@@ -70,7 +69,7 @@ async function generateUserAccessToken (server: ServerInfo, username: string) {
70 const password = 'my super password' 69 const password = 'my super password'
71 await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) 70 await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
72 71
73 return userLogin(server, { username, password }) 72 return server.loginCommand.getAccessToken({ username, password })
74} 73}
75 74
76function registerUser (url: string, username: string, password: string, specialStatus = HttpStatusCode.NO_CONTENT_204) { 75function registerUser (url: string, username: string, password: string, specialStatus = HttpStatusCode.NO_CONTENT_204) {