diff options
Diffstat (limited to 'server/middlewares')
-rw-r--r-- | server/middlewares/csp.ts | 44 | ||||
-rw-r--r-- | server/middlewares/dnt.ts | 2 | ||||
-rw-r--r-- | server/middlewares/index.ts | 2 | ||||
-rw-r--r-- | server/middlewares/oauth.ts | 22 | ||||
-rw-r--r-- | server/middlewares/validators/config.ts | 19 | ||||
-rw-r--r-- | server/middlewares/validators/index.ts | 1 | ||||
-rw-r--r-- | server/middlewares/validators/server.ts | 49 | ||||
-rw-r--r-- | server/middlewares/validators/sort.ts | 5 | ||||
-rw-r--r-- | server/middlewares/validators/user-history.ts | 26 | ||||
-rw-r--r-- | server/middlewares/validators/user-notifications.ts | 63 | ||||
-rw-r--r-- | server/middlewares/validators/users.ts | 11 | ||||
-rw-r--r-- | server/middlewares/validators/videos/video-blacklist.ts | 15 | ||||
-rw-r--r-- | server/middlewares/validators/videos/video-watch.ts | 7 |
13 files changed, 255 insertions, 11 deletions
diff --git a/server/middlewares/csp.ts b/server/middlewares/csp.ts new file mode 100644 index 000000000..8b919af0d --- /dev/null +++ b/server/middlewares/csp.ts | |||
@@ -0,0 +1,44 @@ | |||
1 | import * as helmet from 'helmet' | ||
2 | import { CONFIG } from '../initializers/constants' | ||
3 | |||
4 | const baseDirectives = Object.assign({}, | ||
5 | { | ||
6 | defaultSrc: ["'none'"], // by default, not specifying default-src = '*' | ||
7 | connectSrc: ['*', 'data:'], | ||
8 | mediaSrc: ["'self'", 'https:', 'blob:'], | ||
9 | fontSrc: ["'self'", 'data:'], | ||
10 | imgSrc: ["'self'", 'data:'], | ||
11 | scriptSrc: ["'self' 'unsafe-inline' 'unsafe-eval'"], | ||
12 | styleSrc: ["'self' 'unsafe-inline'"], | ||
13 | objectSrc: ["'none'"], // only define to allow plugins, else let defaultSrc 'none' block it | ||
14 | formAction: ["'self'"], | ||
15 | frameAncestors: ["'none'"], | ||
16 | baseUri: ["'self'"], | ||
17 | manifestSrc: ["'self'"], | ||
18 | frameSrc: ["'self'"], // instead of deprecated child-src / self because of test-embed | ||
19 | workerSrc: ["'self'"] // instead of deprecated child-src | ||
20 | }, | ||
21 | CONFIG.SERVICES['CSP-LOGGER'] ? { reportUri: CONFIG.SERVICES['CSP-LOGGER'] } : {}, | ||
22 | CONFIG.WEBSERVER.SCHEME === 'https' ? { upgradeInsecureRequests: true } : {} | ||
23 | ) | ||
24 | |||
25 | const baseCSP = helmet.contentSecurityPolicy({ | ||
26 | directives: baseDirectives, | ||
27 | browserSniff: false, | ||
28 | reportOnly: true | ||
29 | }) | ||
30 | |||
31 | const embedCSP = helmet.contentSecurityPolicy({ | ||
32 | directives: Object.assign(baseDirectives, { | ||
33 | frameAncestors: ['*'] | ||
34 | }), | ||
35 | browserSniff: false, // assumes a modern browser, but allows CDN in front | ||
36 | reportOnly: true | ||
37 | }) | ||
38 | |||
39 | // --------------------------------------------------------------------------- | ||
40 | |||
41 | export { | ||
42 | baseCSP, | ||
43 | embedCSP | ||
44 | } | ||
diff --git a/server/middlewares/dnt.ts b/server/middlewares/dnt.ts index cabad39c6..607def855 100644 --- a/server/middlewares/dnt.ts +++ b/server/middlewares/dnt.ts | |||
@@ -10,4 +10,4 @@ const advertiseDoNotTrack = (_, res, next) => { | |||
10 | 10 | ||
11 | export { | 11 | export { |
12 | advertiseDoNotTrack | 12 | advertiseDoNotTrack |
13 | } | 13 | } |
diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts index 0cef26953..b758a8586 100644 --- a/server/middlewares/index.ts +++ b/server/middlewares/index.ts | |||
@@ -6,3 +6,5 @@ export * from './pagination' | |||
6 | export * from './servers' | 6 | export * from './servers' |
7 | export * from './sort' | 7 | export * from './sort' |
8 | export * from './user-right' | 8 | export * from './user-right' |
9 | export * from './dnt' | ||
10 | export * from './csp' | ||
diff --git a/server/middlewares/oauth.ts b/server/middlewares/oauth.ts index 8c1df2c3e..1d193d467 100644 --- a/server/middlewares/oauth.ts +++ b/server/middlewares/oauth.ts | |||
@@ -3,6 +3,8 @@ import * as OAuthServer from 'express-oauth-server' | |||
3 | import 'express-validator' | 3 | import 'express-validator' |
4 | import { OAUTH_LIFETIME } from '../initializers' | 4 | import { OAUTH_LIFETIME } from '../initializers' |
5 | import { logger } from '../helpers/logger' | 5 | import { logger } from '../helpers/logger' |
6 | import { Socket } from 'socket.io' | ||
7 | import { getAccessToken } from '../lib/oauth-model' | ||
6 | 8 | ||
7 | const oAuthServer = new OAuthServer({ | 9 | const oAuthServer = new OAuthServer({ |
8 | useErrorHandler: true, | 10 | useErrorHandler: true, |
@@ -28,6 +30,25 @@ function authenticate (req: express.Request, res: express.Response, next: expres | |||
28 | }) | 30 | }) |
29 | } | 31 | } |
30 | 32 | ||
33 | function authenticateSocket (socket: Socket, next: (err?: any) => void) { | ||
34 | const accessToken = socket.handshake.query.accessToken | ||
35 | |||
36 | logger.debug('Checking socket access token %s.', accessToken) | ||
37 | |||
38 | getAccessToken(accessToken) | ||
39 | .then(tokenDB => { | ||
40 | const now = new Date() | ||
41 | |||
42 | if (!tokenDB || tokenDB.accessTokenExpiresAt < now || tokenDB.refreshTokenExpiresAt < now) { | ||
43 | return next(new Error('Invalid access token.')) | ||
44 | } | ||
45 | |||
46 | socket.handshake.query.user = tokenDB.User | ||
47 | |||
48 | return next() | ||
49 | }) | ||
50 | } | ||
51 | |||
31 | function authenticatePromiseIfNeeded (req: express.Request, res: express.Response) { | 52 | function authenticatePromiseIfNeeded (req: express.Request, res: express.Response) { |
32 | return new Promise(resolve => { | 53 | return new Promise(resolve => { |
33 | // Already authenticated? (or tried to) | 54 | // Already authenticated? (or tried to) |
@@ -68,6 +89,7 @@ function token (req: express.Request, res: express.Response, next: express.NextF | |||
68 | 89 | ||
69 | export { | 90 | export { |
70 | authenticate, | 91 | authenticate, |
92 | authenticateSocket, | ||
71 | authenticatePromiseIfNeeded, | 93 | authenticatePromiseIfNeeded, |
72 | optionalAuthenticate, | 94 | optionalAuthenticate, |
73 | token | 95 | token |
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts index f3f257d57..90108fa82 100644 --- a/server/middlewares/validators/config.ts +++ b/server/middlewares/validators/config.ts | |||
@@ -1,29 +1,44 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body } from 'express-validator/check' | 2 | import { body } from 'express-validator/check' |
3 | import { isUserNSFWPolicyValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users' | 3 | import { isUserNSFWPolicyValid, isUserVideoQuotaValid, isUserVideoQuotaDailyValid } from '../../helpers/custom-validators/users' |
4 | import { logger } from '../../helpers/logger' | 4 | import { logger } from '../../helpers/logger' |
5 | import { areValidationErrors } from './utils' | 5 | import { areValidationErrors } from './utils' |
6 | 6 | ||
7 | const customConfigUpdateValidator = [ | 7 | const customConfigUpdateValidator = [ |
8 | body('instance.name').exists().withMessage('Should have a valid instance name'), | 8 | body('instance.name').exists().withMessage('Should have a valid instance name'), |
9 | body('instance.shortDescription').exists().withMessage('Should have a valid instance short description'), | ||
9 | body('instance.description').exists().withMessage('Should have a valid instance description'), | 10 | body('instance.description').exists().withMessage('Should have a valid instance description'), |
10 | body('instance.terms').exists().withMessage('Should have a valid instance terms'), | 11 | body('instance.terms').exists().withMessage('Should have a valid instance terms'), |
11 | body('instance.defaultClientRoute').exists().withMessage('Should have a valid instance default client route'), | 12 | body('instance.defaultClientRoute').exists().withMessage('Should have a valid instance default client route'), |
12 | body('instance.defaultNSFWPolicy').custom(isUserNSFWPolicyValid).withMessage('Should have a valid NSFW policy'), | 13 | body('instance.defaultNSFWPolicy').custom(isUserNSFWPolicyValid).withMessage('Should have a valid NSFW policy'), |
13 | body('instance.customizations.css').exists().withMessage('Should have a valid instance CSS customization'), | 14 | body('instance.customizations.css').exists().withMessage('Should have a valid instance CSS customization'), |
14 | body('instance.customizations.javascript').exists().withMessage('Should have a valid instance JavaScript customization'), | 15 | body('instance.customizations.javascript').exists().withMessage('Should have a valid instance JavaScript customization'), |
15 | body('cache.previews.size').isInt().withMessage('Should have a valid previews size'), | 16 | |
17 | body('services.twitter.username').exists().withMessage('Should have a valid twitter username'), | ||
18 | body('services.twitter.whitelisted').isBoolean().withMessage('Should have a valid twitter whitelisted boolean'), | ||
19 | |||
20 | body('cache.previews.size').isInt().withMessage('Should have a valid previews cache size'), | ||
21 | body('cache.captions.size').isInt().withMessage('Should have a valid captions cache size'), | ||
22 | |||
16 | body('signup.enabled').isBoolean().withMessage('Should have a valid signup enabled boolean'), | 23 | body('signup.enabled').isBoolean().withMessage('Should have a valid signup enabled boolean'), |
17 | body('signup.limit').isInt().withMessage('Should have a valid signup limit'), | 24 | body('signup.limit').isInt().withMessage('Should have a valid signup limit'), |
25 | body('signup.requiresEmailVerification').isBoolean().withMessage('Should have a valid requiresEmailVerification boolean'), | ||
26 | |||
18 | body('admin.email').isEmail().withMessage('Should have a valid administrator email'), | 27 | body('admin.email').isEmail().withMessage('Should have a valid administrator email'), |
28 | body('contactForm.enabled').isBoolean().withMessage('Should have a valid contact form enabled boolean'), | ||
29 | |||
19 | body('user.videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid video quota'), | 30 | body('user.videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid video quota'), |
31 | body('user.videoQuotaDaily').custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily video quota'), | ||
32 | |||
20 | body('transcoding.enabled').isBoolean().withMessage('Should have a valid transcoding enabled boolean'), | 33 | body('transcoding.enabled').isBoolean().withMessage('Should have a valid transcoding enabled boolean'), |
34 | body('transcoding.allowAdditionalExtensions').isBoolean().withMessage('Should have a valid additional extensions boolean'), | ||
21 | body('transcoding.threads').isInt().withMessage('Should have a valid transcoding threads number'), | 35 | body('transcoding.threads').isInt().withMessage('Should have a valid transcoding threads number'), |
22 | body('transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'), | 36 | body('transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'), |
23 | body('transcoding.resolutions.360p').isBoolean().withMessage('Should have a valid transcoding 360p resolution enabled boolean'), | 37 | body('transcoding.resolutions.360p').isBoolean().withMessage('Should have a valid transcoding 360p resolution enabled boolean'), |
24 | body('transcoding.resolutions.480p').isBoolean().withMessage('Should have a valid transcoding 480p resolution enabled boolean'), | 38 | body('transcoding.resolutions.480p').isBoolean().withMessage('Should have a valid transcoding 480p resolution enabled boolean'), |
25 | body('transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'), | 39 | body('transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'), |
26 | body('transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'), | 40 | body('transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'), |
41 | |||
27 | body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'), | 42 | body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'), |
28 | body('import.videos.torrent.enabled').isBoolean().withMessage('Should have a valid import video torrent enabled boolean'), | 43 | body('import.videos.torrent.enabled').isBoolean().withMessage('Should have a valid import video torrent enabled boolean'), |
29 | 44 | ||
diff --git a/server/middlewares/validators/index.ts b/server/middlewares/validators/index.ts index 46c7f0f3a..65dd00335 100644 --- a/server/middlewares/validators/index.ts +++ b/server/middlewares/validators/index.ts | |||
@@ -12,3 +12,4 @@ export * from './videos' | |||
12 | export * from './webfinger' | 12 | export * from './webfinger' |
13 | export * from './search' | 13 | export * from './search' |
14 | export * from './server' | 14 | export * from './server' |
15 | export * from './user-history' | ||
diff --git a/server/middlewares/validators/server.ts b/server/middlewares/validators/server.ts index a491dfeb3..d85afc2ff 100644 --- a/server/middlewares/validators/server.ts +++ b/server/middlewares/validators/server.ts | |||
@@ -1,9 +1,13 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { logger } from '../../helpers/logger' | 2 | import { logger } from '../../helpers/logger' |
3 | import { areValidationErrors } from './utils' | 3 | import { areValidationErrors } from './utils' |
4 | import { isHostValid } from '../../helpers/custom-validators/servers' | 4 | import { isHostValid, isValidContactBody } from '../../helpers/custom-validators/servers' |
5 | import { ServerModel } from '../../models/server/server' | 5 | import { ServerModel } from '../../models/server/server' |
6 | import { body } from 'express-validator/check' | 6 | import { body } from 'express-validator/check' |
7 | import { isUserDisplayNameValid } from '../../helpers/custom-validators/users' | ||
8 | import { Emailer } from '../../lib/emailer' | ||
9 | import { Redis } from '../../lib/redis' | ||
10 | import { CONFIG } from '../../initializers/constants' | ||
7 | 11 | ||
8 | const serverGetValidator = [ | 12 | const serverGetValidator = [ |
9 | body('host').custom(isHostValid).withMessage('Should have a valid host'), | 13 | body('host').custom(isHostValid).withMessage('Should have a valid host'), |
@@ -26,8 +30,49 @@ const serverGetValidator = [ | |||
26 | } | 30 | } |
27 | ] | 31 | ] |
28 | 32 | ||
33 | const contactAdministratorValidator = [ | ||
34 | body('fromName') | ||
35 | .custom(isUserDisplayNameValid).withMessage('Should have a valid name'), | ||
36 | body('fromEmail') | ||
37 | .isEmail().withMessage('Should have a valid email'), | ||
38 | body('body') | ||
39 | .custom(isValidContactBody).withMessage('Should have a valid body'), | ||
40 | |||
41 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
42 | logger.debug('Checking contactAdministratorValidator parameters', { parameters: req.body }) | ||
43 | |||
44 | if (areValidationErrors(req, res)) return | ||
45 | |||
46 | if (CONFIG.CONTACT_FORM.ENABLED === false) { | ||
47 | return res | ||
48 | .status(409) | ||
49 | .send({ error: 'Contact form is not enabled on this instance.' }) | ||
50 | .end() | ||
51 | } | ||
52 | |||
53 | if (Emailer.isEnabled() === false) { | ||
54 | return res | ||
55 | .status(409) | ||
56 | .send({ error: 'Emailer is not enabled on this instance.' }) | ||
57 | .end() | ||
58 | } | ||
59 | |||
60 | if (await Redis.Instance.isContactFormIpExists(req.ip)) { | ||
61 | logger.info('Refusing a contact form by %s: already sent one recently.', req.ip) | ||
62 | |||
63 | return res | ||
64 | .status(403) | ||
65 | .send({ error: 'You already sent a contact form recently.' }) | ||
66 | .end() | ||
67 | } | ||
68 | |||
69 | return next() | ||
70 | } | ||
71 | ] | ||
72 | |||
29 | // --------------------------------------------------------------------------- | 73 | // --------------------------------------------------------------------------- |
30 | 74 | ||
31 | export { | 75 | export { |
32 | serverGetValidator | 76 | serverGetValidator, |
77 | contactAdministratorValidator | ||
33 | } | 78 | } |
diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index 4c0577d8f..5ceda845f 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts | |||
@@ -18,6 +18,7 @@ const SORTABLE_FOLLOWING_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.FOLLOW | |||
18 | const SORTABLE_USER_SUBSCRIPTIONS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USER_SUBSCRIPTIONS) | 18 | const SORTABLE_USER_SUBSCRIPTIONS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USER_SUBSCRIPTIONS) |
19 | const SORTABLE_ACCOUNTS_BLOCKLIST_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.ACCOUNTS_BLOCKLIST) | 19 | const SORTABLE_ACCOUNTS_BLOCKLIST_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.ACCOUNTS_BLOCKLIST) |
20 | const SORTABLE_SERVERS_BLOCKLIST_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.SERVERS_BLOCKLIST) | 20 | const SORTABLE_SERVERS_BLOCKLIST_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.SERVERS_BLOCKLIST) |
21 | const SORTABLE_USER_NOTIFICATIONS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USER_NOTIFICATIONS) | ||
21 | 22 | ||
22 | const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) | 23 | const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) |
23 | const accountsSortValidator = checkSort(SORTABLE_ACCOUNTS_COLUMNS) | 24 | const accountsSortValidator = checkSort(SORTABLE_ACCOUNTS_COLUMNS) |
@@ -35,6 +36,7 @@ const followingSortValidator = checkSort(SORTABLE_FOLLOWING_COLUMNS) | |||
35 | const userSubscriptionsSortValidator = checkSort(SORTABLE_USER_SUBSCRIPTIONS_COLUMNS) | 36 | const userSubscriptionsSortValidator = checkSort(SORTABLE_USER_SUBSCRIPTIONS_COLUMNS) |
36 | const accountsBlocklistSortValidator = checkSort(SORTABLE_ACCOUNTS_BLOCKLIST_COLUMNS) | 37 | const accountsBlocklistSortValidator = checkSort(SORTABLE_ACCOUNTS_BLOCKLIST_COLUMNS) |
37 | const serversBlocklistSortValidator = checkSort(SORTABLE_SERVERS_BLOCKLIST_COLUMNS) | 38 | const serversBlocklistSortValidator = checkSort(SORTABLE_SERVERS_BLOCKLIST_COLUMNS) |
39 | const userNotificationsSortValidator = checkSort(SORTABLE_USER_NOTIFICATIONS_COLUMNS) | ||
38 | 40 | ||
39 | // --------------------------------------------------------------------------- | 41 | // --------------------------------------------------------------------------- |
40 | 42 | ||
@@ -54,5 +56,6 @@ export { | |||
54 | userSubscriptionsSortValidator, | 56 | userSubscriptionsSortValidator, |
55 | videoChannelsSearchSortValidator, | 57 | videoChannelsSearchSortValidator, |
56 | accountsBlocklistSortValidator, | 58 | accountsBlocklistSortValidator, |
57 | serversBlocklistSortValidator | 59 | serversBlocklistSortValidator, |
60 | userNotificationsSortValidator | ||
58 | } | 61 | } |
diff --git a/server/middlewares/validators/user-history.ts b/server/middlewares/validators/user-history.ts new file mode 100644 index 000000000..418313d09 --- /dev/null +++ b/server/middlewares/validators/user-history.ts | |||
@@ -0,0 +1,26 @@ | |||
1 | import * as express from 'express' | ||
2 | import 'express-validator' | ||
3 | import { body } from 'express-validator/check' | ||
4 | import { logger } from '../../helpers/logger' | ||
5 | import { areValidationErrors } from './utils' | ||
6 | import { isDateValid } from '../../helpers/custom-validators/misc' | ||
7 | |||
8 | const userHistoryRemoveValidator = [ | ||
9 | body('beforeDate') | ||
10 | .optional() | ||
11 | .custom(isDateValid).withMessage('Should have a valid before date'), | ||
12 | |||
13 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
14 | logger.debug('Checking userHistoryRemoveValidator parameters', { parameters: req.body }) | ||
15 | |||
16 | if (areValidationErrors(req, res)) return | ||
17 | |||
18 | return next() | ||
19 | } | ||
20 | ] | ||
21 | |||
22 | // --------------------------------------------------------------------------- | ||
23 | |||
24 | export { | ||
25 | userHistoryRemoveValidator | ||
26 | } | ||
diff --git a/server/middlewares/validators/user-notifications.ts b/server/middlewares/validators/user-notifications.ts new file mode 100644 index 000000000..46486e081 --- /dev/null +++ b/server/middlewares/validators/user-notifications.ts | |||
@@ -0,0 +1,63 @@ | |||
1 | import * as express from 'express' | ||
2 | import 'express-validator' | ||
3 | import { body, query } from 'express-validator/check' | ||
4 | import { logger } from '../../helpers/logger' | ||
5 | import { areValidationErrors } from './utils' | ||
6 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' | ||
7 | import { isNotEmptyIntArray } from '../../helpers/custom-validators/misc' | ||
8 | |||
9 | const listUserNotificationsValidator = [ | ||
10 | query('unread') | ||
11 | .optional() | ||
12 | .toBoolean() | ||
13 | .isBoolean().withMessage('Should have a valid unread boolean'), | ||
14 | |||
15 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
16 | logger.debug('Checking listUserNotificationsValidator parameters', { parameters: req.query }) | ||
17 | |||
18 | if (areValidationErrors(req, res)) return | ||
19 | |||
20 | return next() | ||
21 | } | ||
22 | ] | ||
23 | |||
24 | const updateNotificationSettingsValidator = [ | ||
25 | body('newVideoFromSubscription') | ||
26 | .custom(isUserNotificationSettingValid).withMessage('Should have a valid new video from subscription notification setting'), | ||
27 | body('newCommentOnMyVideo') | ||
28 | .custom(isUserNotificationSettingValid).withMessage('Should have a valid new comment on my video notification setting'), | ||
29 | body('videoAbuseAsModerator') | ||
30 | .custom(isUserNotificationSettingValid).withMessage('Should have a valid new video abuse as moderator notification setting'), | ||
31 | body('blacklistOnMyVideo') | ||
32 | .custom(isUserNotificationSettingValid).withMessage('Should have a valid new blacklist on my video notification setting'), | ||
33 | |||
34 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
35 | logger.debug('Checking updateNotificationSettingsValidator parameters', { parameters: req.body }) | ||
36 | |||
37 | if (areValidationErrors(req, res)) return | ||
38 | |||
39 | return next() | ||
40 | } | ||
41 | ] | ||
42 | |||
43 | const markAsReadUserNotificationsValidator = [ | ||
44 | body('ids') | ||
45 | .optional() | ||
46 | .custom(isNotEmptyIntArray).withMessage('Should have a valid notification ids to mark as read'), | ||
47 | |||
48 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
49 | logger.debug('Checking markAsReadUserNotificationsValidator parameters', { parameters: req.body }) | ||
50 | |||
51 | if (areValidationErrors(req, res)) return | ||
52 | |||
53 | return next() | ||
54 | } | ||
55 | ] | ||
56 | |||
57 | // --------------------------------------------------------------------------- | ||
58 | |||
59 | export { | ||
60 | listUserNotificationsValidator, | ||
61 | updateNotificationSettingsValidator, | ||
62 | markAsReadUserNotificationsValidator | ||
63 | } | ||
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index ccaf2eeb6..1bb0bfb1b 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -5,15 +5,16 @@ import { body, param } from 'express-validator/check' | |||
5 | import { omit } from 'lodash' | 5 | import { omit } from 'lodash' |
6 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | 6 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' |
7 | import { | 7 | import { |
8 | isUserAutoPlayVideoValid, isUserBlockedReasonValid, | 8 | isUserAutoPlayVideoValid, |
9 | isUserBlockedReasonValid, | ||
9 | isUserDescriptionValid, | 10 | isUserDescriptionValid, |
10 | isUserDisplayNameValid, | 11 | isUserDisplayNameValid, |
11 | isUserNSFWPolicyValid, | 12 | isUserNSFWPolicyValid, |
12 | isUserPasswordValid, | 13 | isUserPasswordValid, |
13 | isUserRoleValid, | 14 | isUserRoleValid, |
14 | isUserUsernameValid, | 15 | isUserUsernameValid, |
15 | isUserVideoQuotaValid, | 16 | isUserVideoQuotaDailyValid, |
16 | isUserVideoQuotaDailyValid | 17 | isUserVideoQuotaValid, isUserVideosHistoryEnabledValid |
17 | } from '../../helpers/custom-validators/users' | 18 | } from '../../helpers/custom-validators/users' |
18 | import { isVideoExist } from '../../helpers/custom-validators/videos' | 19 | import { isVideoExist } from '../../helpers/custom-validators/videos' |
19 | import { logger } from '../../helpers/logger' | 20 | import { logger } from '../../helpers/logger' |
@@ -22,7 +23,6 @@ import { Redis } from '../../lib/redis' | |||
22 | import { UserModel } from '../../models/account/user' | 23 | import { UserModel } from '../../models/account/user' |
23 | import { areValidationErrors } from './utils' | 24 | import { areValidationErrors } from './utils' |
24 | import { ActorModel } from '../../models/activitypub/actor' | 25 | import { ActorModel } from '../../models/activitypub/actor' |
25 | import { comparePassword } from '../../helpers/peertube-crypto' | ||
26 | 26 | ||
27 | const usersAddValidator = [ | 27 | const usersAddValidator = [ |
28 | body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), | 28 | body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), |
@@ -144,6 +144,9 @@ const usersUpdateMeValidator = [ | |||
144 | body('email').optional().isEmail().withMessage('Should have a valid email attribute'), | 144 | body('email').optional().isEmail().withMessage('Should have a valid email attribute'), |
145 | body('nsfwPolicy').optional().custom(isUserNSFWPolicyValid).withMessage('Should have a valid display Not Safe For Work policy'), | 145 | body('nsfwPolicy').optional().custom(isUserNSFWPolicyValid).withMessage('Should have a valid display Not Safe For Work policy'), |
146 | body('autoPlayVideo').optional().custom(isUserAutoPlayVideoValid).withMessage('Should have a valid automatically plays video attribute'), | 146 | body('autoPlayVideo').optional().custom(isUserAutoPlayVideoValid).withMessage('Should have a valid automatically plays video attribute'), |
147 | body('videosHistoryEnabled') | ||
148 | .optional() | ||
149 | .custom(isUserVideosHistoryEnabledValid).withMessage('Should have a valid videos history enabled attribute'), | ||
147 | 150 | ||
148 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 151 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
149 | logger.debug('Checking usersUpdateMe parameters', { parameters: omit(req.body, 'password') }) | 152 | logger.debug('Checking usersUpdateMe parameters', { parameters: omit(req.body, 'password') }) |
diff --git a/server/middlewares/validators/videos/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts index 13da7acff..2688f63ae 100644 --- a/server/middlewares/validators/videos/video-blacklist.ts +++ b/server/middlewares/validators/videos/video-blacklist.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param } from 'express-validator/check' | 2 | import { body, param } from 'express-validator/check' |
3 | import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' | 3 | import { isBooleanValid, isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' |
4 | import { isVideoExist } from '../../../helpers/custom-validators/videos' | 4 | import { isVideoExist } from '../../../helpers/custom-validators/videos' |
5 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
6 | import { areValidationErrors } from '../utils' | 6 | import { areValidationErrors } from '../utils' |
7 | import { isVideoBlacklistExist, isVideoBlacklistReasonValid } from '../../../helpers/custom-validators/video-blacklist' | 7 | import { isVideoBlacklistExist, isVideoBlacklistReasonValid } from '../../../helpers/custom-validators/video-blacklist' |
8 | import { VideoModel } from '../../../models/video/video' | ||
8 | 9 | ||
9 | const videosBlacklistRemoveValidator = [ | 10 | const videosBlacklistRemoveValidator = [ |
10 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 11 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
@@ -22,6 +23,10 @@ const videosBlacklistRemoveValidator = [ | |||
22 | 23 | ||
23 | const videosBlacklistAddValidator = [ | 24 | const videosBlacklistAddValidator = [ |
24 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 25 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
26 | body('unfederate') | ||
27 | .optional() | ||
28 | .toBoolean() | ||
29 | .custom(isBooleanValid).withMessage('Should have a valid unfederate boolean'), | ||
25 | body('reason') | 30 | body('reason') |
26 | .optional() | 31 | .optional() |
27 | .custom(isVideoBlacklistReasonValid).withMessage('Should have a valid reason'), | 32 | .custom(isVideoBlacklistReasonValid).withMessage('Should have a valid reason'), |
@@ -32,6 +37,14 @@ const videosBlacklistAddValidator = [ | |||
32 | if (areValidationErrors(req, res)) return | 37 | if (areValidationErrors(req, res)) return |
33 | if (!await isVideoExist(req.params.videoId, res)) return | 38 | if (!await isVideoExist(req.params.videoId, res)) return |
34 | 39 | ||
40 | const video: VideoModel = res.locals.video | ||
41 | if (req.body.unfederate === true && video.remote === true) { | ||
42 | return res | ||
43 | .status(409) | ||
44 | .send({ error: 'You cannot unfederate a remote video.' }) | ||
45 | .end() | ||
46 | } | ||
47 | |||
35 | return next() | 48 | return next() |
36 | } | 49 | } |
37 | ] | 50 | ] |
diff --git a/server/middlewares/validators/videos/video-watch.ts b/server/middlewares/validators/videos/video-watch.ts index bca64662f..c38ad8a10 100644 --- a/server/middlewares/validators/videos/video-watch.ts +++ b/server/middlewares/validators/videos/video-watch.ts | |||
@@ -4,6 +4,7 @@ import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' | |||
4 | import { isVideoExist } from '../../../helpers/custom-validators/videos' | 4 | import { isVideoExist } from '../../../helpers/custom-validators/videos' |
5 | import { areValidationErrors } from '../utils' | 5 | import { areValidationErrors } from '../utils' |
6 | import { logger } from '../../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
7 | import { UserModel } from '../../../models/account/user' | ||
7 | 8 | ||
8 | const videoWatchingValidator = [ | 9 | const videoWatchingValidator = [ |
9 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 10 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
@@ -17,6 +18,12 @@ const videoWatchingValidator = [ | |||
17 | if (areValidationErrors(req, res)) return | 18 | if (areValidationErrors(req, res)) return |
18 | if (!await isVideoExist(req.params.videoId, res, 'id')) return | 19 | if (!await isVideoExist(req.params.videoId, res, 'id')) return |
19 | 20 | ||
21 | const user = res.locals.oauth.token.User as UserModel | ||
22 | if (user.videosHistoryEnabled === false) { | ||
23 | logger.warn('Cannot set videos to watch by user %d: videos history is disabled.', user.id) | ||
24 | return res.status(409).end() | ||
25 | } | ||
26 | |||
20 | return next() | 27 | return next() |
21 | } | 28 | } |
22 | ] | 29 | ] |