aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-04-29 09:04:42 +0200
committerChocobozzz <chocobozzz@cpy.re>2020-05-04 16:21:39 +0200
commit9107d791e2eef9a1b24b0499dac8b9dbba8a792f (patch)
treef09b20f06008b094f3266b39063bc9785dfebf5f /server/tests
parent4a8d113b9b57d97ff13ad1608798eabca99643e4 (diff)
downloadPeerTube-9107d791e2eef9a1b24b0499dac8b9dbba8a792f.tar.gz
PeerTube-9107d791e2eef9a1b24b0499dac8b9dbba8a792f.tar.zst
PeerTube-9107d791e2eef9a1b24b0499dac8b9dbba8a792f.zip
Add external login tests
Diffstat (limited to 'server/tests')
-rw-r--r--server/tests/api/check-params/plugins.ts13
-rw-r--r--server/tests/external-plugins/auth-ldap.ts14
-rw-r--r--server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js67
-rw-r--r--server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json20
-rw-r--r--server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js31
-rw-r--r--server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json20
-rw-r--r--server/tests/plugins/external-auth.ts295
-rw-r--r--server/tests/plugins/id-and-pass-auth.ts30
-rw-r--r--server/tests/plugins/index.ts1
9 files changed, 486 insertions, 5 deletions
diff --git a/server/tests/api/check-params/plugins.ts b/server/tests/api/check-params/plugins.ts
index cf80b35c2..07ded26ee 100644
--- a/server/tests/api/check-params/plugins.ts
+++ b/server/tests/api/check-params/plugins.ts
@@ -64,6 +64,7 @@ describe('Test server plugins API validators', function () {
64 describe('With static plugin routes', function () { 64 describe('With static plugin routes', function () {
65 it('Should fail with an unknown plugin name/plugin version', async function () { 65 it('Should fail with an unknown plugin name/plugin version', async function () {
66 const paths = [ 66 const paths = [
67 '/plugins/' + pluginName + '/0.0.1/auth/fake-auth',
67 '/plugins/' + pluginName + '/0.0.1/static/images/chocobo.png', 68 '/plugins/' + pluginName + '/0.0.1/static/images/chocobo.png',
68 '/plugins/' + pluginName + '/0.0.1/client-scripts/client/common-client-plugin.js', 69 '/plugins/' + pluginName + '/0.0.1/client-scripts/client/common-client-plugin.js',
69 '/themes/' + themeName + '/0.0.1/static/images/chocobo.png', 70 '/themes/' + themeName + '/0.0.1/static/images/chocobo.png',
@@ -86,6 +87,7 @@ describe('Test server plugins API validators', function () {
86 87
87 it('Should fail with invalid versions', async function () { 88 it('Should fail with invalid versions', async function () {
88 const paths = [ 89 const paths = [
90 '/plugins/' + pluginName + '/0.0.1.1/auth/fake-auth',
89 '/plugins/' + pluginName + '/0.0.1.1/static/images/chocobo.png', 91 '/plugins/' + pluginName + '/0.0.1.1/static/images/chocobo.png',
90 '/plugins/' + pluginName + '/0.1/client-scripts/client/common-client-plugin.js', 92 '/plugins/' + pluginName + '/0.1/client-scripts/client/common-client-plugin.js',
91 '/themes/' + themeName + '/1/static/images/chocobo.png', 93 '/themes/' + themeName + '/1/static/images/chocobo.png',
@@ -112,6 +114,12 @@ describe('Test server plugins API validators', function () {
112 } 114 }
113 }) 115 })
114 116
117 it('Should fail with an unknown auth name', async function () {
118 const path = '/plugins/' + pluginName + '/' + npmVersion + '/auth/bad-auth'
119
120 await makeGetRequest({ url: server.url, path, statusCodeExpected: 404 })
121 })
122
115 it('Should fail with an unknown static file', async function () { 123 it('Should fail with an unknown static file', async function () {
116 const paths = [ 124 const paths = [
117 '/plugins/' + pluginName + '/' + npmVersion + '/static/fake/chocobo.png', 125 '/plugins/' + pluginName + '/' + npmVersion + '/static/fake/chocobo.png',
@@ -145,6 +153,9 @@ describe('Test server plugins API validators', function () {
145 for (const p of paths) { 153 for (const p of paths) {
146 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: 200 }) 154 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: 200 })
147 } 155 }
156
157 const authPath = '/plugins/' + pluginName + '/' + npmVersion + '/auth/fake-auth'
158 await makeGetRequest({ url: server.url, path: authPath, statusCodeExpected: 302 })
148 }) 159 })
149 }) 160 })
150 161
@@ -462,6 +473,8 @@ describe('Test server plugins API validators', function () {
462 }) 473 })
463 474
464 it('Should succeed with the correct parameters', async function () { 475 it('Should succeed with the correct parameters', async function () {
476 this.timeout(10000)
477
465 const it = [ 478 const it = [
466 { suffix: 'install', status: 200 }, 479 { suffix: 'install', status: 200 },
467 { suffix: 'update', status: 200 }, 480 { suffix: 'update', status: 200 },
diff --git a/server/tests/external-plugins/auth-ldap.ts b/server/tests/external-plugins/auth-ldap.ts
index 7aee986c7..0f0a08532 100644
--- a/server/tests/external-plugins/auth-ldap.ts
+++ b/server/tests/external-plugins/auth-ldap.ts
@@ -1,10 +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 'mocha' 3import 'mocha'
4import { getMyUserInformation, installPlugin, setAccessTokensToServers, updatePluginSettings, userLogin, uploadVideo, uninstallPlugin } from '../../../shared/extra-utils'
5import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
6import { User } from '@shared/models/users/user.model'
7import { expect } from 'chai' 4import { expect } from 'chai'
5import { User } from '@shared/models/users/user.model'
6import {
7 getMyUserInformation,
8 installPlugin,
9 setAccessTokensToServers,
10 uninstallPlugin,
11 updatePluginSettings,
12 uploadVideo,
13 userLogin
14} from '../../../shared/extra-utils'
15import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
8 16
9describe('Official plugin auth-ldap', function () { 17describe('Official plugin auth-ldap', function () {
10 let server: ServerInfo 18 let server: ServerInfo
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js b/server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js
new file mode 100644
index 000000000..f29fd1f30
--- /dev/null
+++ b/server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js
@@ -0,0 +1,67 @@
1async function register ({
2 registerExternalAuth,
3 peertubeHelpers
4}) {
5 {
6 const result = registerExternalAuth({
7 authName: 'external-auth-1',
8 authDisplayName: 'External Auth 1',
9 onLogout: user => peertubeHelpers.logger.info('On logout %s', user.username),
10 onAuthRequest: (req, res) => {
11 const username = req.query.username
12
13 result.userAuthenticated({
14 req,
15 res,
16 username,
17 email: username + '@example.com'
18 })
19 }
20 })
21 }
22
23 {
24 const result = registerExternalAuth({
25 authName: 'external-auth-2',
26 authDisplayName: 'External Auth 2',
27 onAuthRequest: (req, res) => {
28 result.userAuthenticated({
29 req,
30 res,
31 username: 'kefka',
32 email: 'kefka@example.com',
33 role: 0,
34 displayName: 'Kefka Palazzo'
35 })
36 },
37 hookTokenValidity: (options) => {
38 if (options.type === 'refresh') {
39 return { valid: false }
40 }
41
42 if (options.type === 'access') {
43 const token = options.token
44 const now = new Date()
45 now.setTime(now.getTime() - 5000)
46
47 const createdAt = new Date(token.createdAt)
48
49 return { valid: createdAt.getTime() >= now.getTime() }
50 }
51
52 return { valid: true }
53 }
54 })
55 }
56}
57
58async function unregister () {
59 return
60}
61
62module.exports = {
63 register,
64 unregister
65}
66
67// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json b/server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json
new file mode 100644
index 000000000..22814b047
--- /dev/null
+++ b/server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json
@@ -0,0 +1,20 @@
1{
2 "name": "peertube-plugin-test-external-auth-one",
3 "version": "0.0.1",
4 "description": "External auth one",
5 "engine": {
6 "peertube": ">=1.3.0"
7 },
8 "keywords": [
9 "peertube",
10 "plugin"
11 ],
12 "homepage": "https://github.com/Chocobozzz/PeerTube",
13 "author": "Chocobozzz",
14 "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
15 "library": "./main.js",
16 "staticDirs": {},
17 "css": [],
18 "clientScripts": [],
19 "translations": {}
20}
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js b/server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js
new file mode 100644
index 000000000..34fec1bb3
--- /dev/null
+++ b/server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js
@@ -0,0 +1,31 @@
1async function register ({
2 registerExternalAuth,
3 peertubeHelpers
4}) {
5 {
6 const result = registerExternalAuth({
7 authName: 'external-auth-3',
8 authDisplayName: 'External Auth 3',
9 onAuthRequest: (req, res) => {
10 result.userAuthenticated({
11 req,
12 res,
13 username: 'cid',
14 email: 'cid@example.com',
15 displayName: 'Cid Marquez'
16 })
17 }
18 })
19 }
20}
21
22async function unregister () {
23 return
24}
25
26module.exports = {
27 register,
28 unregister
29}
30
31// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json b/server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json
new file mode 100644
index 000000000..a5ca4d07a
--- /dev/null
+++ b/server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json
@@ -0,0 +1,20 @@
1{
2 "name": "peertube-plugin-test-external-auth-two",
3 "version": "0.0.1",
4 "description": "External auth two",
5 "engine": {
6 "peertube": ">=1.3.0"
7 },
8 "keywords": [
9 "peertube",
10 "plugin"
11 ],
12 "homepage": "https://github.com/Chocobozzz/PeerTube",
13 "author": "Chocobozzz",
14 "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
15 "library": "./main.js",
16 "staticDirs": {},
17 "css": [],
18 "clientScripts": [],
19 "translations": {}
20}
diff --git a/server/tests/plugins/external-auth.ts b/server/tests/plugins/external-auth.ts
new file mode 100644
index 000000000..a72b2829b
--- /dev/null
+++ b/server/tests/plugins/external-auth.ts
@@ -0,0 +1,295 @@
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} from '../../../shared/extra-utils'
21import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
22
23async function loginExternal (options: {
24 server: ServerInfo
25 npmName: string
26 authName: string
27 username: string
28 query?: any
29 statusCodeExpected?: number
30}) {
31 const res = await getExternalAuth({
32 url: options.server.url,
33 npmName: options.npmName,
34 npmVersion: '0.0.1',
35 authName: options.authName,
36 query: options.query,
37 statusCodeExpected: options.statusCodeExpected || 302
38 })
39
40 if (res.status !== 302) return
41
42 const location = res.header.location
43 const { externalAuthToken } = decodeQueryString(location)
44
45 const resLogin = await loginUsingExternalToken(
46 options.server,
47 options.username,
48 externalAuthToken as string
49 )
50
51 return resLogin.body
52}
53
54describe('Test external auth plugins', function () {
55 let server: ServerInfo
56
57 let cyanAccessToken: string
58 let cyanRefreshToken: string
59
60 let kefkaAccessToken: string
61 let kefkaRefreshToken: string
62
63 let externalAuthToken: string
64
65 before(async function () {
66 this.timeout(30000)
67
68 server = await flushAndRunServer(1)
69 await setAccessTokensToServers([ server ])
70
71 for (const suffix of [ 'one', 'two' ]) {
72 await installPlugin({
73 url: server.url,
74 accessToken: server.accessToken,
75 path: getPluginTestPath('-external-auth-' + suffix)
76 })
77 }
78 })
79
80 it('Should display the correct configuration', async function () {
81 const res = await getConfig(server.url)
82
83 const config: ServerConfig = res.body
84
85 const auths = config.plugin.registeredExternalAuths
86 expect(auths).to.have.lengthOf(3)
87
88 const auth2 = auths.find((a) => a.authName === 'external-auth-2')
89 expect(auth2).to.exist
90 expect(auth2.authDisplayName).to.equal('External Auth 2')
91 expect(auth2.npmName).to.equal('peertube-plugin-test-external-auth-one')
92 })
93
94 it('Should redirect for a Cyan login', async function () {
95 const res = await getExternalAuth({
96 url: server.url,
97 npmName: 'test-external-auth-one',
98 npmVersion: '0.0.1',
99 authName: 'external-auth-1',
100 query: {
101 username: 'cyan'
102 },
103 statusCodeExpected: 302
104 })
105
106 const location = res.header.location
107 expect(location.startsWith('/login?')).to.be.true
108
109 const searchParams = decodeQueryString(location)
110
111 expect(searchParams.externalAuthToken).to.exist
112 expect(searchParams.username).to.equal('cyan')
113
114 externalAuthToken = searchParams.externalAuthToken as string
115 })
116
117 it('Should reject auto external login with a missing or invalid token', async function () {
118 await loginUsingExternalToken(server, 'cyan', '', 400)
119 await loginUsingExternalToken(server, 'cyan', 'blabla', 400)
120 })
121
122 it('Should reject auto external login with a missing or invalid username', async function () {
123 await loginUsingExternalToken(server, '', externalAuthToken, 400)
124 await loginUsingExternalToken(server, '', externalAuthToken, 400)
125 })
126
127 it('Should reject auto external login with an expired token', async function () {
128 this.timeout(15000)
129
130 await wait(5000)
131
132 await loginUsingExternalToken(server, 'cyan', externalAuthToken, 400)
133
134 await waitUntilLog(server, 'expired external auth token')
135 })
136
137 it('Should auto login Cyan, create the user and use the token', async function () {
138 {
139 const res = await loginExternal({
140 server,
141 npmName: 'test-external-auth-one',
142 authName: 'external-auth-1',
143 query: {
144 username: 'cyan'
145 },
146 username: 'cyan'
147 })
148
149 cyanAccessToken = res.access_token
150 cyanRefreshToken = res.refresh_token
151 }
152
153 {
154 const res = await getMyUserInformation(server.url, cyanAccessToken)
155
156 const body: User = res.body
157 expect(body.username).to.equal('cyan')
158 expect(body.account.displayName).to.equal('cyan')
159 expect(body.email).to.equal('cyan@example.com')
160 expect(body.role).to.equal(UserRole.USER)
161 }
162 })
163
164 it('Should auto login Kefka, create the user and use the token', async function () {
165 {
166 const res = await loginExternal({
167 server,
168 npmName: 'test-external-auth-one',
169 authName: 'external-auth-2',
170 username: 'kefka'
171 })
172
173 kefkaAccessToken = res.access_token
174 kefkaRefreshToken = res.refresh_token
175 }
176
177 {
178 const res = await getMyUserInformation(server.url, kefkaAccessToken)
179
180 const body: User = res.body
181 expect(body.username).to.equal('kefka')
182 expect(body.account.displayName).to.equal('Kefka Palazzo')
183 expect(body.email).to.equal('kefka@example.com')
184 expect(body.role).to.equal(UserRole.ADMINISTRATOR)
185 }
186 })
187
188 it('Should refresh Cyan token, but not Kefka token', async function () {
189 {
190 const resRefresh = await refreshToken(server, cyanRefreshToken)
191 cyanAccessToken = resRefresh.body.access_token
192 cyanRefreshToken = resRefresh.body.refresh_token
193
194 const res = await getMyUserInformation(server.url, cyanAccessToken)
195 const user: User = res.body
196 expect(user.username).to.equal('cyan')
197 }
198
199 {
200 await refreshToken(server, kefkaRefreshToken, 400)
201 }
202 })
203
204 it('Should update Cyan profile', async function () {
205 await updateMyUser({
206 url: server.url,
207 accessToken: cyanAccessToken,
208 displayName: 'Cyan Garamonde',
209 description: 'Retainer to the king of Doma'
210 })
211
212 const res = await getMyUserInformation(server.url, cyanAccessToken)
213
214 const body: User = res.body
215 expect(body.account.displayName).to.equal('Cyan Garamonde')
216 expect(body.account.description).to.equal('Retainer to the king of Doma')
217 })
218
219 it('Should logout Cyan', async function () {
220 await logout(server.url, cyanAccessToken)
221 })
222
223 it('Should have logged out Cyan', async function () {
224 await waitUntilLog(server, 'On logout cyan')
225
226 await getMyUserInformation(server.url, cyanAccessToken, 401)
227 })
228
229 it('Should login Cyan and keep the old existing profile', async function () {
230 {
231 const res = await loginExternal({
232 server,
233 npmName: 'test-external-auth-one',
234 authName: 'external-auth-1',
235 query: {
236 username: 'cyan'
237 },
238 username: 'cyan'
239 })
240
241 cyanAccessToken = res.access_token
242 }
243
244 const res = await getMyUserInformation(server.url, cyanAccessToken)
245
246 const body: User = res.body
247 expect(body.username).to.equal('cyan')
248 expect(body.account.displayName).to.equal('Cyan Garamonde')
249 expect(body.account.description).to.equal('Retainer to the king of Doma')
250 expect(body.role).to.equal(UserRole.USER)
251 })
252
253 it('Should reject token of Kefka by the plugin hook', async function () {
254 this.timeout(10000)
255
256 await wait(5000)
257
258 await getMyUserInformation(server.url, kefkaAccessToken, 401)
259 })
260
261 it('Should uninstall the plugin one and do not login Cyan', async function () {
262 await uninstallPlugin({
263 url: server.url,
264 accessToken: server.accessToken,
265 npmName: 'peertube-plugin-test-external-auth-one'
266 })
267
268 await loginExternal({
269 server,
270 npmName: 'test-external-auth-one',
271 authName: 'external-auth-1',
272 query: {
273 username: 'cyan'
274 },
275 username: 'cyan',
276 statusCodeExpected: 404
277 })
278 })
279
280 it('Should display the correct configuration', async function () {
281 const res = await getConfig(server.url)
282
283 const config: ServerConfig = res.body
284
285 const auths = config.plugin.registeredExternalAuths
286 expect(auths).to.have.lengthOf(1)
287
288 const auth2 = auths.find((a) => a.authName === 'external-auth-2')
289 expect(auth2).to.not.exist
290 })
291
292 after(async function () {
293 await cleanupTests([ server ])
294 })
295})
diff --git a/server/tests/plugins/id-and-pass-auth.ts b/server/tests/plugins/id-and-pass-auth.ts
index c6382435d..6c10730aa 100644
--- a/server/tests/plugins/id-and-pass-auth.ts
+++ b/server/tests/plugins/id-and-pass-auth.ts
@@ -12,9 +12,9 @@ import {
12 updateMyUser, 12 updateMyUser,
13 userLogin, 13 userLogin,
14 wait, 14 wait,
15 login, refreshToken 15 login, refreshToken, getConfig
16} from '../../../shared/extra-utils' 16} from '../../../shared/extra-utils'
17import { User, UserRole } from '@shared/models' 17import { User, UserRole, ServerConfig } from '@shared/models'
18import { expect } from 'chai' 18import { expect } from 'chai'
19 19
20describe('Test id and pass auth plugins', function () { 20describe('Test id and pass auth plugins', function () {
@@ -41,6 +41,20 @@ describe('Test id and pass auth plugins', function () {
41 } 41 }
42 }) 42 })
43 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
44 it('Should not login', async function () { 58 it('Should not login', async function () {
45 await userLogin(server, { username: 'toto', password: 'password' }, 400) 59 await userLogin(server, { username: 'toto', password: 'password' }, 400)
46 }) 60 })
@@ -175,6 +189,18 @@ describe('Test id and pass auth plugins', function () {
175 await userLogin(server, { username: 'crash', password: 'crash password' }, 400) 189 await userLogin(server, { username: 'crash', password: 'crash password' }, 400)
176 }) 190 })
177 191
192 it('Should display the correct configuration', async function () {
193 const res = await getConfig(server.url)
194
195 const config: ServerConfig = res.body
196
197 const auths = config.plugin.registeredIdAndPassAuths
198 expect(auths).to.have.lengthOf(6)
199
200 const crashAuth = auths.find(a => a.authName === 'crash-auth')
201 expect(crashAuth).to.not.exist
202 })
203
178 after(async function () { 204 after(async function () {
179 await cleanupTests([ server ]) 205 await cleanupTests([ server ])
180 }) 206 })
diff --git a/server/tests/plugins/index.ts b/server/tests/plugins/index.ts
index 8aa30654a..d2bd69131 100644
--- a/server/tests/plugins/index.ts
+++ b/server/tests/plugins/index.ts
@@ -1,5 +1,6 @@
1import './action-hooks' 1import './action-hooks'
2import './id-and-pass-auth' 2import './id-and-pass-auth'
3import './external-auth'
3import './filter-hooks' 4import './filter-hooks'
4import './translations' 5import './translations'
5import './video-constants' 6import './video-constants'