diff options
author | Chocobozzz <me@florianbigard.com> | 2018-01-17 10:32:03 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-01-17 10:41:27 +0100 |
commit | fd206f0b2d7e5c8e00e2817266d90ec54f79e1da (patch) | |
tree | 86b096cf2abd7eb49b892de1c9be855f45a41a9c /server | |
parent | 9581cabc596acb18c0ad86bcf3a07c2b45e8e47e (diff) | |
download | PeerTube-fd206f0b2d7e5c8e00e2817266d90ec54f79e1da.tar.gz PeerTube-fd206f0b2d7e5c8e00e2817266d90ec54f79e1da.tar.zst PeerTube-fd206f0b2d7e5c8e00e2817266d90ec54f79e1da.zip |
Add ability to update some configuration keys
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/config.ts | 91 | ||||
-rw-r--r-- | server/helpers/utils.ts | 2 | ||||
-rw-r--r-- | server/initializers/constants.ts | 84 | ||||
-rw-r--r-- | server/middlewares/validators/config.ts | 32 | ||||
-rw-r--r-- | server/tests/api/check-params/config.ts | 152 | ||||
-rw-r--r-- | server/tests/api/server/config.ts | 112 | ||||
-rw-r--r-- | server/tests/api/videos/single-server.ts | 3 | ||||
-rw-r--r-- | server/tests/utils/miscs/miscs.ts | 23 | ||||
-rw-r--r-- | server/tests/utils/requests/requests.ts | 2 | ||||
-rw-r--r-- | server/tests/utils/server/config.ts | 41 | ||||
-rw-r--r-- | server/tests/utils/videos/videos.ts | 5 |
11 files changed, 496 insertions, 51 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 35c89835b..f0b2c3d79 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -1,15 +1,34 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { ServerConfig, UserRight } from '../../../shared' | ||
3 | import { CustomConfig } from '../../../shared/models/config/custom-config.model' | ||
4 | import { unlinkPromise, writeFilePromise } from '../../helpers/core-utils' | ||
2 | import { isSignupAllowed } from '../../helpers/utils' | 5 | import { isSignupAllowed } from '../../helpers/utils' |
3 | 6 | import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers' | |
4 | import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' | 7 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' |
5 | import { asyncMiddleware } from '../../middlewares' | 8 | import { customConfigUpdateValidator } from '../../middlewares/validators/config' |
6 | import { ServerConfig } from '../../../shared' | 9 | import { omit } from 'lodash' |
7 | 10 | ||
8 | const configRouter = express.Router() | 11 | const configRouter = express.Router() |
9 | 12 | ||
10 | configRouter.get('/', | 13 | configRouter.get('/', |
11 | asyncMiddleware(getConfig) | 14 | asyncMiddleware(getConfig) |
12 | ) | 15 | ) |
16 | configRouter.get('/custom', | ||
17 | authenticate, | ||
18 | ensureUserHasRight(UserRight.MANAGE_CONFIGURATION), | ||
19 | asyncMiddleware(getCustomConfig) | ||
20 | ) | ||
21 | configRouter.put('/custom', | ||
22 | authenticate, | ||
23 | ensureUserHasRight(UserRight.MANAGE_CONFIGURATION), | ||
24 | asyncMiddleware(customConfigUpdateValidator), | ||
25 | asyncMiddleware(updateCustomConfig) | ||
26 | ) | ||
27 | configRouter.delete('/custom', | ||
28 | authenticate, | ||
29 | ensureUserHasRight(UserRight.MANAGE_CONFIGURATION), | ||
30 | asyncMiddleware(deleteCustomConfig) | ||
31 | ) | ||
13 | 32 | ||
14 | async function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) { | 33 | async function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) { |
15 | const allowed = await isSignupAllowed() | 34 | const allowed = await isSignupAllowed() |
@@ -43,8 +62,72 @@ async function getConfig (req: express.Request, res: express.Response, next: exp | |||
43 | return res.json(json) | 62 | return res.json(json) |
44 | } | 63 | } |
45 | 64 | ||
65 | async function getCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
66 | const data = customConfig() | ||
67 | |||
68 | return res.json(data).end() | ||
69 | } | ||
70 | |||
71 | async function deleteCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
72 | await unlinkPromise(CONFIG.CUSTOM_FILE) | ||
73 | |||
74 | reloadConfig() | ||
75 | |||
76 | const data = customConfig() | ||
77 | |||
78 | return res.json(data).end() | ||
79 | } | ||
80 | |||
81 | async function updateCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
82 | const toUpdate: CustomConfig = req.body | ||
83 | |||
84 | // Need to change the videoQuota key a little bit | ||
85 | const toUpdateJSON = omit(toUpdate, 'videoQuota') | ||
86 | toUpdateJSON.user['video_quota'] = toUpdate.user.videoQuota | ||
87 | |||
88 | await writeFilePromise(CONFIG.CUSTOM_FILE, JSON.stringify(toUpdateJSON)) | ||
89 | |||
90 | reloadConfig() | ||
91 | |||
92 | const data = customConfig() | ||
93 | return res.json(data).end() | ||
94 | } | ||
95 | |||
46 | // --------------------------------------------------------------------------- | 96 | // --------------------------------------------------------------------------- |
47 | 97 | ||
48 | export { | 98 | export { |
49 | configRouter | 99 | configRouter |
50 | } | 100 | } |
101 | |||
102 | // --------------------------------------------------------------------------- | ||
103 | |||
104 | function customConfig (): CustomConfig { | ||
105 | return { | ||
106 | cache: { | ||
107 | previews: { | ||
108 | size: CONFIG.CACHE.PREVIEWS.SIZE | ||
109 | } | ||
110 | }, | ||
111 | signup: { | ||
112 | enabled: CONFIG.SIGNUP.ENABLED, | ||
113 | limit: CONFIG.SIGNUP.LIMIT | ||
114 | }, | ||
115 | admin: { | ||
116 | email: CONFIG.ADMIN.EMAIL | ||
117 | }, | ||
118 | user: { | ||
119 | videoQuota: CONFIG.USER.VIDEO_QUOTA | ||
120 | }, | ||
121 | transcoding: { | ||
122 | enabled: CONFIG.TRANSCODING.ENABLED, | ||
123 | threads: CONFIG.TRANSCODING.THREADS, | ||
124 | resolutions: { | ||
125 | '240p': CONFIG.TRANSCODING.RESOLUTIONS[ '240p' ], | ||
126 | '360p': CONFIG.TRANSCODING.RESOLUTIONS[ '360p' ], | ||
127 | '480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ], | ||
128 | '720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ], | ||
129 | '1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ] | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | } | ||
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index b61d6e3fa..79c3b5858 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts | |||
@@ -104,7 +104,7 @@ function computeResolutionsToTranscode (videoFileHeight: number) { | |||
104 | ] | 104 | ] |
105 | 105 | ||
106 | for (const resolution of resolutions) { | 106 | for (const resolution of resolutions) { |
107 | if (configResolutions[resolution.toString()] === true && videoFileHeight > resolution) { | 107 | if (configResolutions[resolution + 'p'] === true && videoFileHeight > resolution) { |
108 | resolutionsEnabled.push(resolution) | 108 | resolutionsEnabled.push(resolution) |
109 | } | 109 | } |
110 | } | 110 | } |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 759880201..7b63a9ccd 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -1,11 +1,14 @@ | |||
1 | import * as config from 'config' | 1 | import { IConfig } from 'config' |
2 | import { join } from 'path' | 2 | import { dirname, join } from 'path' |
3 | import { JobCategory, JobState, VideoRateType } from '../../shared/models' | 3 | import { JobCategory, JobState, VideoRateType } from '../../shared/models' |
4 | import { ActivityPubActorType } from '../../shared/models/activitypub' | 4 | import { ActivityPubActorType } from '../../shared/models/activitypub' |
5 | import { FollowState } from '../../shared/models/actors' | 5 | import { FollowState } from '../../shared/models/actors' |
6 | import { VideoPrivacy } from '../../shared/models/videos' | 6 | import { VideoPrivacy } from '../../shared/models/videos' |
7 | // Do not use barrels, remain constants as independent as possible | 7 | // Do not use barrels, remain constants as independent as possible |
8 | import { buildPath, isTestInstance, sanitizeHost, sanitizeUrl } from '../helpers/core-utils' | 8 | import { buildPath, isTestInstance, root, sanitizeHost, sanitizeUrl } from '../helpers/core-utils' |
9 | |||
10 | // Use a variable to reload the configuration if we need | ||
11 | let config: IConfig = require('config') | ||
9 | 12 | ||
10 | // --------------------------------------------------------------------------- | 13 | // --------------------------------------------------------------------------- |
11 | 14 | ||
@@ -82,6 +85,7 @@ let SCHEDULER_INTERVAL = 60000 * 60 | |||
82 | // --------------------------------------------------------------------------- | 85 | // --------------------------------------------------------------------------- |
83 | 86 | ||
84 | const CONFIG = { | 87 | const CONFIG = { |
88 | CUSTOM_FILE: getLocalConfigFilePath(), | ||
85 | LISTEN: { | 89 | LISTEN: { |
86 | PORT: config.get<number>('listen.port') | 90 | PORT: config.get<number>('listen.port') |
87 | }, | 91 | }, |
@@ -110,29 +114,29 @@ const CONFIG = { | |||
110 | HOST: '' | 114 | HOST: '' |
111 | }, | 115 | }, |
112 | ADMIN: { | 116 | ADMIN: { |
113 | EMAIL: config.get<string>('admin.email') | 117 | get EMAIL () { return config.get<string>('admin.email') } |
114 | }, | 118 | }, |
115 | SIGNUP: { | 119 | SIGNUP: { |
116 | ENABLED: config.get<boolean>('signup.enabled'), | 120 | get ENABLED () { return config.get<boolean>('signup.enabled') }, |
117 | LIMIT: config.get<number>('signup.limit') | 121 | get LIMIT () { return config.get<number>('signup.limit') } |
118 | }, | 122 | }, |
119 | USER: { | 123 | USER: { |
120 | VIDEO_QUOTA: config.get<number>('user.video_quota') | 124 | get VIDEO_QUOTA () { return config.get<number>('user.video_quota') } |
121 | }, | 125 | }, |
122 | TRANSCODING: { | 126 | TRANSCODING: { |
123 | ENABLED: config.get<boolean>('transcoding.enabled'), | 127 | get ENABLED () { return config.get<boolean>('transcoding.enabled') }, |
124 | THREADS: config.get<number>('transcoding.threads'), | 128 | get THREADS () { return config.get<number>('transcoding.threads') }, |
125 | RESOLUTIONS: { | 129 | RESOLUTIONS: { |
126 | '240' : config.get<boolean>('transcoding.resolutions.240p'), | 130 | get '240p' () { return config.get<boolean>('transcoding.resolutions.240p') }, |
127 | '360': config.get<boolean>('transcoding.resolutions.360p'), | 131 | get '360p' () { return config.get<boolean>('transcoding.resolutions.360p') }, |
128 | '480': config.get<boolean>('transcoding.resolutions.480p'), | 132 | get '480p' () { return config.get<boolean>('transcoding.resolutions.480p') }, |
129 | '720': config.get<boolean>('transcoding.resolutions.720p'), | 133 | get '720p' () { return config.get<boolean>('transcoding.resolutions.720p') }, |
130 | '1080': config.get<boolean>('transcoding.resolutions.1080p') | 134 | get '1080p' () { return config.get<boolean>('transcoding.resolutions.1080p') } |
131 | } | 135 | } |
132 | }, | 136 | }, |
133 | CACHE: { | 137 | CACHE: { |
134 | PREVIEWS: { | 138 | PREVIEWS: { |
135 | SIZE: config.get<number>('cache.previews.size') | 139 | get SIZE () { return config.get<number>('cache.previews.size') } |
136 | } | 140 | } |
137 | } | 141 | } |
138 | } | 142 | } |
@@ -361,8 +365,7 @@ if (isTestInstance() === true) { | |||
361 | SCHEDULER_INTERVAL = 10000 | 365 | SCHEDULER_INTERVAL = 10000 |
362 | } | 366 | } |
363 | 367 | ||
364 | CONFIG.WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT) | 368 | updateWebserverConfig() |
365 | CONFIG.WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP) | ||
366 | 369 | ||
367 | // --------------------------------------------------------------------------- | 370 | // --------------------------------------------------------------------------- |
368 | 371 | ||
@@ -404,3 +407,50 @@ export { | |||
404 | AVATAR_MIMETYPE_EXT, | 407 | AVATAR_MIMETYPE_EXT, |
405 | SCHEDULER_INTERVAL | 408 | SCHEDULER_INTERVAL |
406 | } | 409 | } |
410 | |||
411 | // --------------------------------------------------------------------------- | ||
412 | |||
413 | function getLocalConfigFilePath () { | ||
414 | const configSources = config.util.getConfigSources() | ||
415 | if (configSources.length === 0) throw new Error('Invalid config source.') | ||
416 | |||
417 | let filename = 'local' | ||
418 | if (process.env.NODE_ENV) filename += `-${process.env.NODE_ENV}` | ||
419 | if (process.env.NODE_APP_INSTANCE) filename += `-${process.env.NODE_APP_INSTANCE}` | ||
420 | |||
421 | return join(dirname(configSources[ 0 ].name), filename + '.json') | ||
422 | } | ||
423 | |||
424 | function updateWebserverConfig () { | ||
425 | CONFIG.WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT) | ||
426 | CONFIG.WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP) | ||
427 | } | ||
428 | |||
429 | export function reloadConfig () { | ||
430 | |||
431 | function directory () { | ||
432 | if (process.env.NODE_CONFIG_DIR) { | ||
433 | return process.env.NODE_CONFIG_DIR | ||
434 | } | ||
435 | |||
436 | return join(root(), 'config') | ||
437 | } | ||
438 | |||
439 | function purge () { | ||
440 | for (const fileName in require.cache) { | ||
441 | if (-1 === fileName.indexOf(directory())) { | ||
442 | continue | ||
443 | } | ||
444 | |||
445 | delete require.cache[fileName] | ||
446 | } | ||
447 | |||
448 | delete require.cache[require.resolve('config')] | ||
449 | } | ||
450 | |||
451 | purge() | ||
452 | |||
453 | config = require('config') | ||
454 | |||
455 | updateWebserverConfig() | ||
456 | } | ||
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts new file mode 100644 index 000000000..800aaf107 --- /dev/null +++ b/server/middlewares/validators/config.ts | |||
@@ -0,0 +1,32 @@ | |||
1 | import * as express from 'express' | ||
2 | import { body } from 'express-validator/check' | ||
3 | import { isUserVideoQuotaValid } from '../../helpers/custom-validators/users' | ||
4 | import { logger } from '../../helpers/logger' | ||
5 | import { areValidationErrors } from './utils' | ||
6 | |||
7 | const customConfigUpdateValidator = [ | ||
8 | body('cache.previews.size').isInt().withMessage('Should have a valid previews size'), | ||
9 | body('signup.enabled').isBoolean().withMessage('Should have a valid signup enabled boolean'), | ||
10 | body('signup.limit').isInt().withMessage('Should have a valid signup limit'), | ||
11 | body('admin.email').isEmail().withMessage('Should have a valid administrator email'), | ||
12 | body('user.videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid video quota'), | ||
13 | body('transcoding.enabled').isBoolean().withMessage('Should have a valid transcoding enabled boolean'), | ||
14 | body('transcoding.threads').isInt().withMessage('Should have a valid transcoding threads number'), | ||
15 | body('transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'), | ||
16 | body('transcoding.resolutions.360p').isBoolean().withMessage('Should have a valid transcoding 360p resolution enabled boolean'), | ||
17 | body('transcoding.resolutions.480p').isBoolean().withMessage('Should have a valid transcoding 480p resolution enabled boolean'), | ||
18 | body('transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'), | ||
19 | body('transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'), | ||
20 | |||
21 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
22 | logger.debug('Checking customConfigUpdateValidator parameters', { parameters: req.body }) | ||
23 | |||
24 | if (areValidationErrors(req, res)) return | ||
25 | |||
26 | return next() | ||
27 | } | ||
28 | ] | ||
29 | |||
30 | export { | ||
31 | customConfigUpdateValidator | ||
32 | } | ||
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts new file mode 100644 index 000000000..59a0c3049 --- /dev/null +++ b/server/tests/api/check-params/config.ts | |||
@@ -0,0 +1,152 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import { omit } from 'lodash' | ||
4 | import 'mocha' | ||
5 | import { CustomConfig } from '../../../../shared/models/config/custom-config.model' | ||
6 | |||
7 | import { | ||
8 | createUser, flushTests, killallServers, makeDeleteRequest, makeGetRequest, makePutBodyRequest, runServer, ServerInfo, | ||
9 | setAccessTokensToServers, userLogin | ||
10 | } from '../../utils' | ||
11 | |||
12 | describe('Test config API validators', function () { | ||
13 | const path = '/api/v1/config/custom' | ||
14 | let server: ServerInfo | ||
15 | let userAccessToken: string | ||
16 | const updateParams: CustomConfig = { | ||
17 | cache: { | ||
18 | previews: { | ||
19 | size: 2 | ||
20 | } | ||
21 | }, | ||
22 | signup: { | ||
23 | enabled: false, | ||
24 | limit: 5 | ||
25 | }, | ||
26 | admin: { | ||
27 | email: 'superadmin1@example.com' | ||
28 | }, | ||
29 | user: { | ||
30 | videoQuota: 5242881 | ||
31 | }, | ||
32 | transcoding: { | ||
33 | enabled: true, | ||
34 | threads: 1, | ||
35 | resolutions: { | ||
36 | '240p': false, | ||
37 | '360p': true, | ||
38 | '480p': true, | ||
39 | '720p': false, | ||
40 | '1080p': false | ||
41 | } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | // --------------------------------------------------------------- | ||
46 | |||
47 | before(async function () { | ||
48 | this.timeout(20000) | ||
49 | |||
50 | await flushTests() | ||
51 | server = await runServer(1) | ||
52 | |||
53 | await setAccessTokensToServers([ server ]) | ||
54 | |||
55 | const user = { | ||
56 | username: 'user1', | ||
57 | password: 'password' | ||
58 | } | ||
59 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
60 | userAccessToken = await userLogin(server, user) | ||
61 | }) | ||
62 | |||
63 | describe('When getting the configuration', function () { | ||
64 | it('Should fail without token', async function () { | ||
65 | await makeGetRequest({ | ||
66 | url: server.url, | ||
67 | path, | ||
68 | statusCodeExpected: 401 | ||
69 | }) | ||
70 | }) | ||
71 | |||
72 | it('Should fail if the user is not an administrator', async function () { | ||
73 | await makeGetRequest({ | ||
74 | url: server.url, | ||
75 | path, | ||
76 | token: userAccessToken, | ||
77 | statusCodeExpected: 403 | ||
78 | }) | ||
79 | }) | ||
80 | }) | ||
81 | |||
82 | describe('When updating the configuration', function () { | ||
83 | it('Should fail without token', async function () { | ||
84 | await makePutBodyRequest({ | ||
85 | url: server.url, | ||
86 | path, | ||
87 | fields: updateParams, | ||
88 | statusCodeExpected: 401 | ||
89 | }) | ||
90 | }) | ||
91 | |||
92 | it('Should fail if the user is not an administrator', async function () { | ||
93 | await makePutBodyRequest({ | ||
94 | url: server.url, | ||
95 | path, | ||
96 | fields: updateParams, | ||
97 | token: userAccessToken, | ||
98 | statusCodeExpected: 403 | ||
99 | }) | ||
100 | }) | ||
101 | |||
102 | it('Should fail if it misses a key', async function () { | ||
103 | const newUpdateParams = omit(updateParams, 'admin.email') | ||
104 | |||
105 | await makePutBodyRequest({ | ||
106 | url: server.url, | ||
107 | path, | ||
108 | fields: newUpdateParams, | ||
109 | token: server.accessToken, | ||
110 | statusCodeExpected: 400 | ||
111 | }) | ||
112 | }) | ||
113 | |||
114 | it('Should success with the correct parameters', async function () { | ||
115 | await makePutBodyRequest({ | ||
116 | url: server.url, | ||
117 | path, | ||
118 | fields: updateParams, | ||
119 | token: server.accessToken, | ||
120 | statusCodeExpected: 200 | ||
121 | }) | ||
122 | }) | ||
123 | }) | ||
124 | |||
125 | describe('When deleting the configuration', function () { | ||
126 | it('Should fail without token', async function () { | ||
127 | await makeDeleteRequest({ | ||
128 | url: server.url, | ||
129 | path, | ||
130 | statusCodeExpected: 401 | ||
131 | }) | ||
132 | }) | ||
133 | |||
134 | it('Should fail if the user is not an administrator', async function () { | ||
135 | await makeDeleteRequest({ | ||
136 | url: server.url, | ||
137 | path, | ||
138 | token: userAccessToken, | ||
139 | statusCodeExpected: 403 | ||
140 | }) | ||
141 | }) | ||
142 | }) | ||
143 | |||
144 | after(async function () { | ||
145 | killallServers([ server ]) | ||
146 | |||
147 | // Keep the logs if the test failed | ||
148 | if (this['ok']) { | ||
149 | await flushTests() | ||
150 | } | ||
151 | }) | ||
152 | }) | ||
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index e8846c8db..8c1389e7f 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -2,13 +2,14 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { deleteCustomConfig, killallServers, reRunServer } from '../../utils' | ||
5 | const expect = chai.expect | 6 | const expect = chai.expect |
6 | 7 | ||
7 | import { | 8 | import { |
8 | getConfig, | 9 | getConfig, |
9 | flushTests, | 10 | flushTests, |
10 | runServer, | 11 | runServer, |
11 | registerUser | 12 | registerUser, getCustomConfig, setAccessTokensToServers, updateCustomConfig |
12 | } from '../../utils/index' | 13 | } from '../../utils/index' |
13 | 14 | ||
14 | describe('Test config', function () { | 15 | describe('Test config', function () { |
@@ -19,6 +20,7 @@ describe('Test config', function () { | |||
19 | 20 | ||
20 | await flushTests() | 21 | await flushTests() |
21 | server = await runServer(1) | 22 | server = await runServer(1) |
23 | await setAccessTokensToServers([ server ]) | ||
22 | }) | 24 | }) |
23 | 25 | ||
24 | it('Should have a correct config on a server with registration enabled', async function () { | 26 | it('Should have a correct config on a server with registration enabled', async function () { |
@@ -43,6 +45,114 @@ describe('Test config', function () { | |||
43 | expect(data.signup.allowed).to.be.false | 45 | expect(data.signup.allowed).to.be.false |
44 | }) | 46 | }) |
45 | 47 | ||
48 | it('Should get the customized configuration', async function () { | ||
49 | const res = await getCustomConfig(server.url, server.accessToken) | ||
50 | const data = res.body | ||
51 | |||
52 | expect(data.cache.previews.size).to.equal(1) | ||
53 | expect(data.signup.enabled).to.be.true | ||
54 | expect(data.signup.limit).to.equal(4) | ||
55 | expect(data.admin.email).to.equal('admin1@example.com') | ||
56 | expect(data.user.videoQuota).to.equal(5242880) | ||
57 | expect(data.transcoding.enabled).to.be.false | ||
58 | expect(data.transcoding.threads).to.equal(2) | ||
59 | expect(data.transcoding.resolutions['240p']).to.be.true | ||
60 | expect(data.transcoding.resolutions['360p']).to.be.true | ||
61 | expect(data.transcoding.resolutions['480p']).to.be.true | ||
62 | expect(data.transcoding.resolutions['720p']).to.be.true | ||
63 | expect(data.transcoding.resolutions['1080p']).to.be.true | ||
64 | }) | ||
65 | |||
66 | it('Should update the customized configuration', async function () { | ||
67 | const newCustomConfig = { | ||
68 | cache: { | ||
69 | previews: { | ||
70 | size: 2 | ||
71 | } | ||
72 | }, | ||
73 | signup: { | ||
74 | enabled: false, | ||
75 | limit: 5 | ||
76 | }, | ||
77 | admin: { | ||
78 | email: 'superadmin1@example.com' | ||
79 | }, | ||
80 | user: { | ||
81 | videoQuota: 5242881 | ||
82 | }, | ||
83 | transcoding: { | ||
84 | enabled: true, | ||
85 | threads: 1, | ||
86 | resolutions: { | ||
87 | '240p': false, | ||
88 | '360p': true, | ||
89 | '480p': true, | ||
90 | '720p': false, | ||
91 | '1080p': false | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | await updateCustomConfig(server.url, server.accessToken, newCustomConfig) | ||
96 | |||
97 | const res = await getCustomConfig(server.url, server.accessToken) | ||
98 | const data = res.body | ||
99 | |||
100 | expect(data.cache.previews.size).to.equal(2) | ||
101 | expect(data.signup.enabled).to.be.false | ||
102 | expect(data.signup.limit).to.equal(5) | ||
103 | expect(data.admin.email).to.equal('superadmin1@example.com') | ||
104 | expect(data.user.videoQuota).to.equal(5242881) | ||
105 | expect(data.transcoding.enabled).to.be.true | ||
106 | expect(data.transcoding.threads).to.equal(1) | ||
107 | expect(data.transcoding.resolutions['240p']).to.be.false | ||
108 | expect(data.transcoding.resolutions['360p']).to.be.true | ||
109 | expect(data.transcoding.resolutions['480p']).to.be.true | ||
110 | expect(data.transcoding.resolutions['720p']).to.be.false | ||
111 | expect(data.transcoding.resolutions['1080p']).to.be.false | ||
112 | }) | ||
113 | |||
114 | it('Should have the configuration updated after a restart', async function () { | ||
115 | killallServers([ server ]) | ||
116 | |||
117 | await reRunServer(server) | ||
118 | |||
119 | const res = await getCustomConfig(server.url, server.accessToken) | ||
120 | const data = res.body | ||
121 | |||
122 | expect(data.cache.previews.size).to.equal(2) | ||
123 | expect(data.signup.enabled).to.be.false | ||
124 | expect(data.signup.limit).to.equal(5) | ||
125 | expect(data.admin.email).to.equal('superadmin1@example.com') | ||
126 | expect(data.user.videoQuota).to.equal(5242881) | ||
127 | expect(data.transcoding.enabled).to.be.true | ||
128 | expect(data.transcoding.threads).to.equal(1) | ||
129 | expect(data.transcoding.resolutions['240p']).to.be.false | ||
130 | expect(data.transcoding.resolutions['360p']).to.be.true | ||
131 | expect(data.transcoding.resolutions['480p']).to.be.true | ||
132 | expect(data.transcoding.resolutions['720p']).to.be.false | ||
133 | expect(data.transcoding.resolutions['1080p']).to.be.false | ||
134 | }) | ||
135 | |||
136 | it('Should remove the custom configuration', async function () { | ||
137 | await deleteCustomConfig(server.url, server.accessToken) | ||
138 | |||
139 | const res = await getCustomConfig(server.url, server.accessToken) | ||
140 | const data = res.body | ||
141 | |||
142 | expect(data.cache.previews.size).to.equal(1) | ||
143 | expect(data.signup.enabled).to.be.true | ||
144 | expect(data.signup.limit).to.equal(4) | ||
145 | expect(data.admin.email).to.equal('admin1@example.com') | ||
146 | expect(data.user.videoQuota).to.equal(5242880) | ||
147 | expect(data.transcoding.enabled).to.be.false | ||
148 | expect(data.transcoding.threads).to.equal(2) | ||
149 | expect(data.transcoding.resolutions['240p']).to.be.true | ||
150 | expect(data.transcoding.resolutions['360p']).to.be.true | ||
151 | expect(data.transcoding.resolutions['480p']).to.be.true | ||
152 | expect(data.transcoding.resolutions['720p']).to.be.true | ||
153 | expect(data.transcoding.resolutions['1080p']).to.be.true | ||
154 | }) | ||
155 | |||
46 | after(async function () { | 156 | after(async function () { |
47 | process.kill(-server.app.pid) | 157 | process.kill(-server.app.pid) |
48 | 158 | ||
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index 0a0c95750..ca20f39a0 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -5,9 +5,10 @@ import { keyBy } from 'lodash' | |||
5 | import 'mocha' | 5 | import 'mocha' |
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | import { VideoPrivacy } from '../../../../shared/models/videos' | 7 | import { VideoPrivacy } from '../../../../shared/models/videos' |
8 | import { readdirPromise } from '../../../helpers/core-utils' | ||
8 | import { | 9 | import { |
9 | completeVideoCheck, flushTests, getVideo, getVideoCategories, getVideoLanguages, getVideoLicences, getVideoPrivacies, | 10 | completeVideoCheck, flushTests, getVideo, getVideoCategories, getVideoLanguages, getVideoLicences, getVideoPrivacies, |
10 | getVideosList, getVideosListPagination, getVideosListSort, killallServers, rateVideo, readdirPromise, removeVideo, runServer, searchVideo, | 11 | getVideosList, getVideosListPagination, getVideosListSort, killallServers, rateVideo, removeVideo, runServer, searchVideo, |
11 | searchVideoWithPagination, searchVideoWithSort, ServerInfo, setAccessTokensToServers, testVideoImage, updateVideo, uploadVideo, viewVideo | 12 | searchVideoWithPagination, searchVideoWithSort, ServerInfo, setAccessTokensToServers, testVideoImage, updateVideo, uploadVideo, viewVideo |
12 | } from '../../utils' | 13 | } from '../../utils' |
13 | 14 | ||
diff --git a/server/tests/utils/miscs/miscs.ts b/server/tests/utils/miscs/miscs.ts index 2c51d1f0a..2aac37791 100644 --- a/server/tests/utils/miscs/miscs.ts +++ b/server/tests/utils/miscs/miscs.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import * as WebTorrent from 'webtorrent' | 1 | import * as WebTorrent from 'webtorrent' |
2 | import { readFile, readdir } from 'fs' | ||
3 | 2 | ||
4 | let webtorrent = new WebTorrent() | 3 | let webtorrent = new WebTorrent() |
5 | 4 | ||
@@ -7,26 +6,6 @@ function immutableAssign <T, U> (target: T, source: U) { | |||
7 | return Object.assign<{}, T, U>({}, target, source) | 6 | return Object.assign<{}, T, U>({}, target, source) |
8 | } | 7 | } |
9 | 8 | ||
10 | function readFilePromise (path: string) { | ||
11 | return new Promise<Buffer>((res, rej) => { | ||
12 | readFile(path, (err, data) => { | ||
13 | if (err) return rej(err) | ||
14 | |||
15 | return res(data) | ||
16 | }) | ||
17 | }) | ||
18 | } | ||
19 | |||
20 | function readdirPromise (path: string) { | ||
21 | return new Promise<string[]>((res, rej) => { | ||
22 | readdir(path, (err, files) => { | ||
23 | if (err) return rej(err) | ||
24 | |||
25 | return res(files) | ||
26 | }) | ||
27 | }) | ||
28 | } | ||
29 | |||
30 | // Default interval -> 5 minutes | 9 | // Default interval -> 5 minutes |
31 | function dateIsValid (dateString: string, interval = 300000) { | 10 | function dateIsValid (dateString: string, interval = 300000) { |
32 | const dateToCheck = new Date(dateString) | 11 | const dateToCheck = new Date(dateString) |
@@ -48,8 +27,6 @@ function webtorrentAdd (torrent: string, refreshWebTorrent = false) { | |||
48 | // --------------------------------------------------------------------------- | 27 | // --------------------------------------------------------------------------- |
49 | 28 | ||
50 | export { | 29 | export { |
51 | readFilePromise, | ||
52 | readdirPromise, | ||
53 | dateIsValid, | 30 | dateIsValid, |
54 | wait, | 31 | wait, |
55 | webtorrentAdd, | 32 | webtorrentAdd, |
diff --git a/server/tests/utils/requests/requests.ts b/server/tests/utils/requests/requests.ts index eb02cf9e6..840072430 100644 --- a/server/tests/utils/requests/requests.ts +++ b/server/tests/utils/requests/requests.ts | |||
@@ -99,7 +99,7 @@ function makePostBodyRequest (options: { | |||
99 | function makePutBodyRequest (options: { | 99 | function makePutBodyRequest (options: { |
100 | url: string, | 100 | url: string, |
101 | path: string, | 101 | path: string, |
102 | token: string, | 102 | token?: string, |
103 | fields: { [ fieldName: string ]: any }, | 103 | fields: { [ fieldName: string ]: any }, |
104 | statusCodeExpected?: number | 104 | statusCodeExpected?: number |
105 | }) { | 105 | }) { |
diff --git a/server/tests/utils/server/config.ts b/server/tests/utils/server/config.ts index d09c19c60..b6905757a 100644 --- a/server/tests/utils/server/config.ts +++ b/server/tests/utils/server/config.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import * as request from 'supertest' | 1 | import * as request from 'supertest' |
2 | import { makeDeleteRequest, makeGetRequest, makePutBodyRequest } from '../' | ||
3 | import { CustomConfig } from '../../../../shared/models/config/custom-config.model' | ||
2 | 4 | ||
3 | function getConfig (url: string) { | 5 | function getConfig (url: string) { |
4 | const path = '/api/v1/config' | 6 | const path = '/api/v1/config' |
@@ -10,8 +12,45 @@ function getConfig (url: string) { | |||
10 | .expect('Content-Type', /json/) | 12 | .expect('Content-Type', /json/) |
11 | } | 13 | } |
12 | 14 | ||
15 | function getCustomConfig (url: string, token: string, statusCodeExpected = 200) { | ||
16 | const path = '/api/v1/config/custom' | ||
17 | |||
18 | return makeGetRequest({ | ||
19 | url, | ||
20 | token, | ||
21 | path, | ||
22 | statusCodeExpected | ||
23 | }) | ||
24 | } | ||
25 | |||
26 | function updateCustomConfig (url: string, token: string, newCustomConfig: CustomConfig, statusCodeExpected = 200) { | ||
27 | const path = '/api/v1/config/custom' | ||
28 | |||
29 | return makePutBodyRequest({ | ||
30 | url, | ||
31 | token, | ||
32 | path, | ||
33 | fields: newCustomConfig, | ||
34 | statusCodeExpected | ||
35 | }) | ||
36 | } | ||
37 | |||
38 | function deleteCustomConfig (url: string, token: string, statusCodeExpected = 200) { | ||
39 | const path = '/api/v1/config/custom' | ||
40 | |||
41 | return makeDeleteRequest({ | ||
42 | url, | ||
43 | token, | ||
44 | path, | ||
45 | statusCodeExpected | ||
46 | }) | ||
47 | } | ||
48 | |||
13 | // --------------------------------------------------------------------------- | 49 | // --------------------------------------------------------------------------- |
14 | 50 | ||
15 | export { | 51 | export { |
16 | getConfig | 52 | getConfig, |
53 | getCustomConfig, | ||
54 | updateCustomConfig, | ||
55 | deleteCustomConfig | ||
17 | } | 56 | } |
diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts index dc1327215..095d4e29d 100644 --- a/server/tests/utils/videos/videos.ts +++ b/server/tests/utils/videos/videos.ts | |||
@@ -5,8 +5,9 @@ import { readFile } from 'fs' | |||
5 | import * as parseTorrent from 'parse-torrent' | 5 | import * as parseTorrent from 'parse-torrent' |
6 | import { extname, isAbsolute, join } from 'path' | 6 | import { extname, isAbsolute, join } from 'path' |
7 | import * as request from 'supertest' | 7 | import * as request from 'supertest' |
8 | import { getMyUserInformation, makeGetRequest, readFilePromise, ServerInfo } from '../' | 8 | import { getMyUserInformation, makeGetRequest, ServerInfo } from '../' |
9 | import { VideoPrivacy } from '../../../../shared/models/videos' | 9 | import { VideoPrivacy } from '../../../../shared/models/videos' |
10 | import { readFileBufferPromise } from '../../../helpers/core-utils' | ||
10 | import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers' | 11 | import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers' |
11 | import { dateIsValid, webtorrentAdd } from '../index' | 12 | import { dateIsValid, webtorrentAdd } from '../index' |
12 | 13 | ||
@@ -210,7 +211,7 @@ async function testVideoImage (url: string, imageName: string, imagePath: string | |||
210 | .get(imagePath) | 211 | .get(imagePath) |
211 | .expect(200) | 212 | .expect(200) |
212 | 213 | ||
213 | const data = await readFilePromise(join(__dirname, '..', '..', 'api', 'fixtures', imageName + extension)) | 214 | const data = await readFileBufferPromise(join(__dirname, '..', '..', 'api', 'fixtures', imageName + extension)) |
214 | 215 | ||
215 | return data.equals(res.body) | 216 | return data.equals(res.body) |
216 | } else { | 217 | } else { |