diff options
Diffstat (limited to 'server/middlewares/validators')
23 files changed, 309 insertions, 109 deletions
diff --git a/server/middlewares/validators/activitypub/activity.ts b/server/middlewares/validators/activitypub/activity.ts index 7582f65e7..7350be5d5 100644 --- a/server/middlewares/validators/activitypub/activity.ts +++ b/server/middlewares/validators/activitypub/activity.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { isRootActivityValid } from '../../../helpers/custom-validators/activitypub/activity' | 2 | import { isRootActivityValid } from '../../../helpers/custom-validators/activitypub/activity' |
3 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
4 | import { getServerActor } from '../../../helpers/utils' | 4 | import { getServerActor } from '@server/models/application/application' |
5 | 5 | ||
6 | async function activityPubValidator (req: express.Request, res: express.Response, next: express.NextFunction) { | 6 | async function activityPubValidator (req: express.Request, res: express.Response, next: express.NextFunction) { |
7 | logger.debug('Checking activity pub parameters') | 7 | logger.debug('Checking activity pub parameters') |
diff --git a/server/middlewares/validators/avatar.ts b/server/middlewares/validators/avatar.ts index 8623d07e8..2acb97483 100644 --- a/server/middlewares/validators/avatar.ts +++ b/server/middlewares/validators/avatar.ts | |||
@@ -8,8 +8,8 @@ import { cleanUpReqFiles } from '../../helpers/express-utils' | |||
8 | 8 | ||
9 | const updateAvatarValidator = [ | 9 | const updateAvatarValidator = [ |
10 | body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage( | 10 | body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage( |
11 | 'This file is not supported or too large. Please, make sure it is of the following type : ' | 11 | 'This file is not supported or too large. Please, make sure it is of the following type : ' + |
12 | + CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME.join(', ') | 12 | CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME.join(', ') |
13 | ), | 13 | ), |
14 | 14 | ||
15 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 15 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
diff --git a/server/middlewares/validators/blocklist.ts b/server/middlewares/validators/blocklist.ts index 47a0b1a1c..27224ff9b 100644 --- a/server/middlewares/validators/blocklist.ts +++ b/server/middlewares/validators/blocklist.ts | |||
@@ -6,9 +6,9 @@ import { AccountBlocklistModel } from '../../models/account/account-blocklist' | |||
6 | import { isHostValid } from '../../helpers/custom-validators/servers' | 6 | import { isHostValid } from '../../helpers/custom-validators/servers' |
7 | import { ServerBlocklistModel } from '../../models/server/server-blocklist' | 7 | import { ServerBlocklistModel } from '../../models/server/server-blocklist' |
8 | import { ServerModel } from '../../models/server/server' | 8 | import { ServerModel } from '../../models/server/server' |
9 | import { getServerActor } from '../../helpers/utils' | ||
10 | import { WEBSERVER } from '../../initializers/constants' | 9 | import { WEBSERVER } from '../../initializers/constants' |
11 | import { doesAccountNameWithHostExist } from '../../helpers/middlewares' | 10 | import { doesAccountNameWithHostExist } from '../../helpers/middlewares' |
11 | import { getServerActor } from '@server/models/application/application' | ||
12 | 12 | ||
13 | const blockAccountValidator = [ | 13 | const blockAccountValidator = [ |
14 | body('accountName').exists().withMessage('Should have an account name with host'), | 14 | body('accountName').exists().withMessage('Should have an account name with host'), |
@@ -84,12 +84,7 @@ const blockServerValidator = [ | |||
84 | .end() | 84 | .end() |
85 | } | 85 | } |
86 | 86 | ||
87 | const server = await ServerModel.loadByHost(host) | 87 | const server = await ServerModel.loadOrCreateByHost(host) |
88 | if (!server) { | ||
89 | return res.status(404) | ||
90 | .send({ error: 'Server host not found.' }) | ||
91 | .end() | ||
92 | } | ||
93 | 88 | ||
94 | res.locals.server = server | 89 | res.locals.server = server |
95 | 90 | ||
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts index 2d1f61947..dfa549e76 100644 --- a/server/middlewares/validators/config.ts +++ b/server/middlewares/validators/config.ts | |||
@@ -3,10 +3,10 @@ import { body } from 'express-validator' | |||
3 | import { isUserNSFWPolicyValid, isUserVideoQuotaDailyValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users' | 3 | import { isUserNSFWPolicyValid, isUserVideoQuotaDailyValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users' |
4 | import { logger } from '../../helpers/logger' | 4 | import { logger } from '../../helpers/logger' |
5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' | 5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' |
6 | import { Emailer } from '../../lib/emailer' | ||
7 | import { areValidationErrors } from './utils' | 6 | import { areValidationErrors } from './utils' |
8 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' | 7 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' |
9 | import { isThemeRegistered } from '../../lib/plugins/theme-utils' | 8 | import { isThemeRegistered } from '../../lib/plugins/theme-utils' |
9 | import { isEmailEnabled } from '@server/initializers/config' | ||
10 | 10 | ||
11 | const customConfigUpdateValidator = [ | 11 | const customConfigUpdateValidator = [ |
12 | body('instance.name').exists().withMessage('Should have a valid instance name'), | 12 | body('instance.name').exists().withMessage('Should have a valid instance name'), |
@@ -55,7 +55,7 @@ const customConfigUpdateValidator = [ | |||
55 | 55 | ||
56 | body('theme.default').custom(v => isThemeNameValid(v) && isThemeRegistered(v)).withMessage('Should have a valid theme'), | 56 | body('theme.default').custom(v => isThemeNameValid(v) && isThemeRegistered(v)).withMessage('Should have a valid theme'), |
57 | 57 | ||
58 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 58 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
59 | logger.debug('Checking customConfigUpdateValidator parameters', { parameters: req.body }) | 59 | logger.debug('Checking customConfigUpdateValidator parameters', { parameters: req.body }) |
60 | 60 | ||
61 | if (areValidationErrors(req, res)) return | 61 | if (areValidationErrors(req, res)) return |
@@ -73,7 +73,7 @@ export { | |||
73 | } | 73 | } |
74 | 74 | ||
75 | function checkInvalidConfigIfEmailDisabled (customConfig: CustomConfig, res: express.Response) { | 75 | function checkInvalidConfigIfEmailDisabled (customConfig: CustomConfig, res: express.Response) { |
76 | if (Emailer.isEnabled()) return true | 76 | if (isEmailEnabled()) return true |
77 | 77 | ||
78 | if (customConfig.signup.requiresEmailVerification === true) { | 78 | if (customConfig.signup.requiresEmailVerification === true) { |
79 | res.status(400) | 79 | res.status(400) |
diff --git a/server/middlewares/validators/feeds.ts b/server/middlewares/validators/feeds.ts index 29f6c87be..f34c2b174 100644 --- a/server/middlewares/validators/feeds.ts +++ b/server/middlewares/validators/feeds.ts | |||
@@ -22,13 +22,13 @@ function setFeedFormatContentType (req: express.Request, res: express.Response, | |||
22 | 22 | ||
23 | let acceptableContentTypes: string[] | 23 | let acceptableContentTypes: string[] |
24 | if (format === 'atom' || format === 'atom1') { | 24 | if (format === 'atom' || format === 'atom1') { |
25 | acceptableContentTypes = ['application/atom+xml', 'application/xml', 'text/xml'] | 25 | acceptableContentTypes = [ 'application/atom+xml', 'application/xml', 'text/xml' ] |
26 | } else if (format === 'json' || format === 'json1') { | 26 | } else if (format === 'json' || format === 'json1') { |
27 | acceptableContentTypes = ['application/json'] | 27 | acceptableContentTypes = [ 'application/json' ] |
28 | } else if (format === 'rss' || format === 'rss2') { | 28 | } else if (format === 'rss' || format === 'rss2') { |
29 | acceptableContentTypes = ['application/rss+xml', 'application/xml', 'text/xml'] | 29 | acceptableContentTypes = [ 'application/rss+xml', 'application/xml', 'text/xml' ] |
30 | } else { | 30 | } else { |
31 | acceptableContentTypes = ['application/xml', 'text/xml'] | 31 | acceptableContentTypes = [ 'application/xml', 'text/xml' ] |
32 | } | 32 | } |
33 | 33 | ||
34 | if (req.accepts(acceptableContentTypes)) { | 34 | if (req.accepts(acceptableContentTypes)) { |
diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts index a98d32d86..7808135f7 100644 --- a/server/middlewares/validators/follows.ts +++ b/server/middlewares/validators/follows.ts | |||
@@ -3,7 +3,6 @@ import { body, param, query } from 'express-validator' | |||
3 | import { isTestInstance } from '../../helpers/core-utils' | 3 | import { isTestInstance } from '../../helpers/core-utils' |
4 | import { isEachUniqueHostValid, isHostValid } from '../../helpers/custom-validators/servers' | 4 | import { isEachUniqueHostValid, isHostValid } from '../../helpers/custom-validators/servers' |
5 | import { logger } from '../../helpers/logger' | 5 | import { logger } from '../../helpers/logger' |
6 | import { getServerActor } from '../../helpers/utils' | ||
7 | import { SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' | 6 | import { SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' |
8 | import { ActorFollowModel } from '../../models/activitypub/actor-follow' | 7 | import { ActorFollowModel } from '../../models/activitypub/actor-follow' |
9 | import { areValidationErrors } from './utils' | 8 | import { areValidationErrors } from './utils' |
@@ -12,6 +11,7 @@ import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger' | |||
12 | import { isActorTypeValid, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor' | 11 | import { isActorTypeValid, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor' |
13 | import { MActorFollowActorsDefault } from '@server/typings/models' | 12 | import { MActorFollowActorsDefault } from '@server/typings/models' |
14 | import { isFollowStateValid } from '@server/helpers/custom-validators/follows' | 13 | import { isFollowStateValid } from '@server/helpers/custom-validators/follows' |
14 | import { getServerActor } from '@server/models/application/application' | ||
15 | 15 | ||
16 | const listFollowsValidator = [ | 16 | const listFollowsValidator = [ |
17 | query('state') | 17 | query('state') |
diff --git a/server/middlewares/validators/plugins.ts b/server/middlewares/validators/plugins.ts index 910d03c29..2cb49ec43 100644 --- a/server/middlewares/validators/plugins.ts +++ b/server/middlewares/validators/plugins.ts | |||
@@ -1,33 +1,72 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param, query } from 'express-validator' | 2 | import { body, param, query, ValidationChain } from 'express-validator' |
3 | import { logger } from '../../helpers/logger' | 3 | import { logger } from '../../helpers/logger' |
4 | import { areValidationErrors } from './utils' | 4 | import { areValidationErrors } from './utils' |
5 | import { isNpmPluginNameValid, isPluginNameValid, isPluginTypeValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' | 5 | import { isNpmPluginNameValid, isPluginNameValid, isPluginTypeValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' |
6 | import { PluginManager } from '../../lib/plugins/plugin-manager' | 6 | import { PluginManager } from '../../lib/plugins/plugin-manager' |
7 | import { isBooleanValid, isSafePath, toBooleanOrNull } from '../../helpers/custom-validators/misc' | 7 | import { isBooleanValid, isSafePath, toBooleanOrNull, exists } from '../../helpers/custom-validators/misc' |
8 | import { PluginModel } from '../../models/server/plugin' | 8 | import { PluginModel } from '../../models/server/plugin' |
9 | import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/install-plugin.model' | 9 | import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/install-plugin.model' |
10 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | 10 | import { PluginType } from '../../../shared/models/plugins/plugin.type' |
11 | import { CONFIG } from '../../initializers/config' | 11 | import { CONFIG } from '../../initializers/config' |
12 | 12 | ||
13 | const servePluginStaticDirectoryValidator = (pluginType: PluginType) => [ | 13 | const getPluginValidator = (pluginType: PluginType, withVersion = true) => { |
14 | param('pluginName').custom(isPluginNameValid).withMessage('Should have a valid plugin name'), | 14 | const validators: (ValidationChain | express.Handler)[] = [ |
15 | param('pluginVersion').custom(isPluginVersionValid).withMessage('Should have a valid plugin version'), | 15 | param('pluginName').custom(isPluginNameValid).withMessage('Should have a valid plugin name') |
16 | param('staticEndpoint').custom(isSafePath).withMessage('Should have a valid static endpoint'), | 16 | ] |
17 | |||
18 | if (withVersion) { | ||
19 | validators.push( | ||
20 | param('pluginVersion').custom(isPluginVersionValid).withMessage('Should have a valid plugin version') | ||
21 | ) | ||
22 | } | ||
23 | |||
24 | return validators.concat([ | ||
25 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
26 | logger.debug('Checking getPluginValidator parameters', { parameters: req.params }) | ||
27 | |||
28 | if (areValidationErrors(req, res)) return | ||
29 | |||
30 | const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType) | ||
31 | const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName) | ||
32 | |||
33 | if (!plugin) return res.sendStatus(404) | ||
34 | if (withVersion && plugin.version !== req.params.pluginVersion) return res.sendStatus(404) | ||
35 | |||
36 | res.locals.registeredPlugin = plugin | ||
37 | |||
38 | return next() | ||
39 | } | ||
40 | ]) | ||
41 | } | ||
42 | |||
43 | const getExternalAuthValidator = [ | ||
44 | param('authName').custom(exists).withMessage('Should have a valid auth name'), | ||
17 | 45 | ||
18 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 46 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
19 | logger.debug('Checking servePluginStaticDirectory parameters', { parameters: req.params }) | 47 | logger.debug('Checking getExternalAuthValidator parameters', { parameters: req.params }) |
20 | 48 | ||
21 | if (areValidationErrors(req, res)) return | 49 | if (areValidationErrors(req, res)) return |
22 | 50 | ||
23 | const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType) | 51 | const plugin = res.locals.registeredPlugin |
24 | const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName) | 52 | if (!plugin.registerHelpersStore) return res.sendStatus(404) |
25 | 53 | ||
26 | if (!plugin || plugin.version !== req.params.pluginVersion) { | 54 | const externalAuth = plugin.registerHelpersStore.getExternalAuths().find(a => a.authName === req.params.authName) |
27 | return res.sendStatus(404) | 55 | if (!externalAuth) return res.sendStatus(404) |
28 | } | 56 | |
57 | res.locals.externalAuth = externalAuth | ||
58 | |||
59 | return next() | ||
60 | } | ||
61 | ] | ||
29 | 62 | ||
30 | res.locals.registeredPlugin = plugin | 63 | const pluginStaticDirectoryValidator = [ |
64 | param('staticEndpoint').custom(isSafePath).withMessage('Should have a valid static endpoint'), | ||
65 | |||
66 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
67 | logger.debug('Checking pluginStaticDirectoryValidator parameters', { parameters: req.params }) | ||
68 | |||
69 | if (areValidationErrors(req, res)) return | ||
31 | 70 | ||
32 | return next() | 71 | return next() |
33 | } | 72 | } |
@@ -149,11 +188,13 @@ const listAvailablePluginsValidator = [ | |||
149 | // --------------------------------------------------------------------------- | 188 | // --------------------------------------------------------------------------- |
150 | 189 | ||
151 | export { | 190 | export { |
152 | servePluginStaticDirectoryValidator, | 191 | pluginStaticDirectoryValidator, |
192 | getPluginValidator, | ||
153 | updatePluginSettingsValidator, | 193 | updatePluginSettingsValidator, |
154 | uninstallPluginValidator, | 194 | uninstallPluginValidator, |
155 | listAvailablePluginsValidator, | 195 | listAvailablePluginsValidator, |
156 | existingPluginValidator, | 196 | existingPluginValidator, |
157 | installOrUpdatePluginValidator, | 197 | installOrUpdatePluginValidator, |
158 | listPluginsValidator | 198 | listPluginsValidator, |
199 | getExternalAuthValidator | ||
159 | } | 200 | } |
diff --git a/server/middlewares/validators/redundancy.ts b/server/middlewares/validators/redundancy.ts index 8098e3a44..8cd3bc33d 100644 --- a/server/middlewares/validators/redundancy.ts +++ b/server/middlewares/validators/redundancy.ts | |||
@@ -1,12 +1,13 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { exists, isBooleanValid, isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' | 3 | import { exists, isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' |
4 | import { logger } from '../../helpers/logger' | 4 | import { logger } from '../../helpers/logger' |
5 | import { areValidationErrors } from './utils' | 5 | import { areValidationErrors } from './utils' |
6 | import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy' | 6 | import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy' |
7 | import { isHostValid } from '../../helpers/custom-validators/servers' | 7 | import { isHostValid } from '../../helpers/custom-validators/servers' |
8 | import { ServerModel } from '../../models/server/server' | 8 | import { ServerModel } from '../../models/server/server' |
9 | import { doesVideoExist } from '../../helpers/middlewares' | 9 | import { doesVideoExist } from '../../helpers/middlewares' |
10 | import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies' | ||
10 | 11 | ||
11 | const videoFileRedundancyGetValidator = [ | 12 | const videoFileRedundancyGetValidator = [ |
12 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), | 13 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), |
@@ -101,10 +102,77 @@ const updateServerRedundancyValidator = [ | |||
101 | } | 102 | } |
102 | ] | 103 | ] |
103 | 104 | ||
105 | const listVideoRedundanciesValidator = [ | ||
106 | query('target') | ||
107 | .custom(isVideoRedundancyTarget).withMessage('Should have a valid video redundancies target'), | ||
108 | |||
109 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
110 | logger.debug('Checking listVideoRedundanciesValidator parameters', { parameters: req.query }) | ||
111 | |||
112 | if (areValidationErrors(req, res)) return | ||
113 | |||
114 | return next() | ||
115 | } | ||
116 | ] | ||
117 | |||
118 | const addVideoRedundancyValidator = [ | ||
119 | body('videoId') | ||
120 | .custom(isIdValid) | ||
121 | .withMessage('Should have a valid video id'), | ||
122 | |||
123 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
124 | logger.debug('Checking addVideoRedundancyValidator parameters', { parameters: req.query }) | ||
125 | |||
126 | if (areValidationErrors(req, res)) return | ||
127 | |||
128 | if (!await doesVideoExist(req.body.videoId, res, 'only-video')) return | ||
129 | |||
130 | if (res.locals.onlyVideo.remote === false) { | ||
131 | return res.status(400) | ||
132 | .json({ error: 'Cannot create a redundancy on a local video' }) | ||
133 | .end() | ||
134 | } | ||
135 | |||
136 | const alreadyExists = await VideoRedundancyModel.isLocalByVideoUUIDExists(res.locals.onlyVideo.uuid) | ||
137 | if (alreadyExists) { | ||
138 | return res.status(409) | ||
139 | .json({ error: 'This video is already duplicated by your instance.' }) | ||
140 | } | ||
141 | |||
142 | return next() | ||
143 | } | ||
144 | ] | ||
145 | |||
146 | const removeVideoRedundancyValidator = [ | ||
147 | param('redundancyId') | ||
148 | .custom(isIdValid) | ||
149 | .withMessage('Should have a valid redundancy id'), | ||
150 | |||
151 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
152 | logger.debug('Checking removeVideoRedundancyValidator parameters', { parameters: req.query }) | ||
153 | |||
154 | if (areValidationErrors(req, res)) return | ||
155 | |||
156 | const redundancy = await VideoRedundancyModel.loadByIdWithVideo(parseInt(req.params.redundancyId, 10)) | ||
157 | if (!redundancy) { | ||
158 | return res.status(404) | ||
159 | .json({ error: 'Video redundancy not found' }) | ||
160 | .end() | ||
161 | } | ||
162 | |||
163 | res.locals.videoRedundancy = redundancy | ||
164 | |||
165 | return next() | ||
166 | } | ||
167 | ] | ||
168 | |||
104 | // --------------------------------------------------------------------------- | 169 | // --------------------------------------------------------------------------- |
105 | 170 | ||
106 | export { | 171 | export { |
107 | videoFileRedundancyGetValidator, | 172 | videoFileRedundancyGetValidator, |
108 | videoPlaylistRedundancyGetValidator, | 173 | videoPlaylistRedundancyGetValidator, |
109 | updateServerRedundancyValidator | 174 | updateServerRedundancyValidator, |
175 | listVideoRedundanciesValidator, | ||
176 | addVideoRedundancyValidator, | ||
177 | removeVideoRedundancyValidator | ||
110 | } | 178 | } |
diff --git a/server/middlewares/validators/server.ts b/server/middlewares/validators/server.ts index f6812647b..6158c3363 100644 --- a/server/middlewares/validators/server.ts +++ b/server/middlewares/validators/server.ts | |||
@@ -5,9 +5,8 @@ import { isHostValid, isValidContactBody } from '../../helpers/custom-validators | |||
5 | import { ServerModel } from '../../models/server/server' | 5 | import { ServerModel } from '../../models/server/server' |
6 | import { body } from 'express-validator' | 6 | import { body } from 'express-validator' |
7 | import { isUserDisplayNameValid } from '../../helpers/custom-validators/users' | 7 | import { isUserDisplayNameValid } from '../../helpers/custom-validators/users' |
8 | import { Emailer } from '../../lib/emailer' | ||
9 | import { Redis } from '../../lib/redis' | 8 | import { Redis } from '../../lib/redis' |
10 | import { CONFIG } from '../../initializers/config' | 9 | import { CONFIG, isEmailEnabled } from '../../initializers/config' |
11 | 10 | ||
12 | const serverGetValidator = [ | 11 | const serverGetValidator = [ |
13 | body('host').custom(isHostValid).withMessage('Should have a valid host'), | 12 | body('host').custom(isHostValid).withMessage('Should have a valid host'), |
@@ -50,7 +49,7 @@ const contactAdministratorValidator = [ | |||
50 | .end() | 49 | .end() |
51 | } | 50 | } |
52 | 51 | ||
53 | if (Emailer.isEnabled() === false) { | 52 | if (isEmailEnabled() === false) { |
54 | return res | 53 | return res |
55 | .status(409) | 54 | .status(409) |
56 | .send({ error: 'Emailer is not enabled on this instance.' }) | 55 | .send({ error: 'Emailer is not enabled on this instance.' }) |
diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index c75e701d6..b76dab722 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts | |||
@@ -23,6 +23,7 @@ const SORTABLE_USER_NOTIFICATIONS_COLUMNS = createSortableColumns(SORTABLE_COLUM | |||
23 | const SORTABLE_VIDEO_PLAYLISTS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_PLAYLISTS) | 23 | const SORTABLE_VIDEO_PLAYLISTS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_PLAYLISTS) |
24 | const SORTABLE_PLUGINS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.PLUGINS) | 24 | const SORTABLE_PLUGINS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.PLUGINS) |
25 | const SORTABLE_AVAILABLE_PLUGINS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.AVAILABLE_PLUGINS) | 25 | const SORTABLE_AVAILABLE_PLUGINS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.AVAILABLE_PLUGINS) |
26 | const SORTABLE_VIDEO_REDUNDANCIES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_REDUNDANCIES) | ||
26 | 27 | ||
27 | const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) | 28 | const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) |
28 | const accountsSortValidator = checkSort(SORTABLE_ACCOUNTS_COLUMNS) | 29 | const accountsSortValidator = checkSort(SORTABLE_ACCOUNTS_COLUMNS) |
@@ -45,6 +46,7 @@ const userNotificationsSortValidator = checkSort(SORTABLE_USER_NOTIFICATIONS_COL | |||
45 | const videoPlaylistsSortValidator = checkSort(SORTABLE_VIDEO_PLAYLISTS_COLUMNS) | 46 | const videoPlaylistsSortValidator = checkSort(SORTABLE_VIDEO_PLAYLISTS_COLUMNS) |
46 | const pluginsSortValidator = checkSort(SORTABLE_PLUGINS_COLUMNS) | 47 | const pluginsSortValidator = checkSort(SORTABLE_PLUGINS_COLUMNS) |
47 | const availablePluginsSortValidator = checkSort(SORTABLE_AVAILABLE_PLUGINS_COLUMNS) | 48 | const availablePluginsSortValidator = checkSort(SORTABLE_AVAILABLE_PLUGINS_COLUMNS) |
49 | const videoRedundanciesSortValidator = checkSort(SORTABLE_VIDEO_REDUNDANCIES_COLUMNS) | ||
48 | 50 | ||
49 | // --------------------------------------------------------------------------- | 51 | // --------------------------------------------------------------------------- |
50 | 52 | ||
@@ -69,5 +71,6 @@ export { | |||
69 | serversBlocklistSortValidator, | 71 | serversBlocklistSortValidator, |
70 | userNotificationsSortValidator, | 72 | userNotificationsSortValidator, |
71 | videoPlaylistsSortValidator, | 73 | videoPlaylistsSortValidator, |
74 | videoRedundanciesSortValidator, | ||
72 | pluginsSortValidator | 75 | pluginsSortValidator |
73 | } | 76 | } |
diff --git a/server/middlewares/validators/themes.ts b/server/middlewares/validators/themes.ts index 24a9673f7..82794656d 100644 --- a/server/middlewares/validators/themes.ts +++ b/server/middlewares/validators/themes.ts | |||
@@ -16,7 +16,7 @@ const serveThemeCSSValidator = [ | |||
16 | 16 | ||
17 | if (areValidationErrors(req, res)) return | 17 | if (areValidationErrors(req, res)) return |
18 | 18 | ||
19 | const theme = PluginManager.Instance.getRegisteredTheme(req.params.themeName) | 19 | const theme = PluginManager.Instance.getRegisteredThemeByShortName(req.params.themeName) |
20 | 20 | ||
21 | if (!theme || theme.version !== req.params.themeVersion) { | 21 | if (!theme || theme.version !== req.params.themeVersion) { |
22 | return res.sendStatus(404) | 22 | return res.sendStatus(404) |
diff --git a/server/middlewares/validators/user-subscriptions.ts b/server/middlewares/validators/user-subscriptions.ts index 9bc8c87e7..5d4cc94c5 100644 --- a/server/middlewares/validators/user-subscriptions.ts +++ b/server/middlewares/validators/user-subscriptions.ts | |||
@@ -53,7 +53,6 @@ const userSubscriptionGetValidator = [ | |||
53 | .json({ | 53 | .json({ |
54 | error: `Subscription ${req.params.uri} not found.` | 54 | error: `Subscription ${req.params.uri} not found.` |
55 | }) | 55 | }) |
56 | .end() | ||
57 | } | 56 | } |
58 | 57 | ||
59 | res.locals.subscription = subscription | 58 | res.locals.subscription = subscription |
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index c78c67a8c..840b9fc74 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import * as express from 'express' | 2 | import * as express from 'express' |
3 | import { body, param } from 'express-validator' | 3 | import { body, param, query } from 'express-validator' |
4 | import { omit } from 'lodash' | 4 | import { omit } from 'lodash' |
5 | import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' | 5 | import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' |
6 | import { | 6 | import { |
@@ -14,6 +14,7 @@ import { | |||
14 | isUserDisplayNameValid, | 14 | isUserDisplayNameValid, |
15 | isUserNSFWPolicyValid, | 15 | isUserNSFWPolicyValid, |
16 | isUserPasswordValid, | 16 | isUserPasswordValid, |
17 | isUserPasswordValidOrEmpty, | ||
17 | isUserRoleValid, | 18 | isUserRoleValid, |
18 | isUserUsernameValid, | 19 | isUserUsernameValid, |
19 | isUserVideoLanguages, | 20 | isUserVideoLanguages, |
@@ -36,11 +37,10 @@ import { doesVideoExist } from '../../helpers/middlewares' | |||
36 | import { UserRole } from '../../../shared/models/users' | 37 | import { UserRole } from '../../../shared/models/users' |
37 | import { MUserDefault } from '@server/typings/models' | 38 | import { MUserDefault } from '@server/typings/models' |
38 | import { Hooks } from '@server/lib/plugins/hooks' | 39 | import { Hooks } from '@server/lib/plugins/hooks' |
39 | import { isLocalVideoAccepted } from '@server/lib/moderation' | ||
40 | 40 | ||
41 | const usersAddValidator = [ | 41 | const usersAddValidator = [ |
42 | body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), | 42 | body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), |
43 | body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'), | 43 | body('password').custom(isUserPasswordValidOrEmpty).withMessage('Should have a valid password'), |
44 | body('email').isEmail().withMessage('Should have a valid email'), | 44 | body('email').isEmail().withMessage('Should have a valid email'), |
45 | body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), | 45 | body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), |
46 | body('videoQuotaDaily').custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily user quota'), | 46 | body('videoQuotaDaily').custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily user quota'), |
@@ -149,7 +149,7 @@ const usersBlockingValidator = [ | |||
149 | ] | 149 | ] |
150 | 150 | ||
151 | const deleteMeValidator = [ | 151 | const deleteMeValidator = [ |
152 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 152 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
153 | const user = res.locals.oauth.token.User | 153 | const user = res.locals.oauth.token.User |
154 | if (user.username === 'root') { | 154 | if (user.username === 'root') { |
155 | return res.status(400) | 155 | return res.status(400) |
@@ -256,12 +256,13 @@ const usersUpdateMeValidator = [ | |||
256 | 256 | ||
257 | const usersGetValidator = [ | 257 | const usersGetValidator = [ |
258 | param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), | 258 | param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), |
259 | query('withStats').optional().isBoolean().withMessage('Should have a valid stats flag'), | ||
259 | 260 | ||
260 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 261 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
261 | logger.debug('Checking usersGet parameters', { parameters: req.params }) | 262 | logger.debug('Checking usersGet parameters', { parameters: req.params }) |
262 | 263 | ||
263 | if (areValidationErrors(req, res)) return | 264 | if (areValidationErrors(req, res)) return |
264 | if (!await checkUserIdExist(req.params.id, res)) return | 265 | if (!await checkUserIdExist(req.params.id, res, req.query.withStats)) return |
265 | 266 | ||
266 | return next() | 267 | return next() |
267 | } | 268 | } |
@@ -303,7 +304,7 @@ const ensureUserRegistrationAllowed = [ | |||
303 | ] | 304 | ] |
304 | 305 | ||
305 | const ensureUserRegistrationAllowedForIP = [ | 306 | const ensureUserRegistrationAllowedForIP = [ |
306 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 307 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
307 | const allowed = isSignupAllowedForCurrentIP(req.ip) | 308 | const allowed = isSignupAllowedForCurrentIP(req.ip) |
308 | 309 | ||
309 | if (allowed === false) { | 310 | if (allowed === false) { |
@@ -410,7 +411,7 @@ const userAutocompleteValidator = [ | |||
410 | ] | 411 | ] |
411 | 412 | ||
412 | const ensureAuthUserOwnsAccountValidator = [ | 413 | const ensureAuthUserOwnsAccountValidator = [ |
413 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 414 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
414 | const user = res.locals.oauth.token.User | 415 | const user = res.locals.oauth.token.User |
415 | 416 | ||
416 | if (res.locals.account.id !== user.Account.id) { | 417 | if (res.locals.account.id !== user.Account.id) { |
@@ -460,9 +461,9 @@ export { | |||
460 | 461 | ||
461 | // --------------------------------------------------------------------------- | 462 | // --------------------------------------------------------------------------- |
462 | 463 | ||
463 | function checkUserIdExist (idArg: number | string, res: express.Response) { | 464 | function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) { |
464 | const id = parseInt(idArg + '', 10) | 465 | const id = parseInt(idArg + '', 10) |
465 | return checkUserExist(() => UserModel.loadById(id), res) | 466 | return checkUserExist(() => UserModel.loadById(id, withStats), res) |
466 | } | 467 | } |
467 | 468 | ||
468 | function checkUserEmailExist (email: string, res: express.Response, abortResponse = true) { | 469 | function checkUserEmailExist (email: string, res: express.Response, abortResponse = true) { |
diff --git a/server/middlewares/validators/videos/video-abuses.ts b/server/middlewares/validators/videos/video-abuses.ts index a4aef4024..901997bcb 100644 --- a/server/middlewares/validators/videos/video-abuses.ts +++ b/server/middlewares/validators/videos/video-abuses.ts | |||
@@ -1,14 +1,15 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' | 3 | import { exists, isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' |
4 | import { logger } from '../../../helpers/logger' | ||
5 | import { areValidationErrors } from '../utils' | ||
6 | import { | 4 | import { |
5 | isAbuseVideoIsValid, | ||
7 | isVideoAbuseModerationCommentValid, | 6 | isVideoAbuseModerationCommentValid, |
8 | isVideoAbuseReasonValid, | 7 | isVideoAbuseReasonValid, |
9 | isVideoAbuseStateValid | 8 | isVideoAbuseStateValid |
10 | } from '../../../helpers/custom-validators/video-abuses' | 9 | } from '../../../helpers/custom-validators/video-abuses' |
10 | import { logger } from '../../../helpers/logger' | ||
11 | import { doesVideoAbuseExist, doesVideoExist } from '../../../helpers/middlewares' | 11 | import { doesVideoAbuseExist, doesVideoExist } from '../../../helpers/middlewares' |
12 | import { areValidationErrors } from '../utils' | ||
12 | 13 | ||
13 | const videoAbuseReportValidator = [ | 14 | const videoAbuseReportValidator = [ |
14 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 15 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
@@ -32,8 +33,7 @@ const videoAbuseGetValidator = [ | |||
32 | logger.debug('Checking videoAbuseGetValidator parameters', { parameters: req.body }) | 33 | logger.debug('Checking videoAbuseGetValidator parameters', { parameters: req.body }) |
33 | 34 | ||
34 | if (areValidationErrors(req, res)) return | 35 | if (areValidationErrors(req, res)) return |
35 | if (!await doesVideoExist(req.params.videoId, res)) return | 36 | if (!await doesVideoAbuseExist(req.params.id, req.params.videoId, res)) return |
36 | if (!await doesVideoAbuseExist(req.params.id, res.locals.videoAll.id, res)) return | ||
37 | 37 | ||
38 | return next() | 38 | return next() |
39 | } | 39 | } |
@@ -53,8 +53,42 @@ const videoAbuseUpdateValidator = [ | |||
53 | logger.debug('Checking videoAbuseUpdateValidator parameters', { parameters: req.body }) | 53 | logger.debug('Checking videoAbuseUpdateValidator parameters', { parameters: req.body }) |
54 | 54 | ||
55 | if (areValidationErrors(req, res)) return | 55 | if (areValidationErrors(req, res)) return |
56 | if (!await doesVideoExist(req.params.videoId, res)) return | 56 | if (!await doesVideoAbuseExist(req.params.id, req.params.videoId, res)) return |
57 | if (!await doesVideoAbuseExist(req.params.id, res.locals.videoAll.id, res)) return | 57 | |
58 | return next() | ||
59 | } | ||
60 | ] | ||
61 | |||
62 | const videoAbuseListValidator = [ | ||
63 | query('id') | ||
64 | .optional() | ||
65 | .custom(isIdValid).withMessage('Should have a valid id'), | ||
66 | query('search') | ||
67 | .optional() | ||
68 | .custom(exists).withMessage('Should have a valid search'), | ||
69 | query('state') | ||
70 | .optional() | ||
71 | .custom(isVideoAbuseStateValid).withMessage('Should have a valid video abuse state'), | ||
72 | query('videoIs') | ||
73 | .optional() | ||
74 | .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'), | ||
75 | query('searchReporter') | ||
76 | .optional() | ||
77 | .custom(exists).withMessage('Should have a valid reporter search'), | ||
78 | query('searchReportee') | ||
79 | .optional() | ||
80 | .custom(exists).withMessage('Should have a valid reportee search'), | ||
81 | query('searchVideo') | ||
82 | .optional() | ||
83 | .custom(exists).withMessage('Should have a valid video search'), | ||
84 | query('searchVideoChannel') | ||
85 | .optional() | ||
86 | .custom(exists).withMessage('Should have a valid video channel search'), | ||
87 | |||
88 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
89 | logger.debug('Checking videoAbuseListValidator parameters', { parameters: req.body }) | ||
90 | |||
91 | if (areValidationErrors(req, res)) return | ||
58 | 92 | ||
59 | return next() | 93 | return next() |
60 | } | 94 | } |
@@ -63,6 +97,7 @@ const videoAbuseUpdateValidator = [ | |||
63 | // --------------------------------------------------------------------------- | 97 | // --------------------------------------------------------------------------- |
64 | 98 | ||
65 | export { | 99 | export { |
100 | videoAbuseListValidator, | ||
66 | videoAbuseReportValidator, | 101 | videoAbuseReportValidator, |
67 | videoAbuseGetValidator, | 102 | videoAbuseGetValidator, |
68 | videoAbuseUpdateValidator | 103 | videoAbuseUpdateValidator |
diff --git a/server/middlewares/validators/videos/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts index 5440e57e7..4bd6a8333 100644 --- a/server/middlewares/validators/videos/video-blacklist.ts +++ b/server/middlewares/validators/videos/video-blacklist.ts | |||
@@ -69,6 +69,10 @@ const videosBlacklistFiltersValidator = [ | |||
69 | query('type') | 69 | query('type') |
70 | .optional() | 70 | .optional() |
71 | .custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'), | 71 | .custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'), |
72 | query('search') | ||
73 | .optional() | ||
74 | .not() | ||
75 | .isEmpty().withMessage('Should have a valid search'), | ||
72 | 76 | ||
73 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 77 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
74 | logger.debug('Checking videos blacklist filters query', { parameters: req.query }) | 78 | logger.debug('Checking videos blacklist filters query', { parameters: req.query }) |
diff --git a/server/middlewares/validators/videos/video-captions.ts b/server/middlewares/validators/videos/video-captions.ts index 7b0cd6f66..872d9c2ab 100644 --- a/server/middlewares/validators/videos/video-captions.ts +++ b/server/middlewares/validators/videos/video-captions.ts | |||
@@ -13,10 +13,12 @@ const addVideoCaptionValidator = [ | |||
13 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), | 13 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), |
14 | param('captionLanguage').custom(isVideoCaptionLanguageValid).not().isEmpty().withMessage('Should have a valid caption language'), | 14 | param('captionLanguage').custom(isVideoCaptionLanguageValid).not().isEmpty().withMessage('Should have a valid caption language'), |
15 | body('captionfile') | 15 | body('captionfile') |
16 | .custom((_, { req }) => isVideoCaptionFile(req.files, 'captionfile')).withMessage( | 16 | .custom((_, { req }) => isVideoCaptionFile(req.files, 'captionfile')) |
17 | `This caption file is not supported or too large. Please, make sure it is under ${CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE} and one of the following mimetypes: ` | 17 | .withMessage( |
18 | + Object.keys(MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT).map(key => `${key} (${MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT[key]})`).join(', ') | 18 | 'This caption file is not supported or too large. ' + |
19 | ), | 19 | `Please, make sure it is under ${CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE} and one of the following mimetypes: ` + |
20 | Object.keys(MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT).map(key => `${key} (${MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT[key]})`).join(', ') | ||
21 | ), | ||
20 | 22 | ||
21 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 23 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
22 | logger.debug('Checking addVideoCaption parameters', { parameters: req.body }) | 24 | logger.debug('Checking addVideoCaption parameters', { parameters: req.body }) |
diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts index ebce14714..882fb2b84 100644 --- a/server/middlewares/validators/videos/video-channels.ts +++ b/server/middlewares/validators/videos/video-channels.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { UserRight } from '../../../../shared' | 3 | import { UserRight } from '../../../../shared' |
4 | import { | 4 | import { |
5 | isVideoChannelDescriptionValid, | 5 | isVideoChannelDescriptionValid, |
@@ -128,6 +128,15 @@ const localVideoChannelValidator = [ | |||
128 | } | 128 | } |
129 | ] | 129 | ] |
130 | 130 | ||
131 | const videoChannelStatsValidator = [ | ||
132 | query('withStats').optional().isBoolean().withMessage('Should have a valid stats flag'), | ||
133 | |||
134 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
135 | if (areValidationErrors(req, res)) return | ||
136 | return next() | ||
137 | } | ||
138 | ] | ||
139 | |||
131 | // --------------------------------------------------------------------------- | 140 | // --------------------------------------------------------------------------- |
132 | 141 | ||
133 | export { | 142 | export { |
@@ -135,7 +144,8 @@ export { | |||
135 | videoChannelsUpdateValidator, | 144 | videoChannelsUpdateValidator, |
136 | videoChannelsRemoveValidator, | 145 | videoChannelsRemoveValidator, |
137 | videoChannelsNameWithHostValidator, | 146 | videoChannelsNameWithHostValidator, |
138 | localVideoChannelValidator | 147 | localVideoChannelValidator, |
148 | videoChannelStatsValidator | ||
139 | } | 149 | } |
140 | 150 | ||
141 | // --------------------------------------------------------------------------- | 151 | // --------------------------------------------------------------------------- |
diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts index 77c5f940d..4846a5e9e 100644 --- a/server/middlewares/validators/videos/video-comments.ts +++ b/server/middlewares/validators/videos/video-comments.ts | |||
@@ -1,16 +1,16 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param } from 'express-validator' | 2 | import { body, param } from 'express-validator' |
3 | import { MUserAccountUrl } from '@server/typings/models' | ||
3 | import { UserRight } from '../../../../shared' | 4 | import { UserRight } from '../../../../shared' |
4 | import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' | 5 | import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' |
5 | import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments' | 6 | import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments' |
6 | import { logger } from '../../../helpers/logger' | 7 | import { logger } from '../../../helpers/logger' |
8 | import { doesVideoExist } from '../../../helpers/middlewares' | ||
9 | import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation' | ||
10 | import { Hooks } from '../../../lib/plugins/hooks' | ||
7 | import { VideoCommentModel } from '../../../models/video/video-comment' | 11 | import { VideoCommentModel } from '../../../models/video/video-comment' |
12 | import { MCommentOwnerVideoReply, MVideo, MVideoFullLight, MVideoId } from '../../../typings/models/video' | ||
8 | import { areValidationErrors } from '../utils' | 13 | import { areValidationErrors } from '../utils' |
9 | import { Hooks } from '../../../lib/plugins/hooks' | ||
10 | import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation' | ||
11 | import { doesVideoExist } from '../../../helpers/middlewares' | ||
12 | import { MCommentOwner, MVideo, MVideoFullLight, MVideoId } from '../../../typings/models/video' | ||
13 | import { MUser } from '@server/typings/models' | ||
14 | 14 | ||
15 | const listVideoCommentThreadsValidator = [ | 15 | const listVideoCommentThreadsValidator = [ |
16 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 16 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
@@ -50,7 +50,7 @@ const addVideoCommentThreadValidator = [ | |||
50 | if (areValidationErrors(req, res)) return | 50 | if (areValidationErrors(req, res)) return |
51 | if (!await doesVideoExist(req.params.videoId, res)) return | 51 | if (!await doesVideoExist(req.params.videoId, res)) return |
52 | if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return | 52 | if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return |
53 | if (!await isVideoCommentAccepted(req, res, res.locals.videoAll,false)) return | 53 | if (!await isVideoCommentAccepted(req, res, res.locals.videoAll, false)) return |
54 | 54 | ||
55 | return next() | 55 | return next() |
56 | } | 56 | } |
@@ -188,7 +188,7 @@ function isVideoCommentsEnabled (video: MVideo, res: express.Response) { | |||
188 | return true | 188 | return true |
189 | } | 189 | } |
190 | 190 | ||
191 | function checkUserCanDeleteVideoComment (user: MUser, videoComment: MCommentOwner, res: express.Response) { | 191 | function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) { |
192 | if (videoComment.isDeleted()) { | 192 | if (videoComment.isDeleted()) { |
193 | res.status(409) | 193 | res.status(409) |
194 | .json({ error: 'This comment is already deleted' }) | 194 | .json({ error: 'This comment is already deleted' }) |
@@ -196,11 +196,16 @@ function checkUserCanDeleteVideoComment (user: MUser, videoComment: MCommentOwne | |||
196 | return false | 196 | return false |
197 | } | 197 | } |
198 | 198 | ||
199 | const account = videoComment.Account | 199 | const userAccount = user.Account |
200 | if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && account.userId !== user.id) { | 200 | |
201 | if ( | ||
202 | user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && // Not a moderator | ||
203 | videoComment.accountId !== userAccount.id && // Not the comment owner | ||
204 | videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner | ||
205 | ) { | ||
201 | res.status(403) | 206 | res.status(403) |
202 | .json({ error: 'Cannot remove video comment of another user' }) | 207 | .json({ error: 'Cannot remove video comment of another user' }) |
203 | .end() | 208 | |
204 | return false | 209 | return false |
205 | } | 210 | } |
206 | 211 | ||
diff --git a/server/middlewares/validators/videos/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts index 318dad100..5dc5db533 100644 --- a/server/middlewares/validators/videos/video-imports.ts +++ b/server/middlewares/validators/videos/video-imports.ts | |||
@@ -22,10 +22,11 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([ | |||
22 | .optional() | 22 | .optional() |
23 | .custom(isVideoMagnetUriValid).withMessage('Should have a valid video magnet URI'), | 23 | .custom(isVideoMagnetUriValid).withMessage('Should have a valid video magnet URI'), |
24 | body('torrentfile') | 24 | body('torrentfile') |
25 | .custom((value, { req }) => isVideoImportTorrentFile(req.files)).withMessage( | 25 | .custom((value, { req }) => isVideoImportTorrentFile(req.files)) |
26 | 'This torrent file is not supported or too large. Please, make sure it is of the following type: ' | 26 | .withMessage( |
27 | + CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.EXTNAME.join(', ') | 27 | 'This torrent file is not supported or too large. Please, make sure it is of the following type: ' + |
28 | ), | 28 | CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.EXTNAME.join(', ') |
29 | ), | ||
29 | body('name') | 30 | body('name') |
30 | .optional() | 31 | .optional() |
31 | .custom(isVideoNameValid).withMessage('Should have a valid name'), | 32 | .custom(isVideoNameValid).withMessage('Should have a valid name'), |
diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts index 1d67e8666..6b15c5464 100644 --- a/server/middlewares/validators/videos/video-playlists.ts +++ b/server/middlewares/validators/videos/video-playlists.ts | |||
@@ -384,10 +384,11 @@ export { | |||
384 | function getCommonPlaylistEditAttributes () { | 384 | function getCommonPlaylistEditAttributes () { |
385 | return [ | 385 | return [ |
386 | body('thumbnailfile') | 386 | body('thumbnailfile') |
387 | .custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage( | 387 | .custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')) |
388 | 'This thumbnail file is not supported or too large. Please, make sure it is of the following type: ' | 388 | .withMessage( |
389 | + CONSTRAINTS_FIELDS.VIDEO_PLAYLISTS.IMAGE.EXTNAME.join(', ') | 389 | 'This thumbnail file is not supported or too large. Please, make sure it is of the following type: ' + |
390 | ), | 390 | CONSTRAINTS_FIELDS.VIDEO_PLAYLISTS.IMAGE.EXTNAME.join(', ') |
391 | ), | ||
391 | 392 | ||
392 | body('description') | 393 | body('description') |
393 | .optional() | 394 | .optional() |
diff --git a/server/middlewares/validators/videos/video-rates.ts b/server/middlewares/validators/videos/video-rates.ts index 4021cfecc..cbc144f69 100644 --- a/server/middlewares/validators/videos/video-rates.ts +++ b/server/middlewares/validators/videos/video-rates.ts | |||
@@ -24,7 +24,7 @@ const videoUpdateRateValidator = [ | |||
24 | } | 24 | } |
25 | ] | 25 | ] |
26 | 26 | ||
27 | const getAccountVideoRateValidator = function (rateType: VideoRateType) { | 27 | const getAccountVideoRateValidatorFactory = function (rateType: VideoRateType) { |
28 | return [ | 28 | return [ |
29 | param('name').custom(isAccountNameValid).withMessage('Should have a valid account name'), | 29 | param('name').custom(isAccountNameValid).withMessage('Should have a valid account name'), |
30 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 30 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
@@ -51,7 +51,7 @@ const getAccountVideoRateValidator = function (rateType: VideoRateType) { | |||
51 | const videoRatingValidator = [ | 51 | const videoRatingValidator = [ |
52 | query('rating').optional().custom(isRatingValid).withMessage('Value must be one of "like" or "dislike"'), | 52 | query('rating').optional().custom(isRatingValid).withMessage('Value must be one of "like" or "dislike"'), |
53 | 53 | ||
54 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 54 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
55 | logger.debug('Checking rating parameter', { parameters: req.params }) | 55 | logger.debug('Checking rating parameter', { parameters: req.params }) |
56 | 56 | ||
57 | if (areValidationErrors(req, res)) return | 57 | if (areValidationErrors(req, res)) return |
@@ -64,6 +64,6 @@ const videoRatingValidator = [ | |||
64 | 64 | ||
65 | export { | 65 | export { |
66 | videoUpdateRateValidator, | 66 | videoUpdateRateValidator, |
67 | getAccountVideoRateValidator, | 67 | getAccountVideoRateValidatorFactory, |
68 | videoRatingValidator | 68 | videoRatingValidator |
69 | } | 69 | } |
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 6733d9dec..867c05fc1 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts | |||
@@ -29,7 +29,7 @@ import { | |||
29 | } from '../../../helpers/custom-validators/videos' | 29 | } from '../../../helpers/custom-validators/videos' |
30 | import { getDurationFromVideoFile } from '../../../helpers/ffmpeg-utils' | 30 | import { getDurationFromVideoFile } from '../../../helpers/ffmpeg-utils' |
31 | import { logger } from '../../../helpers/logger' | 31 | import { logger } from '../../../helpers/logger' |
32 | import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' | 32 | import { CONSTRAINTS_FIELDS, OVERVIEWS } from '../../../initializers/constants' |
33 | import { authenticatePromiseIfNeeded } from '../../oauth' | 33 | import { authenticatePromiseIfNeeded } from '../../oauth' |
34 | import { areValidationErrors } from '../utils' | 34 | import { areValidationErrors } from '../utils' |
35 | import { cleanUpReqFiles } from '../../../helpers/express-utils' | 35 | import { cleanUpReqFiles } from '../../../helpers/express-utils' |
@@ -38,19 +38,24 @@ import { checkUserCanTerminateOwnershipChange, doesChangeVideoOwnershipExist } f | |||
38 | import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/video-change-ownership-accept.model' | 38 | import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/video-change-ownership-accept.model' |
39 | import { AccountModel } from '../../../models/account/account' | 39 | import { AccountModel } from '../../../models/account/account' |
40 | import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search' | 40 | import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search' |
41 | import { getServerActor } from '../../../helpers/utils' | ||
42 | import { CONFIG } from '../../../initializers/config' | 41 | import { CONFIG } from '../../../initializers/config' |
43 | import { isLocalVideoAccepted } from '../../../lib/moderation' | 42 | import { isLocalVideoAccepted } from '../../../lib/moderation' |
44 | import { Hooks } from '../../../lib/plugins/hooks' | 43 | import { Hooks } from '../../../lib/plugins/hooks' |
45 | import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '../../../helpers/middlewares' | 44 | import { |
45 | checkUserCanManageVideo, | ||
46 | doesVideoChannelOfAccountExist, | ||
47 | doesVideoExist, | ||
48 | doesVideoFileOfVideoExist | ||
49 | } from '../../../helpers/middlewares' | ||
46 | import { MVideoFullLight } from '@server/typings/models' | 50 | import { MVideoFullLight } from '@server/typings/models' |
47 | import { getVideoWithAttributes } from '../../../helpers/video' | 51 | import { getVideoWithAttributes } from '../../../helpers/video' |
52 | import { getServerActor } from '@server/models/application/application' | ||
48 | 53 | ||
49 | const videosAddValidator = getCommonVideoEditAttributes().concat([ | 54 | const videosAddValidator = getCommonVideoEditAttributes().concat([ |
50 | body('videofile') | 55 | body('videofile') |
51 | .custom((value, { req }) => isVideoFile(req.files)).withMessage( | 56 | .custom((value, { req }) => isVideoFile(req.files)).withMessage( |
52 | 'This file is not supported or too large. Please, make sure it is of the following type: ' | 57 | 'This file is not supported or too large. Please, make sure it is of the following type: ' + |
53 | + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') | 58 | CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') |
54 | ), | 59 | ), |
55 | body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), | 60 | body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), |
56 | body('channelId') | 61 | body('channelId') |
@@ -147,7 +152,10 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R | |||
147 | }) | 152 | }) |
148 | } | 153 | } |
149 | 154 | ||
150 | const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video-with-rights', authenticateInQuery = false) => { | 155 | const videosCustomGetValidator = ( |
156 | fetchType: 'all' | 'only-video' | 'only-video-with-rights' | 'only-immutable-attributes', | ||
157 | authenticateInQuery = false | ||
158 | ) => { | ||
151 | return [ | 159 | return [ |
152 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 160 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
153 | 161 | ||
@@ -157,6 +165,9 @@ const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video- | |||
157 | if (areValidationErrors(req, res)) return | 165 | if (areValidationErrors(req, res)) return |
158 | if (!await doesVideoExist(req.params.id, res, fetchType)) return | 166 | if (!await doesVideoExist(req.params.id, res, fetchType)) return |
159 | 167 | ||
168 | // Controllers does not need to check video rights | ||
169 | if (fetchType === 'only-immutable-attributes') return next() | ||
170 | |||
160 | const video = getVideoWithAttributes(res) | 171 | const video = getVideoWithAttributes(res) |
161 | const videoAll = video as MVideoFullLight | 172 | const videoAll = video as MVideoFullLight |
162 | 173 | ||
@@ -192,6 +203,20 @@ const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video- | |||
192 | const videosGetValidator = videosCustomGetValidator('all') | 203 | const videosGetValidator = videosCustomGetValidator('all') |
193 | const videosDownloadValidator = videosCustomGetValidator('all', true) | 204 | const videosDownloadValidator = videosCustomGetValidator('all', true) |
194 | 205 | ||
206 | const videoFileMetadataGetValidator = getCommonVideoEditAttributes().concat([ | ||
207 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | ||
208 | param('videoFileId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid videoFileId'), | ||
209 | |||
210 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
211 | logger.debug('Checking videoFileMetadataGet parameters', { parameters: req.params }) | ||
212 | |||
213 | if (areValidationErrors(req, res)) return | ||
214 | if (!await doesVideoFileOfVideoExist(+req.params.videoFileId, req.params.id, res)) return | ||
215 | |||
216 | return next() | ||
217 | } | ||
218 | ]) | ||
219 | |||
195 | const videosRemoveValidator = [ | 220 | const videosRemoveValidator = [ |
196 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 221 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
197 | 222 | ||
@@ -245,19 +270,15 @@ const videosTerminateChangeOwnershipValidator = [ | |||
245 | // Check if the user who did the request is able to change the ownership of the video | 270 | // Check if the user who did the request is able to change the ownership of the video |
246 | if (!checkUserCanTerminateOwnershipChange(res.locals.oauth.token.User, res.locals.videoChangeOwnership, res)) return | 271 | if (!checkUserCanTerminateOwnershipChange(res.locals.oauth.token.User, res.locals.videoChangeOwnership, res)) return |
247 | 272 | ||
248 | return next() | ||
249 | }, | ||
250 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
251 | const videoChangeOwnership = res.locals.videoChangeOwnership | 273 | const videoChangeOwnership = res.locals.videoChangeOwnership |
252 | 274 | ||
253 | if (videoChangeOwnership.status === VideoChangeOwnershipStatus.WAITING) { | 275 | if (videoChangeOwnership.status !== VideoChangeOwnershipStatus.WAITING) { |
254 | return next() | ||
255 | } else { | ||
256 | res.status(403) | 276 | res.status(403) |
257 | .json({ error: 'Ownership already accepted or refused' }) | 277 | .json({ error: 'Ownership already accepted or refused' }) |
258 | |||
259 | return | 278 | return |
260 | } | 279 | } |
280 | |||
281 | return next() | ||
261 | } | 282 | } |
262 | ] | 283 | ] |
263 | 284 | ||
@@ -280,18 +301,31 @@ const videosAcceptChangeOwnershipValidator = [ | |||
280 | } | 301 | } |
281 | ] | 302 | ] |
282 | 303 | ||
304 | const videosOverviewValidator = [ | ||
305 | query('page') | ||
306 | .optional() | ||
307 | .isInt({ min: 1, max: OVERVIEWS.VIDEOS.SAMPLES_COUNT }) | ||
308 | .withMessage('Should have a valid pagination'), | ||
309 | |||
310 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
311 | if (areValidationErrors(req, res)) return | ||
312 | |||
313 | return next() | ||
314 | } | ||
315 | ] | ||
316 | |||
283 | function getCommonVideoEditAttributes () { | 317 | function getCommonVideoEditAttributes () { |
284 | return [ | 318 | return [ |
285 | body('thumbnailfile') | 319 | body('thumbnailfile') |
286 | .custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage( | 320 | .custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage( |
287 | 'This thumbnail file is not supported or too large. Please, make sure it is of the following type: ' | 321 | 'This thumbnail file is not supported or too large. Please, make sure it is of the following type: ' + |
288 | + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') | 322 | CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') |
289 | ), | 323 | ), |
290 | body('previewfile') | 324 | body('previewfile') |
291 | .custom((value, { req }) => isVideoImage(req.files, 'previewfile')).withMessage( | 325 | .custom((value, { req }) => isVideoImage(req.files, 'previewfile')).withMessage( |
292 | 'This preview file is not supported or too large. Please, make sure it is of the following type: ' | 326 | 'This preview file is not supported or too large. Please, make sure it is of the following type: ' + |
293 | + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') | 327 | CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') |
294 | ), | 328 | ), |
295 | 329 | ||
296 | body('category') | 330 | body('category') |
297 | .optional() | 331 | .optional() |
@@ -409,6 +443,7 @@ export { | |||
409 | videosAddValidator, | 443 | videosAddValidator, |
410 | videosUpdateValidator, | 444 | videosUpdateValidator, |
411 | videosGetValidator, | 445 | videosGetValidator, |
446 | videoFileMetadataGetValidator, | ||
412 | videosDownloadValidator, | 447 | videosDownloadValidator, |
413 | checkVideoFollowConstraints, | 448 | checkVideoFollowConstraints, |
414 | videosCustomGetValidator, | 449 | videosCustomGetValidator, |
@@ -420,7 +455,9 @@ export { | |||
420 | 455 | ||
421 | getCommonVideoEditAttributes, | 456 | getCommonVideoEditAttributes, |
422 | 457 | ||
423 | commonVideosFiltersValidator | 458 | commonVideosFiltersValidator, |
459 | |||
460 | videosOverviewValidator | ||
424 | } | 461 | } |
425 | 462 | ||
426 | // --------------------------------------------------------------------------- | 463 | // --------------------------------------------------------------------------- |
diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts index d50e6527f..5fe864f8b 100644 --- a/server/middlewares/validators/webfinger.ts +++ b/server/middlewares/validators/webfinger.ts | |||
@@ -18,15 +18,14 @@ const webfingerValidator = [ | |||
18 | const nameWithHost = getHostWithPort(req.query.resource.substr(5)) | 18 | const nameWithHost = getHostWithPort(req.query.resource.substr(5)) |
19 | const [ name ] = nameWithHost.split('@') | 19 | const [ name ] = nameWithHost.split('@') |
20 | 20 | ||
21 | // FIXME: we don't need the full actor | 21 | const actor = await ActorModel.loadLocalUrlByName(name) |
22 | const actor = await ActorModel.loadLocalByName(name) | ||
23 | if (!actor) { | 22 | if (!actor) { |
24 | return res.status(404) | 23 | return res.status(404) |
25 | .send({ error: 'Actor not found' }) | 24 | .send({ error: 'Actor not found' }) |
26 | .end() | 25 | .end() |
27 | } | 26 | } |
28 | 27 | ||
29 | res.locals.actorFull = actor | 28 | res.locals.actorUrl = actor |
30 | return next() | 29 | return next() |
31 | } | 30 | } |
32 | ] | 31 | ] |