aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/plugins')
-rw-r--r--server/tests/plugins/action-hooks.ts17
-rw-r--r--server/tests/plugins/external-auth.ts331
-rw-r--r--server/tests/plugins/filter-hooks.ts41
-rw-r--r--server/tests/plugins/id-and-pass-auth.ts245
-rw-r--r--server/tests/plugins/index.ts5
-rw-r--r--server/tests/plugins/plugin-helpers.ts210
-rw-r--r--server/tests/plugins/plugin-router.ts91
-rw-r--r--server/tests/plugins/plugin-storage.ts30
-rw-r--r--server/tests/plugins/translations.ts35
-rw-r--r--server/tests/plugins/video-constants.ts111
10 files changed, 1014 insertions, 102 deletions
diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts
index 510ec3151..ca57a4b51 100644
--- a/server/tests/plugins/action-hooks.ts
+++ b/server/tests/plugins/action-hooks.ts
@@ -1,6 +1,5 @@
1/* tslint:disable:no-unused-expression */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai'
4import 'mocha' 3import 'mocha'
5import { 4import {
6 cleanupTests, 5 cleanupTests,
@@ -17,18 +16,18 @@ import {
17 createUser, 16 createUser,
18 deleteVideoComment, 17 deleteVideoComment,
19 getPluginTestPath, 18 getPluginTestPath,
20 installPlugin, login, 19 installPlugin,
21 registerUser, removeUser, 20 registerUser,
21 removeUser,
22 setAccessTokensToServers, 22 setAccessTokensToServers,
23 unblockUser, updateUser, 23 unblockUser,
24 updateUser,
24 updateVideo, 25 updateVideo,
25 uploadVideo, 26 uploadVideo,
26 viewVideo, 27 userLogin,
27 userLogin 28 viewVideo
28} from '../../../shared/extra-utils' 29} from '../../../shared/extra-utils'
29 30
30const expect = chai.expect
31
32describe('Test plugin action hooks', function () { 31describe('Test plugin action hooks', function () {
33 let servers: ServerInfo[] 32 let servers: ServerInfo[]
34 let videoUUID: string 33 let videoUUID: string
diff --git a/server/tests/plugins/external-auth.ts b/server/tests/plugins/external-auth.ts
new file mode 100644
index 000000000..312561538
--- /dev/null
+++ b/server/tests/plugins/external-auth.ts
@@ -0,0 +1,331 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { expect } from 'chai'
5import { ServerConfig, User, UserRole } from '@shared/models'
6import {
7 decodeQueryString,
8 getConfig,
9 getExternalAuth,
10 getMyUserInformation,
11 getPluginTestPath,
12 installPlugin,
13 loginUsingExternalToken,
14 logout,
15 refreshToken,
16 setAccessTokensToServers,
17 uninstallPlugin,
18 updateMyUser,
19 wait,
20 userLogin,
21 updatePluginSettings
22} from '../../../shared/extra-utils'
23import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
24
25async function loginExternal (options: {
26 server: ServerInfo
27 npmName: string
28 authName: string
29 username: string
30 query?: any
31 statusCodeExpected?: number
32}) {
33 const res = await getExternalAuth({
34 url: options.server.url,
35 npmName: options.npmName,
36 npmVersion: '0.0.1',
37 authName: options.authName,
38 query: options.query,
39 statusCodeExpected: options.statusCodeExpected || 302
40 })
41
42 if (res.status !== 302) return
43
44 const location = res.header.location
45 const { externalAuthToken } = decodeQueryString(location)
46
47 const resLogin = await loginUsingExternalToken(
48 options.server,
49 options.username,
50 externalAuthToken as string
51 )
52
53 return resLogin.body
54}
55
56describe('Test external auth plugins', function () {
57 let server: ServerInfo
58
59 let cyanAccessToken: string
60 let cyanRefreshToken: string
61
62 let kefkaAccessToken: string
63 let kefkaRefreshToken: string
64
65 let externalAuthToken: string
66
67 before(async function () {
68 this.timeout(30000)
69
70 server = await flushAndRunServer(1)
71 await setAccessTokensToServers([ server ])
72
73 for (const suffix of [ 'one', 'two' ]) {
74 await installPlugin({
75 url: server.url,
76 accessToken: server.accessToken,
77 path: getPluginTestPath('-external-auth-' + suffix)
78 })
79 }
80 })
81
82 it('Should display the correct configuration', async function () {
83 const res = await getConfig(server.url)
84
85 const config: ServerConfig = res.body
86
87 const auths = config.plugin.registeredExternalAuths
88 expect(auths).to.have.lengthOf(3)
89
90 const auth2 = auths.find((a) => a.authName === 'external-auth-2')
91 expect(auth2).to.exist
92 expect(auth2.authDisplayName).to.equal('External Auth 2')
93 expect(auth2.npmName).to.equal('peertube-plugin-test-external-auth-one')
94 })
95
96 it('Should redirect for a Cyan login', async function () {
97 const res = await getExternalAuth({
98 url: server.url,
99 npmName: 'test-external-auth-one',
100 npmVersion: '0.0.1',
101 authName: 'external-auth-1',
102 query: {
103 username: 'cyan'
104 },
105 statusCodeExpected: 302
106 })
107
108 const location = res.header.location
109 expect(location.startsWith('/login?')).to.be.true
110
111 const searchParams = decodeQueryString(location)
112
113 expect(searchParams.externalAuthToken).to.exist
114 expect(searchParams.username).to.equal('cyan')
115
116 externalAuthToken = searchParams.externalAuthToken as string
117 })
118
119 it('Should reject auto external login with a missing or invalid token', async function () {
120 await loginUsingExternalToken(server, 'cyan', '', 400)
121 await loginUsingExternalToken(server, 'cyan', 'blabla', 400)
122 })
123
124 it('Should reject auto external login with a missing or invalid username', async function () {
125 await loginUsingExternalToken(server, '', externalAuthToken, 400)
126 await loginUsingExternalToken(server, '', externalAuthToken, 400)
127 })
128
129 it('Should reject auto external login with an expired token', async function () {
130 this.timeout(15000)
131
132 await wait(5000)
133
134 await loginUsingExternalToken(server, 'cyan', externalAuthToken, 400)
135
136 await waitUntilLog(server, 'expired external auth token')
137 })
138
139 it('Should auto login Cyan, create the user and use the token', async function () {
140 {
141 const res = await loginExternal({
142 server,
143 npmName: 'test-external-auth-one',
144 authName: 'external-auth-1',
145 query: {
146 username: 'cyan'
147 },
148 username: 'cyan'
149 })
150
151 cyanAccessToken = res.access_token
152 cyanRefreshToken = res.refresh_token
153 }
154
155 {
156 const res = await getMyUserInformation(server.url, cyanAccessToken)
157
158 const body: User = res.body
159 expect(body.username).to.equal('cyan')
160 expect(body.account.displayName).to.equal('cyan')
161 expect(body.email).to.equal('cyan@example.com')
162 expect(body.role).to.equal(UserRole.USER)
163 }
164 })
165
166 it('Should auto login Kefka, create the user and use the token', async function () {
167 {
168 const res = await loginExternal({
169 server,
170 npmName: 'test-external-auth-one',
171 authName: 'external-auth-2',
172 username: 'kefka'
173 })
174
175 kefkaAccessToken = res.access_token
176 kefkaRefreshToken = res.refresh_token
177 }
178
179 {
180 const res = await getMyUserInformation(server.url, kefkaAccessToken)
181
182 const body: User = res.body
183 expect(body.username).to.equal('kefka')
184 expect(body.account.displayName).to.equal('Kefka Palazzo')
185 expect(body.email).to.equal('kefka@example.com')
186 expect(body.role).to.equal(UserRole.ADMINISTRATOR)
187 }
188 })
189
190 it('Should refresh Cyan token, but not Kefka token', async function () {
191 {
192 const resRefresh = await refreshToken(server, cyanRefreshToken)
193 cyanAccessToken = resRefresh.body.access_token
194 cyanRefreshToken = resRefresh.body.refresh_token
195
196 const res = await getMyUserInformation(server.url, cyanAccessToken)
197 const user: User = res.body
198 expect(user.username).to.equal('cyan')
199 }
200
201 {
202 await refreshToken(server, kefkaRefreshToken, 400)
203 }
204 })
205
206 it('Should update Cyan profile', async function () {
207 await updateMyUser({
208 url: server.url,
209 accessToken: cyanAccessToken,
210 displayName: 'Cyan Garamonde',
211 description: 'Retainer to the king of Doma'
212 })
213
214 const res = await getMyUserInformation(server.url, cyanAccessToken)
215
216 const body: User = res.body
217 expect(body.account.displayName).to.equal('Cyan Garamonde')
218 expect(body.account.description).to.equal('Retainer to the king of Doma')
219 })
220
221 it('Should logout Cyan', async function () {
222 await logout(server.url, cyanAccessToken)
223 })
224
225 it('Should have logged out Cyan', async function () {
226 await waitUntilLog(server, 'On logout cyan')
227
228 await getMyUserInformation(server.url, cyanAccessToken, 401)
229 })
230
231 it('Should login Cyan and keep the old existing profile', async function () {
232 {
233 const res = await loginExternal({
234 server,
235 npmName: 'test-external-auth-one',
236 authName: 'external-auth-1',
237 query: {
238 username: 'cyan'
239 },
240 username: 'cyan'
241 })
242
243 cyanAccessToken = res.access_token
244 }
245
246 const res = await getMyUserInformation(server.url, cyanAccessToken)
247
248 const body: User = res.body
249 expect(body.username).to.equal('cyan')
250 expect(body.account.displayName).to.equal('Cyan Garamonde')
251 expect(body.account.description).to.equal('Retainer to the king of Doma')
252 expect(body.role).to.equal(UserRole.USER)
253 })
254
255 it('Should reject token of Kefka by the plugin hook', async function () {
256 this.timeout(10000)
257
258 await wait(5000)
259
260 await getMyUserInformation(server.url, kefkaAccessToken, 401)
261 })
262
263 it('Should unregister external-auth-2 and do not login existing Kefka', async function () {
264 await updatePluginSettings({
265 url: server.url,
266 accessToken: server.accessToken,
267 npmName: 'peertube-plugin-test-external-auth-one',
268 settings: { disableKefka: true }
269 })
270
271 await userLogin(server, { username: 'kefka', password: 'fake' }, 400)
272
273 await loginExternal({
274 server,
275 npmName: 'test-external-auth-one',
276 authName: 'external-auth-2',
277 query: {
278 username: 'kefka'
279 },
280 username: 'kefka',
281 statusCodeExpected: 404
282 })
283 })
284
285 it('Should have disabled this auth', async function () {
286 const res = await getConfig(server.url)
287
288 const config: ServerConfig = res.body
289
290 const auths = config.plugin.registeredExternalAuths
291 expect(auths).to.have.lengthOf(2)
292
293 const auth1 = auths.find(a => a.authName === 'external-auth-2')
294 expect(auth1).to.not.exist
295 })
296
297 it('Should uninstall the plugin one and do not login Cyan', async function () {
298 await uninstallPlugin({
299 url: server.url,
300 accessToken: server.accessToken,
301 npmName: 'peertube-plugin-test-external-auth-one'
302 })
303
304 await loginExternal({
305 server,
306 npmName: 'test-external-auth-one',
307 authName: 'external-auth-1',
308 query: {
309 username: 'cyan'
310 },
311 username: 'cyan',
312 statusCodeExpected: 404
313 })
314 })
315
316 it('Should display the correct configuration', async function () {
317 const res = await getConfig(server.url)
318
319 const config: ServerConfig = res.body
320
321 const auths = config.plugin.registeredExternalAuths
322 expect(auths).to.have.lengthOf(1)
323
324 const auth2 = auths.find((a) => a.authName === 'external-auth-2')
325 expect(auth2).to.not.exist
326 })
327
328 after(async function () {
329 await cleanupTests([ server ])
330 })
331})
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index 6a5ea4641..6c1fd40ba 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -1,34 +1,27 @@
1/* tslint:disable:no-unused-expression */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai' 3import * as chai from 'chai'
4import 'mocha' 4import 'mocha'
5import { 5import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../shared/extra-utils/server/servers'
6 cleanupTests,
7 flushAndRunMultipleServers,
8 flushAndRunServer, killallServers, reRunServer,
9 ServerInfo,
10 waitUntilLog
11} from '../../../shared/extra-utils/server/servers'
12import { 6import {
13 addVideoCommentReply, 7 addVideoCommentReply,
14 addVideoCommentThread, 8 addVideoCommentThread,
15 deleteVideoComment, 9 doubleFollow,
10 getConfig,
16 getPluginTestPath, 11 getPluginTestPath,
17 getVideosList,
18 installPlugin,
19 removeVideo,
20 setAccessTokensToServers,
21 updateVideo,
22 uploadVideo,
23 viewVideo,
24 getVideosListPagination,
25 getVideo, 12 getVideo,
26 getVideoCommentThreads, 13 getVideoCommentThreads,
14 getVideosList,
15 getVideosListPagination,
27 getVideoThreadComments, 16 getVideoThreadComments,
28 getVideoWithToken, 17 getVideoWithToken,
18 installPlugin,
19 registerUser,
20 setAccessTokensToServers,
29 setDefaultVideoChannel, 21 setDefaultVideoChannel,
30 waitJobs, 22 updateVideo,
31 doubleFollow, getConfig, registerUser 23 uploadVideo,
24 waitJobs
32} from '../../../shared/extra-utils' 25} from '../../../shared/extra-utils'
33import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' 26import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
34import { VideoDetails } from '../../../shared/models/videos' 27import { VideoDetails } from '../../../shared/models/videos'
@@ -140,7 +133,7 @@ describe('Test plugin filter hooks', function () {
140 } 133 }
141 134
142 it('Should blacklist on upload', async function () { 135 it('Should blacklist on upload', async function () {
143 const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'video please blacklist me' }) 136 const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video please blacklist me' })
144 await checkIsBlacklisted(res, true) 137 await checkIsBlacklisted(res, true)
145 }) 138 })
146 139
@@ -157,18 +150,18 @@ describe('Test plugin filter hooks', function () {
157 }) 150 })
158 151
159 it('Should blacklist on update', async function () { 152 it('Should blacklist on update', async function () {
160 const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'video' }) 153 const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
161 const videoId = res.body.video.uuid 154 const videoId = res.body.video.uuid
162 await checkIsBlacklisted(res, false) 155 await checkIsBlacklisted(res, false)
163 156
164 await updateVideo(servers[ 0 ].url, servers[ 0 ].accessToken, videoId, { name: 'please blacklist me' }) 157 await updateVideo(servers[0].url, servers[0].accessToken, videoId, { name: 'please blacklist me' })
165 await checkIsBlacklisted(res, true) 158 await checkIsBlacklisted(res, true)
166 }) 159 })
167 160
168 it('Should blacklist on remote upload', async function () { 161 it('Should blacklist on remote upload', async function () {
169 this.timeout(45000) 162 this.timeout(45000)
170 163
171 const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'remote please blacklist me' }) 164 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'remote please blacklist me' })
172 await waitJobs(servers) 165 await waitJobs(servers)
173 166
174 await checkIsBlacklisted(res, true) 167 await checkIsBlacklisted(res, true)
@@ -177,7 +170,7 @@ describe('Test plugin filter hooks', function () {
177 it('Should blacklist on remote update', async function () { 170 it('Should blacklist on remote update', async function () {
178 this.timeout(45000) 171 this.timeout(45000)
179 172
180 const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video' }) 173 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video' })
181 await waitJobs(servers) 174 await waitJobs(servers)
182 175
183 const videoId = res.body.video.uuid 176 const videoId = res.body.video.uuid
diff --git a/server/tests/plugins/id-and-pass-auth.ts b/server/tests/plugins/id-and-pass-auth.ts
new file mode 100644
index 000000000..cbba638c2
--- /dev/null
+++ b/server/tests/plugins/id-and-pass-auth.ts
@@ -0,0 +1,245 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
5import {
6 getMyUserInformation,
7 getPluginTestPath,
8 installPlugin,
9 logout,
10 setAccessTokensToServers,
11 uninstallPlugin,
12 updateMyUser,
13 userLogin,
14 wait,
15 login, refreshToken, getConfig, updatePluginSettings, getUsersList
16} from '../../../shared/extra-utils'
17import { User, UserRole, ServerConfig } from '@shared/models'
18import { expect } from 'chai'
19
20describe('Test id and pass auth plugins', function () {
21 let server: ServerInfo
22
23 let crashAccessToken: string
24 let crashRefreshToken: string
25
26 let lagunaAccessToken: string
27 let lagunaRefreshToken: string
28
29 before(async function () {
30 this.timeout(30000)
31
32 server = await flushAndRunServer(1)
33 await setAccessTokensToServers([ server ])
34
35 for (const suffix of [ 'one', 'two', 'three' ]) {
36 await installPlugin({
37 url: server.url,
38 accessToken: server.accessToken,
39 path: getPluginTestPath('-id-pass-auth-' + suffix)
40 })
41 }
42 })
43
44 it('Should display the correct configuration', async function () {
45 const res = await getConfig(server.url)
46
47 const config: ServerConfig = res.body
48
49 const auths = config.plugin.registeredIdAndPassAuths
50 expect(auths).to.have.lengthOf(8)
51
52 const crashAuth = auths.find(a => a.authName === 'crash-auth')
53 expect(crashAuth).to.exist
54 expect(crashAuth.npmName).to.equal('peertube-plugin-test-id-pass-auth-one')
55 expect(crashAuth.weight).to.equal(50)
56 })
57
58 it('Should not login', async function () {
59 await userLogin(server, { username: 'toto', password: 'password' }, 400)
60 })
61
62 it('Should login Spyro, create the user and use the token', async function () {
63 const accessToken = await userLogin(server, { username: 'spyro', password: 'spyro password' })
64
65 const res = await getMyUserInformation(server.url, accessToken)
66
67 const body: User = res.body
68 expect(body.username).to.equal('spyro')
69 expect(body.account.displayName).to.equal('Spyro the Dragon')
70 expect(body.role).to.equal(UserRole.USER)
71 })
72
73 it('Should login Crash, create the user and use the token', async function () {
74 {
75 const res = await login(server.url, server.client, { username: 'crash', password: 'crash password' })
76 crashAccessToken = res.body.access_token
77 crashRefreshToken = res.body.refresh_token
78 }
79
80 {
81 const res = await getMyUserInformation(server.url, crashAccessToken)
82
83 const body: User = res.body
84 expect(body.username).to.equal('crash')
85 expect(body.account.displayName).to.equal('Crash Bandicoot')
86 expect(body.role).to.equal(UserRole.MODERATOR)
87 }
88 })
89
90 it('Should login the first Laguna, create the user and use the token', async function () {
91 {
92 const res = await login(server.url, server.client, { username: 'laguna', password: 'laguna password' })
93 lagunaAccessToken = res.body.access_token
94 lagunaRefreshToken = res.body.refresh_token
95 }
96
97 {
98 const res = await getMyUserInformation(server.url, lagunaAccessToken)
99
100 const body: User = res.body
101 expect(body.username).to.equal('laguna')
102 expect(body.account.displayName).to.equal('laguna')
103 expect(body.role).to.equal(UserRole.USER)
104 }
105 })
106
107 it('Should refresh crash token, but not laguna token', async function () {
108 {
109 const resRefresh = await refreshToken(server, crashRefreshToken)
110 crashAccessToken = resRefresh.body.access_token
111 crashRefreshToken = resRefresh.body.refresh_token
112
113 const res = await getMyUserInformation(server.url, crashAccessToken)
114 const user: User = res.body
115 expect(user.username).to.equal('crash')
116 }
117
118 {
119 await refreshToken(server, lagunaRefreshToken, 400)
120 }
121 })
122
123 it('Should update Crash profile', async function () {
124 await updateMyUser({
125 url: server.url,
126 accessToken: crashAccessToken,
127 displayName: 'Beautiful Crash',
128 description: 'Mutant eastern barred bandicoot'
129 })
130
131 const res = await getMyUserInformation(server.url, crashAccessToken)
132
133 const body: User = res.body
134 expect(body.account.displayName).to.equal('Beautiful Crash')
135 expect(body.account.description).to.equal('Mutant eastern barred bandicoot')
136 })
137
138 it('Should logout Crash', async function () {
139 await logout(server.url, crashAccessToken)
140 })
141
142 it('Should have logged out Crash', async function () {
143 await waitUntilLog(server, 'On logout for auth 1 - 2')
144
145 await getMyUserInformation(server.url, crashAccessToken, 401)
146 })
147
148 it('Should login Crash and keep the old existing profile', async function () {
149 crashAccessToken = await userLogin(server, { username: 'crash', password: 'crash password' })
150
151 const res = await getMyUserInformation(server.url, crashAccessToken)
152
153 const body: User = res.body
154 expect(body.username).to.equal('crash')
155 expect(body.account.displayName).to.equal('Beautiful Crash')
156 expect(body.account.description).to.equal('Mutant eastern barred bandicoot')
157 expect(body.role).to.equal(UserRole.MODERATOR)
158 })
159
160 it('Should reject token of laguna by the plugin hook', async function () {
161 this.timeout(10000)
162
163 await wait(5000)
164
165 await getMyUserInformation(server.url, lagunaAccessToken, 401)
166 })
167
168 it('Should reject an invalid username, email, role or display name', async function () {
169 await userLogin(server, { username: 'ward', password: 'ward password' }, 400)
170 await waitUntilLog(server, 'valid username')
171
172 await userLogin(server, { username: 'kiros', password: 'kiros password' }, 400)
173 await waitUntilLog(server, 'valid display name')
174
175 await userLogin(server, { username: 'raine', password: 'raine password' }, 400)
176 await waitUntilLog(server, 'valid role')
177
178 await userLogin(server, { username: 'ellone', password: 'elonne password' }, 400)
179 await waitUntilLog(server, 'valid email')
180 })
181
182 it('Should unregister spyro-auth and do not login existing Spyro', async function () {
183 await updatePluginSettings({
184 url: server.url,
185 accessToken: server.accessToken,
186 npmName: 'peertube-plugin-test-id-pass-auth-one',
187 settings: { disableSpyro: true }
188 })
189
190 await userLogin(server, { username: 'spyro', password: 'spyro password' }, 400)
191 await userLogin(server, { username: 'spyro', password: 'fake' }, 400)
192 })
193
194 it('Should have disabled this auth', async function () {
195 const res = await getConfig(server.url)
196
197 const config: ServerConfig = res.body
198
199 const auths = config.plugin.registeredIdAndPassAuths
200 expect(auths).to.have.lengthOf(7)
201
202 const spyroAuth = auths.find(a => a.authName === 'spyro-auth')
203 expect(spyroAuth).to.not.exist
204 })
205
206 it('Should uninstall the plugin one and do not login existing Crash', async function () {
207 await uninstallPlugin({
208 url: server.url,
209 accessToken: server.accessToken,
210 npmName: 'peertube-plugin-test-id-pass-auth-one'
211 })
212
213 await userLogin(server, { username: 'crash', password: 'crash password' }, 400)
214 })
215
216 it('Should display the correct configuration', async function () {
217 const res = await getConfig(server.url)
218
219 const config: ServerConfig = res.body
220
221 const auths = config.plugin.registeredIdAndPassAuths
222 expect(auths).to.have.lengthOf(6)
223
224 const crashAuth = auths.find(a => a.authName === 'crash-auth')
225 expect(crashAuth).to.not.exist
226 })
227
228 it('Should display plugin auth information in users list', async function () {
229 const res = await getUsersList(server.url, server.accessToken)
230
231 const users: User[] = res.body.data
232
233 const root = users.find(u => u.username === 'root')
234 const crash = users.find(u => u.username === 'crash')
235 const laguna = users.find(u => u.username === 'laguna')
236
237 expect(root.pluginAuth).to.be.null
238 expect(crash.pluginAuth).to.equal('peertube-plugin-test-id-pass-auth-one')
239 expect(laguna.pluginAuth).to.equal('peertube-plugin-test-id-pass-auth-two')
240 })
241
242 after(async function () {
243 await cleanupTests([ server ])
244 })
245})
diff --git a/server/tests/plugins/index.ts b/server/tests/plugins/index.ts
index f41708055..39c4c958a 100644
--- a/server/tests/plugins/index.ts
+++ b/server/tests/plugins/index.ts
@@ -1,4 +1,9 @@
1import './action-hooks' 1import './action-hooks'
2import './id-and-pass-auth'
3import './external-auth'
2import './filter-hooks' 4import './filter-hooks'
3import './translations' 5import './translations'
4import './video-constants' 6import './video-constants'
7import './plugin-helpers'
8import './plugin-router'
9import './plugin-storage'
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts
new file mode 100644
index 000000000..0915603d0
--- /dev/null
+++ b/server/tests/plugins/plugin-helpers.ts
@@ -0,0 +1,210 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import {
5 checkVideoFilesWereRemoved,
6 doubleFollow,
7 getPluginTestPath,
8 getVideo,
9 installPlugin,
10 makePostBodyRequest,
11 setAccessTokensToServers,
12 uploadVideoAndGetId,
13 viewVideo,
14 getVideosList,
15 waitJobs
16} from '../../../shared/extra-utils'
17import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
18import { expect } from 'chai'
19
20function postCommand (server: ServerInfo, command: string, bodyArg?: object) {
21 const body = { command }
22 if (bodyArg) Object.assign(body, bodyArg)
23
24 return makePostBodyRequest({
25 url: server.url,
26 path: '/plugins/test-four/router/commander',
27 fields: body,
28 statusCodeExpected: 204
29 })
30}
31
32describe('Test plugin helpers', function () {
33 let servers: ServerInfo[]
34
35 before(async function () {
36 this.timeout(60000)
37
38 servers = await flushAndRunMultipleServers(2)
39 await setAccessTokensToServers(servers)
40
41 await doubleFollow(servers[0], servers[1])
42
43 await installPlugin({
44 url: servers[0].url,
45 accessToken: servers[0].accessToken,
46 path: getPluginTestPath('-four')
47 })
48 })
49
50 describe('Logger', function () {
51
52 it('Should have logged things', async function () {
53 await waitUntilLog(servers[0], 'localhost:' + servers[0].port + ' peertube-plugin-test-four', 1, false)
54 await waitUntilLog(servers[0], 'Hello world from plugin four', 1)
55 })
56 })
57
58 describe('Database', function () {
59
60 it('Should have made a query', async function () {
61 await waitUntilLog(servers[0], `root email is admin${servers[0].internalServerNumber}@example.com`)
62 })
63 })
64
65 describe('Config', function () {
66
67 it('Should have the correct webserver url', async function () {
68 await waitUntilLog(servers[0], `server url is http://localhost:${servers[0].port}`)
69 })
70 })
71
72 describe('Server', function () {
73
74 it('Should get the server actor', async function () {
75 await waitUntilLog(servers[0], 'server actor name is peertube')
76 })
77 })
78
79 describe('Moderation', function () {
80 let videoUUIDServer1: string
81
82 before(async function () {
83 this.timeout(15000)
84
85 {
86 const res = await uploadVideoAndGetId({ server: servers[0], videoName: 'video server 1' })
87 videoUUIDServer1 = res.uuid
88 }
89
90 {
91 await uploadVideoAndGetId({ server: servers[1], videoName: 'video server 2' })
92 }
93
94 await waitJobs(servers)
95
96 const res = await getVideosList(servers[0].url)
97 const videos = res.body.data
98
99 expect(videos).to.have.lengthOf(2)
100 })
101
102 it('Should mute server 2', async function () {
103 this.timeout(10000)
104 await postCommand(servers[0], 'blockServer', { hostToBlock: `localhost:${servers[1].port}` })
105
106 const res = await getVideosList(servers[0].url)
107 const videos = res.body.data
108
109 expect(videos).to.have.lengthOf(1)
110 expect(videos[0].name).to.equal('video server 1')
111 })
112
113 it('Should unmute server 2', async function () {
114 await postCommand(servers[0], 'unblockServer', { hostToUnblock: `localhost:${servers[1].port}` })
115
116 const res = await getVideosList(servers[0].url)
117 const videos = res.body.data
118
119 expect(videos).to.have.lengthOf(2)
120 })
121
122 it('Should mute account of server 2', async function () {
123 await postCommand(servers[0], 'blockAccount', { handleToBlock: `root@localhost:${servers[1].port}` })
124
125 const res = await getVideosList(servers[0].url)
126 const videos = res.body.data
127
128 expect(videos).to.have.lengthOf(1)
129 expect(videos[0].name).to.equal('video server 1')
130 })
131
132 it('Should unmute account of server 2', async function () {
133 await postCommand(servers[0], 'unblockAccount', { handleToUnblock: `root@localhost:${servers[1].port}` })
134
135 const res = await getVideosList(servers[0].url)
136 const videos = res.body.data
137
138 expect(videos).to.have.lengthOf(2)
139 })
140
141 it('Should blacklist video', async function () {
142 this.timeout(10000)
143
144 await postCommand(servers[0], 'blacklist', { videoUUID: videoUUIDServer1, unfederate: true })
145
146 await waitJobs(servers)
147
148 for (const server of servers) {
149 const res = await getVideosList(server.url)
150 const videos = res.body.data
151
152 expect(videos).to.have.lengthOf(1)
153 expect(videos[0].name).to.equal('video server 2')
154 }
155 })
156
157 it('Should unblacklist video', async function () {
158 this.timeout(10000)
159
160 await postCommand(servers[0], 'unblacklist', { videoUUID: videoUUIDServer1 })
161
162 await waitJobs(servers)
163
164 for (const server of servers) {
165 const res = await getVideosList(server.url)
166 const videos = res.body.data
167
168 expect(videos).to.have.lengthOf(2)
169 }
170 })
171 })
172
173 describe('Videos', function () {
174 let videoUUID: string
175
176 before(async () => {
177 const res = await uploadVideoAndGetId({ server: servers[0], videoName: 'video1' })
178 videoUUID = res.uuid
179 })
180
181 it('Should remove a video after a view', async function () {
182 this.timeout(20000)
183
184 // Should not throw -> video exists
185 await getVideo(servers[0].url, videoUUID)
186 // Should delete the video
187 await viewVideo(servers[0].url, videoUUID)
188
189 await waitUntilLog(servers[0], 'Video deleted by plugin four.')
190
191 try {
192 // Should throw because the video should have been deleted
193 await getVideo(servers[0].url, videoUUID)
194 throw new Error('Video exists')
195 } catch (err) {
196 if (err.message.includes('exists')) throw err
197 }
198
199 await checkVideoFilesWereRemoved(videoUUID, servers[0].internalServerNumber)
200 })
201
202 it('Should have fetched the video by URL', async function () {
203 await waitUntilLog(servers[0], `video from DB uuid is ${videoUUID}`)
204 })
205 })
206
207 after(async function () {
208 await cleanupTests(servers)
209 })
210})
diff --git a/server/tests/plugins/plugin-router.ts b/server/tests/plugins/plugin-router.ts
new file mode 100644
index 000000000..cf4130f4b
--- /dev/null
+++ b/server/tests/plugins/plugin-router.ts
@@ -0,0 +1,91 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
5import {
6 getPluginTestPath,
7 installPlugin,
8 makeGetRequest,
9 makePostBodyRequest,
10 setAccessTokensToServers, uninstallPlugin
11} from '../../../shared/extra-utils'
12import { expect } from 'chai'
13
14describe('Test plugin helpers', function () {
15 let server: ServerInfo
16 const basePaths = [
17 '/plugins/test-five/router/',
18 '/plugins/test-five/0.0.1/router/'
19 ]
20
21 before(async function () {
22 this.timeout(30000)
23
24 server = await flushAndRunServer(1)
25 await setAccessTokensToServers([ server ])
26
27 await installPlugin({
28 url: server.url,
29 accessToken: server.accessToken,
30 path: getPluginTestPath('-five')
31 })
32 })
33
34 it('Should answer "pong"', async function () {
35 for (const path of basePaths) {
36 const res = await makeGetRequest({
37 url: server.url,
38 path: path + 'ping',
39 statusCodeExpected: 200
40 })
41
42 expect(res.body.message).to.equal('pong')
43 }
44 })
45
46 it('Should mirror post body', async function () {
47 const body = {
48 hello: 'world',
49 riri: 'fifi',
50 loulou: 'picsou'
51 }
52
53 for (const path of basePaths) {
54 const res = await makePostBodyRequest({
55 url: server.url,
56 path: path + 'form/post/mirror',
57 fields: body,
58 statusCodeExpected: 200
59 })
60
61 expect(res.body).to.deep.equal(body)
62 }
63 })
64
65 it('Should remove the plugin and remove the routes', async function () {
66 await uninstallPlugin({
67 url: server.url,
68 accessToken: server.accessToken,
69 npmName: 'peertube-plugin-test-five'
70 })
71
72 for (const path of basePaths) {
73 await makeGetRequest({
74 url: server.url,
75 path: path + 'ping',
76 statusCodeExpected: 404
77 })
78
79 await makePostBodyRequest({
80 url: server.url,
81 path: path + 'ping',
82 fields: {},
83 statusCodeExpected: 404
84 })
85 }
86 })
87
88 after(async function () {
89 await cleanupTests([ server ])
90 })
91})
diff --git a/server/tests/plugins/plugin-storage.ts b/server/tests/plugins/plugin-storage.ts
new file mode 100644
index 000000000..356692eb9
--- /dev/null
+++ b/server/tests/plugins/plugin-storage.ts
@@ -0,0 +1,30 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { getPluginTestPath, installPlugin, setAccessTokensToServers } from '../../../shared/extra-utils'
5import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
6
7describe('Test plugin storage', function () {
8 let server: ServerInfo
9
10 before(async function () {
11 this.timeout(30000)
12
13 server = await flushAndRunServer(1)
14 await setAccessTokensToServers([ server ])
15
16 await installPlugin({
17 url: server.url,
18 accessToken: server.accessToken,
19 path: getPluginTestPath('-six')
20 })
21 })
22
23 it('Should correctly store a subkey', async function () {
24 await waitUntilLog(server, 'superkey stored value is toto')
25 })
26
27 after(async function () {
28 await cleanupTests([ server ])
29 })
30})
diff --git a/server/tests/plugins/translations.ts b/server/tests/plugins/translations.ts
index 88d91a033..8dc2043b8 100644
--- a/server/tests/plugins/translations.ts
+++ b/server/tests/plugins/translations.ts
@@ -1,38 +1,15 @@
1/* tslint:disable:no-unused-expression */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai' 3import * as chai from 'chai'
4import 'mocha' 4import 'mocha'
5import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
5import { 6import {
6 cleanupTests,
7 flushAndRunMultipleServers,
8 flushAndRunServer, killallServers, reRunServer,
9 ServerInfo,
10 waitUntilLog
11} from '../../../shared/extra-utils/server/servers'
12import {
13 addVideoCommentReply,
14 addVideoCommentThread,
15 deleteVideoComment,
16 getPluginTestPath, 7 getPluginTestPath,
17 getVideosList, 8 getPluginTranslations,
18 installPlugin, 9 installPlugin,
19 removeVideo,
20 setAccessTokensToServers, 10 setAccessTokensToServers,
21 updateVideo, 11 uninstallPlugin
22 uploadVideo,
23 viewVideo,
24 getVideosListPagination,
25 getVideo,
26 getVideoCommentThreads,
27 getVideoThreadComments,
28 getVideoWithToken,
29 setDefaultVideoChannel,
30 waitJobs,
31 doubleFollow, getVideoLanguages, getVideoLicences, getVideoCategories, uninstallPlugin, getPluginTranslations
32} from '../../../shared/extra-utils' 12} from '../../../shared/extra-utils'
33import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
34import { VideoDetails } from '../../../shared/models/videos'
35import { getYoutubeVideoUrl, importVideo } from '../../../shared/extra-utils/videos/video-imports'
36 13
37const expect = chai.expect 14const expect = chai.expect
38 15
@@ -69,7 +46,7 @@ describe('Test plugin translations', function () {
69 46
70 expect(res.body).to.deep.equal({ 47 expect(res.body).to.deep.equal({
71 'peertube-plugin-test': { 48 'peertube-plugin-test': {
72 'Hi': 'Coucou' 49 Hi: 'Coucou'
73 }, 50 },
74 'peertube-plugin-test-two': { 51 'peertube-plugin-test-two': {
75 'Hello world': 'Bonjour le monde' 52 'Hello world': 'Bonjour le monde'
@@ -95,7 +72,7 @@ describe('Test plugin translations', function () {
95 72
96 expect(res.body).to.deep.equal({ 73 expect(res.body).to.deep.equal({
97 'peertube-plugin-test': { 74 'peertube-plugin-test': {
98 'Hi': 'Coucou' 75 Hi: 'Coucou'
99 } 76 }
100 }) 77 })
101 } 78 }
diff --git a/server/tests/plugins/video-constants.ts b/server/tests/plugins/video-constants.ts
index 6562e2b45..fec9196e2 100644
--- a/server/tests/plugins/video-constants.ts
+++ b/server/tests/plugins/video-constants.ts
@@ -1,38 +1,21 @@
1/* tslint:disable:no-unused-expression */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai' 3import * as chai from 'chai'
4import 'mocha' 4import 'mocha'
5import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
5import { 6import {
6 cleanupTests, 7 createVideoPlaylist,
7 flushAndRunMultipleServers,
8 flushAndRunServer, killallServers, reRunServer,
9 ServerInfo,
10 waitUntilLog
11} from '../../../shared/extra-utils/server/servers'
12import {
13 addVideoCommentReply,
14 addVideoCommentThread,
15 deleteVideoComment,
16 getPluginTestPath, 8 getPluginTestPath,
17 getVideosList, 9 getVideo,
10 getVideoCategories,
11 getVideoLanguages,
12 getVideoLicences, getVideoPlaylistPrivacies, getVideoPrivacies,
18 installPlugin, 13 installPlugin,
19 removeVideo,
20 setAccessTokensToServers, 14 setAccessTokensToServers,
21 updateVideo, 15 uninstallPlugin,
22 uploadVideo, 16 uploadVideo
23 viewVideo,
24 getVideosListPagination,
25 getVideo,
26 getVideoCommentThreads,
27 getVideoThreadComments,
28 getVideoWithToken,
29 setDefaultVideoChannel,
30 waitJobs,
31 doubleFollow, getVideoLanguages, getVideoLicences, getVideoCategories, uninstallPlugin
32} from '../../../shared/extra-utils' 17} from '../../../shared/extra-utils'
33import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' 18import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos'
34import { VideoDetails } from '../../../shared/models/videos'
35import { getYoutubeVideoUrl, importVideo } from '../../../shared/extra-utils/videos/video-imports'
36 19
37const expect = chai.expect 20const expect = chai.expect
38 21
@@ -85,6 +68,35 @@ describe('Test plugin altering video constants', function () {
85 expect(licences[43]).to.equal('High best licence') 68 expect(licences[43]).to.equal('High best licence')
86 }) 69 })
87 70
71 it('Should have updated video privacies', async function () {
72 const res = await getVideoPrivacies(server.url)
73 const privacies = res.body
74
75 expect(privacies[1]).to.exist
76 expect(privacies[2]).to.not.exist
77 expect(privacies[3]).to.exist
78 expect(privacies[4]).to.exist
79 })
80
81 it('Should have updated playlist privacies', async function () {
82 const res = await getVideoPlaylistPrivacies(server.url)
83 const playlistPrivacies = res.body
84
85 expect(playlistPrivacies[1]).to.exist
86 expect(playlistPrivacies[2]).to.exist
87 expect(playlistPrivacies[3]).to.not.exist
88 })
89
90 it('Should not be able to create a video with this privacy', async function () {
91 const attrs = { name: 'video', privacy: 2 }
92 await uploadVideo(server.url, server.accessToken, attrs, 400)
93 })
94
95 it('Should not be able to create a video with this privacy', async function () {
96 const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
97 await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attrs, expectedStatus: 400 })
98 })
99
88 it('Should be able to upload a video with these values', async function () { 100 it('Should be able to upload a video with these values', async function () {
89 const attrs = { name: 'video', category: 42, licence: 42, language: 'al_bhed2' } 101 const attrs = { name: 'video', category: 42, licence: 42, language: 'al_bhed2' }
90 const resUpload = await uploadVideo(server.url, server.accessToken, attrs) 102 const resUpload = await uploadVideo(server.url, server.accessToken, attrs)
@@ -97,40 +109,59 @@ describe('Test plugin altering video constants', function () {
97 expect(video.category.label).to.equal('Best category') 109 expect(video.category.label).to.equal('Best category')
98 }) 110 })
99 111
100 it('Should uninstall the plugin and reset languages, categories and licences', async function () { 112 it('Should uninstall the plugin and reset languages, categories, licences and privacies', async function () {
101 await uninstallPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-test-three' }) 113 await uninstallPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-test-three' })
102 114
103 { 115 {
104 const res = await getVideoLanguages(server.url) 116 const res = await getVideoLanguages(server.url)
105 const languages = res.body 117 const languages = res.body
106 118
107 expect(languages[ 'en' ]).to.equal('English') 119 expect(languages['en']).to.equal('English')
108 expect(languages[ 'fr' ]).to.equal('French') 120 expect(languages['fr']).to.equal('French')
109 121
110 expect(languages[ 'al_bhed' ]).to.not.exist 122 expect(languages['al_bhed']).to.not.exist
111 expect(languages[ 'al_bhed2' ]).to.not.exist 123 expect(languages['al_bhed2']).to.not.exist
112 } 124 }
113 125
114 { 126 {
115 const res = await getVideoCategories(server.url) 127 const res = await getVideoCategories(server.url)
116 const categories = res.body 128 const categories = res.body
117 129
118 expect(categories[ 1 ]).to.equal('Music') 130 expect(categories[1]).to.equal('Music')
119 expect(categories[ 2 ]).to.equal('Films') 131 expect(categories[2]).to.equal('Films')
120 132
121 expect(categories[ 42 ]).to.not.exist 133 expect(categories[42]).to.not.exist
122 expect(categories[ 43 ]).to.not.exist 134 expect(categories[43]).to.not.exist
123 } 135 }
124 136
125 { 137 {
126 const res = await getVideoLicences(server.url) 138 const res = await getVideoLicences(server.url)
127 const licences = res.body 139 const licences = res.body
128 140
129 expect(licences[ 1 ]).to.equal('Attribution') 141 expect(licences[1]).to.equal('Attribution')
130 expect(licences[ 7 ]).to.equal('Public Domain Dedication') 142 expect(licences[7]).to.equal('Public Domain Dedication')
143
144 expect(licences[42]).to.not.exist
145 expect(licences[43]).to.not.exist
146 }
147
148 {
149 const res = await getVideoPrivacies(server.url)
150 const privacies = res.body
151
152 expect(privacies[1]).to.exist
153 expect(privacies[2]).to.exist
154 expect(privacies[3]).to.exist
155 expect(privacies[4]).to.exist
156 }
157
158 {
159 const res = await getVideoPlaylistPrivacies(server.url)
160 const playlistPrivacies = res.body
131 161
132 expect(licences[ 42 ]).to.not.exist 162 expect(playlistPrivacies[1]).to.exist
133 expect(licences[ 43 ]).to.not.exist 163 expect(playlistPrivacies[2]).to.exist
164 expect(playlistPrivacies[3]).to.exist
134 } 165 }
135 }) 166 })
136 167