aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-07-07 10:33:49 +0200
committerChocobozzz <me@florianbigard.com>2021-07-20 15:27:17 +0200
commitae2abfd3aed3e75d39a316b49b914d187faa7475 (patch)
tree4d5060dc310f3d8cdcd5829779522f49b3d10e71 /shared
parent9c6327f803aaf4200672f1fc40b2f43786daca47 (diff)
downloadPeerTube-ae2abfd3aed3e75d39a316b49b914d187faa7475.tar.gz
PeerTube-ae2abfd3aed3e75d39a316b49b914d187faa7475.tar.zst
PeerTube-ae2abfd3aed3e75d39a316b49b914d187faa7475.zip
Introduce plugins command
Diffstat (limited to 'shared')
-rw-r--r--shared/extra-utils/index.ts1
-rw-r--r--shared/extra-utils/server/index.ts2
-rw-r--r--shared/extra-utils/server/plugins-command.ts245
-rw-r--r--shared/extra-utils/server/plugins.ts297
-rw-r--r--shared/extra-utils/server/servers.ts3
-rw-r--r--shared/extra-utils/shared/abstract-command.ts26
6 files changed, 268 insertions, 306 deletions
diff --git a/shared/extra-utils/index.ts b/shared/extra-utils/index.ts
index 652779eea..cf6418249 100644
--- a/shared/extra-utils/index.ts
+++ b/shared/extra-utils/index.ts
@@ -15,7 +15,6 @@ export * from './requests/requests'
15 15
16export * from './server/clients' 16export * from './server/clients'
17export * from './server/config' 17export * from './server/config'
18export * from './server/plugins'
19export * from './server/servers' 18export * from './server/servers'
20 19
21export * from './users/accounts' 20export * from './users/accounts'
diff --git a/shared/extra-utils/server/index.ts b/shared/extra-utils/server/index.ts
index b5b6b2116..e602fec7e 100644
--- a/shared/extra-utils/server/index.ts
+++ b/shared/extra-utils/server/index.ts
@@ -4,3 +4,5 @@ export * from './follows-command'
4export * from './follows' 4export * from './follows'
5export * from './jobs' 5export * from './jobs'
6export * from './jobs-command' 6export * from './jobs-command'
7export * from './plugins-command'
8export * from './plugins'
diff --git a/shared/extra-utils/server/plugins-command.ts b/shared/extra-utils/server/plugins-command.ts
new file mode 100644
index 000000000..f06e58a22
--- /dev/null
+++ b/shared/extra-utils/server/plugins-command.ts
@@ -0,0 +1,245 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { readJSON, writeJSON } from 'fs-extra'
4import { join } from 'path'
5import { root } from '@server/helpers/core-utils'
6import { HttpStatusCode } from '@shared/core-utils'
7import {
8 PeerTubePlugin,
9 PeerTubePluginIndex,
10 PeertubePluginIndexList,
11 PluginPackageJson,
12 PluginTranslation,
13 PluginType,
14 PublicServerSetting,
15 RegisteredServerSettings,
16 ResultList
17} from '@shared/models'
18import { buildServerDirectory } from '../miscs'
19import { AbstractCommand, OverrideCommandOptions } from '../shared'
20
21export class PluginsCommand extends AbstractCommand {
22
23 static getPluginTestPath (suffix = '') {
24 return join(root(), 'server', 'tests', 'fixtures', 'peertube-plugin-test' + suffix)
25 }
26
27 list (options: OverrideCommandOptions & {
28 start?: number
29 count?: number
30 sort?: string
31 pluginType?: PluginType
32 uninstalled?: boolean
33 }) {
34 const { start, count, sort, pluginType, uninstalled } = options
35 const path = '/api/v1/plugins'
36
37 return this.getRequestBody<ResultList<PeerTubePlugin>>({
38 ...options,
39
40 path,
41 query: {
42 start,
43 count,
44 sort,
45 pluginType,
46 uninstalled
47 },
48 defaultExpectedStatus: HttpStatusCode.OK_200
49 })
50 }
51
52 listAvailable (options: OverrideCommandOptions & {
53 start?: number
54 count?: number
55 sort?: string
56 pluginType?: PluginType
57 currentPeerTubeEngine?: string
58 search?: string
59 expectedStatus?: HttpStatusCode
60 }) {
61 const { start, count, sort, pluginType, search, currentPeerTubeEngine } = options
62 const path = '/api/v1/plugins/available'
63
64 const query: PeertubePluginIndexList = {
65 start,
66 count,
67 sort,
68 pluginType,
69 currentPeerTubeEngine,
70 search
71 }
72
73 return this.getRequestBody<ResultList<PeerTubePluginIndex>>({
74 ...options,
75
76 path,
77 query,
78 defaultExpectedStatus: HttpStatusCode.OK_200
79 })
80 }
81
82 get (options: OverrideCommandOptions & {
83 npmName: string
84 }) {
85 const path = '/api/v1/plugins/' + options.npmName
86
87 return this.getRequestBody<PeerTubePlugin>({
88 ...options,
89
90 path,
91 defaultExpectedStatus: HttpStatusCode.OK_200
92 })
93 }
94
95 updateSettings (options: OverrideCommandOptions & {
96 npmName: string
97 settings: any
98 }) {
99 const { npmName, settings } = options
100 const path = '/api/v1/plugins/' + npmName + '/settings'
101
102 return this.putBodyRequest({
103 ...options,
104
105 path,
106 fields: { settings },
107 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
108 })
109 }
110
111 getRegisteredSettings (options: OverrideCommandOptions & {
112 npmName: string
113 }) {
114 const path = '/api/v1/plugins/' + options.npmName + '/registered-settings'
115
116 return this.getRequestBody<RegisteredServerSettings>({
117 ...options,
118
119 path,
120 defaultExpectedStatus: HttpStatusCode.OK_200
121 })
122 }
123
124 getPublicSettings (options: OverrideCommandOptions & {
125 npmName: string
126 }) {
127 const { npmName } = options
128 const path = '/api/v1/plugins/' + npmName + '/public-settings'
129
130 return this.getRequestBody<PublicServerSetting>({
131 ...options,
132
133 path,
134 defaultExpectedStatus: HttpStatusCode.OK_200
135 })
136 }
137
138 getTranslations (options: OverrideCommandOptions & {
139 locale: string
140 }) {
141 const { locale } = options
142 const path = '/plugins/translations/' + locale + '.json'
143
144 return this.getRequestBody<PluginTranslation>({
145 ...options,
146
147 path,
148 defaultExpectedStatus: HttpStatusCode.OK_200
149 })
150 }
151
152 install (options: OverrideCommandOptions & {
153 path?: string
154 npmName?: string
155 }) {
156 const { npmName, path } = options
157 const apiPath = '/api/v1/plugins/install'
158
159 return this.postBodyRequest({
160 ...options,
161
162 path: apiPath,
163 fields: { npmName, path },
164 defaultExpectedStatus: HttpStatusCode.OK_200
165 })
166 }
167
168 update (options: OverrideCommandOptions & {
169 path?: string
170 npmName?: string
171 }) {
172 const { npmName, path } = options
173 const apiPath = '/api/v1/plugins/update'
174
175 return this.postBodyRequest({
176 ...options,
177
178 path: apiPath,
179 fields: { npmName, path },
180 defaultExpectedStatus: HttpStatusCode.OK_200
181 })
182 }
183
184 uninstall (options: OverrideCommandOptions & {
185 npmName: string
186 }) {
187 const { npmName } = options
188 const apiPath = '/api/v1/plugins/uninstall'
189
190 return this.postBodyRequest({
191 ...options,
192
193 path: apiPath,
194 fields: { npmName },
195 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
196 })
197 }
198
199 getCSS (options: OverrideCommandOptions = {}) {
200 const path = '/plugins/global.css'
201
202 return this.getRequestText({
203 ...options,
204
205 path,
206 defaultExpectedStatus: HttpStatusCode.OK_200
207 })
208 }
209
210 getExternalAuth (options: OverrideCommandOptions & {
211 npmName: string
212 npmVersion: string
213 authName: string
214 query?: any
215 }) {
216 const { npmName, npmVersion, authName, query } = options
217
218 const path = '/plugins/' + npmName + '/' + npmVersion + '/auth/' + authName
219
220 return this.getRequest({
221 ...options,
222
223 path,
224 query,
225 defaultExpectedStatus: HttpStatusCode.OK_200,
226 redirects: 0
227 })
228 }
229
230 updatePackageJSON (npmName: string, json: any) {
231 const path = this.getPackageJSONPath(npmName)
232
233 return writeJSON(path, json)
234 }
235
236 getPackageJSON (npmName: string): Promise<PluginPackageJson> {
237 const path = this.getPackageJSONPath(npmName)
238
239 return readJSON(path)
240 }
241
242 private getPackageJSONPath (npmName: string) {
243 return buildServerDirectory(this.server, join('plugins', 'node_modules', npmName, 'package.json'))
244 }
245}
diff --git a/shared/extra-utils/server/plugins.ts b/shared/extra-utils/server/plugins.ts
index d53e5b382..1084ea4f4 100644
--- a/shared/extra-utils/server/plugins.ts
+++ b/shared/extra-utils/server/plugins.ts
@@ -1,307 +1,18 @@
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
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { readJSON, writeJSON } from 'fs-extra' 4import { ServerInfo } from '../server/servers'
5import { join } from 'path'
6import { RegisteredServerSettings } from '@shared/models'
7import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
8import { PeertubePluginIndexList } from '../../models/plugins/plugin-index/peertube-plugin-index-list.model'
9import { PluginType } from '../../models/plugins/plugin.type'
10import { buildServerDirectory, root } from '../miscs/miscs'
11import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
12import { ServerInfo } from './servers'
13
14function listPlugins (parameters: {
15 url: string
16 accessToken: string
17 start?: number
18 count?: number
19 sort?: string
20 pluginType?: PluginType
21 uninstalled?: boolean
22 expectedStatus?: HttpStatusCode
23}) {
24 const { url, accessToken, start, count, sort, pluginType, uninstalled, expectedStatus = HttpStatusCode.OK_200 } = parameters
25 const path = '/api/v1/plugins'
26
27 return makeGetRequest({
28 url,
29 path,
30 token: accessToken,
31 query: {
32 start,
33 count,
34 sort,
35 pluginType,
36 uninstalled
37 },
38 statusCodeExpected: expectedStatus
39 })
40}
41
42function listAvailablePlugins (parameters: {
43 url: string
44 accessToken: string
45 start?: number
46 count?: number
47 sort?: string
48 pluginType?: PluginType
49 currentPeerTubeEngine?: string
50 search?: string
51 expectedStatus?: HttpStatusCode
52}) {
53 const {
54 url,
55 accessToken,
56 start,
57 count,
58 sort,
59 pluginType,
60 search,
61 currentPeerTubeEngine,
62 expectedStatus = HttpStatusCode.OK_200
63 } = parameters
64 const path = '/api/v1/plugins/available'
65
66 const query: PeertubePluginIndexList = {
67 start,
68 count,
69 sort,
70 pluginType,
71 currentPeerTubeEngine,
72 search
73 }
74
75 return makeGetRequest({
76 url,
77 path,
78 token: accessToken,
79 query,
80 statusCodeExpected: expectedStatus
81 })
82}
83
84function getPlugin (parameters: {
85 url: string
86 accessToken: string
87 npmName: string
88 expectedStatus?: HttpStatusCode
89}) {
90 const { url, accessToken, npmName, expectedStatus = HttpStatusCode.OK_200 } = parameters
91 const path = '/api/v1/plugins/' + npmName
92
93 return makeGetRequest({
94 url,
95 path,
96 token: accessToken,
97 statusCodeExpected: expectedStatus
98 })
99}
100
101function updatePluginSettings (parameters: {
102 url: string
103 accessToken: string
104 npmName: string
105 settings: any
106 expectedStatus?: HttpStatusCode
107}) {
108 const { url, accessToken, npmName, settings, expectedStatus = HttpStatusCode.NO_CONTENT_204 } = parameters
109 const path = '/api/v1/plugins/' + npmName + '/settings'
110
111 return makePutBodyRequest({
112 url,
113 path,
114 token: accessToken,
115 fields: { settings },
116 statusCodeExpected: expectedStatus
117 })
118}
119
120function getPluginRegisteredSettings (parameters: {
121 url: string
122 accessToken: string
123 npmName: string
124 expectedStatus?: HttpStatusCode
125}) {
126 const { url, accessToken, npmName, expectedStatus = HttpStatusCode.OK_200 } = parameters
127 const path = '/api/v1/plugins/' + npmName + '/registered-settings'
128
129 return makeGetRequest({
130 url,
131 path,
132 token: accessToken,
133 statusCodeExpected: expectedStatus
134 })
135}
136 5
137async function testHelloWorldRegisteredSettings (server: ServerInfo) { 6async function testHelloWorldRegisteredSettings (server: ServerInfo) {
138 const res = await getPluginRegisteredSettings({ 7 const body = await server.pluginsCommand.getRegisteredSettings({ npmName: 'peertube-plugin-hello-world' })
139 url: server.url,
140 accessToken: server.accessToken,
141 npmName: 'peertube-plugin-hello-world'
142 })
143
144 const registeredSettings = (res.body as RegisteredServerSettings).registeredSettings
145 8
9 const registeredSettings = body.registeredSettings
146 expect(registeredSettings).to.have.length.at.least(1) 10 expect(registeredSettings).to.have.length.at.least(1)
147 11
148 const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name') 12 const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name')
149 expect(adminNameSettings).to.not.be.undefined 13 expect(adminNameSettings).to.not.be.undefined
150} 14}
151 15
152function getPublicSettings (parameters: {
153 url: string
154 npmName: string
155 expectedStatus?: HttpStatusCode
156}) {
157 const { url, npmName, expectedStatus = HttpStatusCode.OK_200 } = parameters
158 const path = '/api/v1/plugins/' + npmName + '/public-settings'
159
160 return makeGetRequest({
161 url,
162 path,
163 statusCodeExpected: expectedStatus
164 })
165}
166
167function getPluginTranslations (parameters: {
168 url: string
169 locale: string
170 expectedStatus?: HttpStatusCode
171}) {
172 const { url, locale, expectedStatus = HttpStatusCode.OK_200 } = parameters
173 const path = '/plugins/translations/' + locale + '.json'
174
175 return makeGetRequest({
176 url,
177 path,
178 statusCodeExpected: expectedStatus
179 })
180}
181
182function installPlugin (parameters: {
183 url: string
184 accessToken: string
185 path?: string
186 npmName?: string
187 expectedStatus?: HttpStatusCode
188}) {
189 const { url, accessToken, npmName, path, expectedStatus = HttpStatusCode.OK_200 } = parameters
190 const apiPath = '/api/v1/plugins/install'
191
192 return makePostBodyRequest({
193 url,
194 path: apiPath,
195 token: accessToken,
196 fields: { npmName, path },
197 statusCodeExpected: expectedStatus
198 })
199}
200
201function updatePlugin (parameters: {
202 url: string
203 accessToken: string
204 path?: string
205 npmName?: string
206 expectedStatus?: HttpStatusCode
207}) {
208 const { url, accessToken, npmName, path, expectedStatus = HttpStatusCode.OK_200 } = parameters
209 const apiPath = '/api/v1/plugins/update'
210
211 return makePostBodyRequest({
212 url,
213 path: apiPath,
214 token: accessToken,
215 fields: { npmName, path },
216 statusCodeExpected: expectedStatus
217 })
218}
219
220function uninstallPlugin (parameters: {
221 url: string
222 accessToken: string
223 npmName: string
224 expectedStatus?: HttpStatusCode
225}) {
226 const { url, accessToken, npmName, expectedStatus = HttpStatusCode.NO_CONTENT_204 } = parameters
227 const apiPath = '/api/v1/plugins/uninstall'
228
229 return makePostBodyRequest({
230 url,
231 path: apiPath,
232 token: accessToken,
233 fields: { npmName },
234 statusCodeExpected: expectedStatus
235 })
236}
237
238function getPluginsCSS (url: string) {
239 const path = '/plugins/global.css'
240
241 return makeGetRequest({
242 url,
243 path,
244 statusCodeExpected: HttpStatusCode.OK_200
245 })
246}
247
248function getPackageJSONPath (server: ServerInfo, npmName: string) {
249 return buildServerDirectory(server, join('plugins', 'node_modules', npmName, 'package.json'))
250}
251
252function updatePluginPackageJSON (server: ServerInfo, npmName: string, json: any) {
253 const path = getPackageJSONPath(server, npmName)
254
255 return writeJSON(path, json)
256}
257
258function getPluginPackageJSON (server: ServerInfo, npmName: string) {
259 const path = getPackageJSONPath(server, npmName)
260
261 return readJSON(path)
262}
263
264function getPluginTestPath (suffix = '') {
265 return join(root(), 'server', 'tests', 'fixtures', 'peertube-plugin-test' + suffix)
266}
267
268function getExternalAuth (options: {
269 url: string
270 npmName: string
271 npmVersion: string
272 authName: string
273 query?: any
274 statusCodeExpected?: HttpStatusCode
275}) {
276 const { url, npmName, npmVersion, authName, statusCodeExpected, query } = options
277
278 const path = '/plugins/' + npmName + '/' + npmVersion + '/auth/' + authName
279
280 return makeGetRequest({
281 url,
282 path,
283 query,
284 statusCodeExpected: statusCodeExpected || HttpStatusCode.OK_200,
285 redirects: 0
286 })
287}
288
289export { 16export {
290 listPlugins, 17 testHelloWorldRegisteredSettings
291 listAvailablePlugins,
292 installPlugin,
293 getPluginTranslations,
294 getPluginsCSS,
295 updatePlugin,
296 getPlugin,
297 uninstallPlugin,
298 testHelloWorldRegisteredSettings,
299 updatePluginSettings,
300 getPluginRegisteredSettings,
301 getPackageJSONPath,
302 updatePluginPackageJSON,
303 getPluginPackageJSON,
304 getPluginTestPath,
305 getPublicSettings,
306 getExternalAuth
307} 18}
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index 5511ce0b0..79d6b7b1a 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -20,6 +20,7 @@ import { ContactFormCommand } from './contact-form-command'
20import { DebugCommand } from './debug-command' 20import { DebugCommand } from './debug-command'
21import { FollowsCommand } from './follows-command' 21import { FollowsCommand } from './follows-command'
22import { JobsCommand } from './jobs-command' 22import { JobsCommand } from './jobs-command'
23import { PluginsCommand } from './plugins-command'
23 24
24interface ServerInfo { 25interface ServerInfo {
25 app: ChildProcess 26 app: ChildProcess
@@ -85,6 +86,7 @@ interface ServerInfo {
85 debugCommand?: DebugCommand 86 debugCommand?: DebugCommand
86 followsCommand?: FollowsCommand 87 followsCommand?: FollowsCommand
87 jobsCommand?: JobsCommand 88 jobsCommand?: JobsCommand
89 pluginsCommand?: PluginsCommand
88} 90}
89 91
90function parallelTests () { 92function parallelTests () {
@@ -302,6 +304,7 @@ async function runServer (server: ServerInfo, configOverrideArg?: any, args = []
302 server.debugCommand = new DebugCommand(server) 304 server.debugCommand = new DebugCommand(server)
303 server.followsCommand = new FollowsCommand(server) 305 server.followsCommand = new FollowsCommand(server)
304 server.jobsCommand = new JobsCommand(server) 306 server.jobsCommand = new JobsCommand(server)
307 server.pluginsCommand = new PluginsCommand(server)
305 308
306 res(server) 309 res(server)
307 }) 310 })
diff --git a/shared/extra-utils/shared/abstract-command.ts b/shared/extra-utils/shared/abstract-command.ts
index 3815fab0e..dd4598a91 100644
--- a/shared/extra-utils/shared/abstract-command.ts
+++ b/shared/extra-utils/shared/abstract-command.ts
@@ -16,6 +16,7 @@ interface GetCommandOptions extends CommonCommandOptions {
16 query?: { [ id: string ]: any } 16 query?: { [ id: string ]: any }
17 contentType?: string 17 contentType?: string
18 accept?: string 18 accept?: string
19 redirects?: number
19} 20}
20 21
21abstract class AbstractCommand { 22abstract class AbstractCommand {
@@ -44,6 +45,19 @@ abstract class AbstractCommand {
44 return unwrapText(this.getRequest(options)) 45 return unwrapText(this.getRequest(options))
45 } 46 }
46 47
48 protected getRequest (options: GetCommandOptions) {
49 const { redirects, query, contentType, accept } = options
50
51 return makeGetRequest({
52 ...this.buildCommonRequestOptions(options),
53
54 redirects,
55 query,
56 contentType,
57 accept
58 })
59 }
60
47 protected deleteRequest (options: CommonCommandOptions) { 61 protected deleteRequest (options: CommonCommandOptions) {
48 return makeDeleteRequest(this.buildCommonRequestOptions(options)) 62 return makeDeleteRequest(this.buildCommonRequestOptions(options))
49 } 63 }
@@ -85,18 +99,6 @@ abstract class AbstractCommand {
85 statusCodeExpected: expectedStatus ?? this.expectedStatus ?? defaultExpectedStatus 99 statusCodeExpected: expectedStatus ?? this.expectedStatus ?? defaultExpectedStatus
86 } 100 }
87 } 101 }
88
89 private getRequest (options: GetCommandOptions) {
90 const { query, contentType, accept } = options
91
92 return makeGetRequest({
93 ...this.buildCommonRequestOptions(options),
94
95 query,
96 contentType,
97 accept
98 })
99 }
100} 102}
101 103
102export { 104export {