diff options
Diffstat (limited to 'server/middlewares')
15 files changed, 369 insertions, 115 deletions
diff --git a/server/middlewares/cache.ts b/server/middlewares/cache.ts index 1b44957d3..1e00fc731 100644 --- a/server/middlewares/cache.ts +++ b/server/middlewares/cache.ts | |||
@@ -8,7 +8,7 @@ const lock = new AsyncLock({ timeout: 5000 }) | |||
8 | 8 | ||
9 | function cacheRoute (lifetimeArg: string | number) { | 9 | function cacheRoute (lifetimeArg: string | number) { |
10 | return async function (req: express.Request, res: express.Response, next: express.NextFunction) { | 10 | return async function (req: express.Request, res: express.Response, next: express.NextFunction) { |
11 | const redisKey = Redis.Instance.buildCachedRouteKey(req) | 11 | const redisKey = Redis.Instance.generateCachedRouteKey(req) |
12 | 12 | ||
13 | try { | 13 | try { |
14 | await lock.acquire(redisKey, async (done) => { | 14 | await lock.acquire(redisKey, async (done) => { |
diff --git a/server/middlewares/validators/blocklist.ts b/server/middlewares/validators/blocklist.ts new file mode 100644 index 000000000..109276c63 --- /dev/null +++ b/server/middlewares/validators/blocklist.ts | |||
@@ -0,0 +1,172 @@ | |||
1 | import { body, param } from 'express-validator/check' | ||
2 | import * as express from 'express' | ||
3 | import { logger } from '../../helpers/logger' | ||
4 | import { areValidationErrors } from './utils' | ||
5 | import { isAccountNameWithHostExist } from '../../helpers/custom-validators/accounts' | ||
6 | import { UserModel } from '../../models/account/user' | ||
7 | import { AccountBlocklistModel } from '../../models/account/account-blocklist' | ||
8 | import { isHostValid } from '../../helpers/custom-validators/servers' | ||
9 | import { ServerBlocklistModel } from '../../models/server/server-blocklist' | ||
10 | import { ServerModel } from '../../models/server/server' | ||
11 | import { CONFIG } from '../../initializers' | ||
12 | import { getServerActor } from '../../helpers/utils' | ||
13 | |||
14 | const blockAccountValidator = [ | ||
15 | body('accountName').exists().withMessage('Should have an account name with host'), | ||
16 | |||
17 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
18 | logger.debug('Checking blockAccountByAccountValidator parameters', { parameters: req.body }) | ||
19 | |||
20 | if (areValidationErrors(req, res)) return | ||
21 | if (!await isAccountNameWithHostExist(req.body.accountName, res)) return | ||
22 | |||
23 | const user = res.locals.oauth.token.User as UserModel | ||
24 | const accountToBlock = res.locals.account | ||
25 | |||
26 | if (user.Account.id === accountToBlock.id) { | ||
27 | res.status(409) | ||
28 | .send({ error: 'You cannot block yourself.' }) | ||
29 | .end() | ||
30 | |||
31 | return | ||
32 | } | ||
33 | |||
34 | return next() | ||
35 | } | ||
36 | ] | ||
37 | |||
38 | const unblockAccountByAccountValidator = [ | ||
39 | param('accountName').exists().withMessage('Should have an account name with host'), | ||
40 | |||
41 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
42 | logger.debug('Checking unblockAccountByAccountValidator parameters', { parameters: req.params }) | ||
43 | |||
44 | if (areValidationErrors(req, res)) return | ||
45 | if (!await isAccountNameWithHostExist(req.params.accountName, res)) return | ||
46 | |||
47 | const user = res.locals.oauth.token.User as UserModel | ||
48 | const targetAccount = res.locals.account | ||
49 | if (!await isUnblockAccountExists(user.Account.id, targetAccount.id, res)) return | ||
50 | |||
51 | return next() | ||
52 | } | ||
53 | ] | ||
54 | |||
55 | const unblockAccountByServerValidator = [ | ||
56 | param('accountName').exists().withMessage('Should have an account name with host'), | ||
57 | |||
58 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
59 | logger.debug('Checking unblockAccountByServerValidator parameters', { parameters: req.params }) | ||
60 | |||
61 | if (areValidationErrors(req, res)) return | ||
62 | if (!await isAccountNameWithHostExist(req.params.accountName, res)) return | ||
63 | |||
64 | const serverActor = await getServerActor() | ||
65 | const targetAccount = res.locals.account | ||
66 | if (!await isUnblockAccountExists(serverActor.Account.id, targetAccount.id, res)) return | ||
67 | |||
68 | return next() | ||
69 | } | ||
70 | ] | ||
71 | |||
72 | const blockServerValidator = [ | ||
73 | body('host').custom(isHostValid).withMessage('Should have a valid host'), | ||
74 | |||
75 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
76 | logger.debug('Checking serverGetValidator parameters', { parameters: req.body }) | ||
77 | |||
78 | if (areValidationErrors(req, res)) return | ||
79 | |||
80 | const host: string = req.body.host | ||
81 | |||
82 | if (host === CONFIG.WEBSERVER.HOST) { | ||
83 | return res.status(409) | ||
84 | .send({ error: 'You cannot block your own server.' }) | ||
85 | .end() | ||
86 | } | ||
87 | |||
88 | const server = await ServerModel.loadByHost(host) | ||
89 | if (!server) { | ||
90 | return res.status(404) | ||
91 | .send({ error: 'Server host not found.' }) | ||
92 | .end() | ||
93 | } | ||
94 | |||
95 | res.locals.server = server | ||
96 | |||
97 | return next() | ||
98 | } | ||
99 | ] | ||
100 | |||
101 | const unblockServerByAccountValidator = [ | ||
102 | param('host').custom(isHostValid).withMessage('Should have an account name with host'), | ||
103 | |||
104 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
105 | logger.debug('Checking unblockServerByAccountValidator parameters', { parameters: req.params }) | ||
106 | |||
107 | if (areValidationErrors(req, res)) return | ||
108 | |||
109 | const user = res.locals.oauth.token.User as UserModel | ||
110 | if (!await isUnblockServerExists(user.Account.id, req.params.host, res)) return | ||
111 | |||
112 | return next() | ||
113 | } | ||
114 | ] | ||
115 | |||
116 | const unblockServerByServerValidator = [ | ||
117 | param('host').custom(isHostValid).withMessage('Should have an account name with host'), | ||
118 | |||
119 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
120 | logger.debug('Checking unblockServerByServerValidator parameters', { parameters: req.params }) | ||
121 | |||
122 | if (areValidationErrors(req, res)) return | ||
123 | |||
124 | const serverActor = await getServerActor() | ||
125 | if (!await isUnblockServerExists(serverActor.Account.id, req.params.host, res)) return | ||
126 | |||
127 | return next() | ||
128 | } | ||
129 | ] | ||
130 | |||
131 | // --------------------------------------------------------------------------- | ||
132 | |||
133 | export { | ||
134 | blockServerValidator, | ||
135 | blockAccountValidator, | ||
136 | unblockAccountByAccountValidator, | ||
137 | unblockServerByAccountValidator, | ||
138 | unblockAccountByServerValidator, | ||
139 | unblockServerByServerValidator | ||
140 | } | ||
141 | |||
142 | // --------------------------------------------------------------------------- | ||
143 | |||
144 | async function isUnblockAccountExists (accountId: number, targetAccountId: number, res: express.Response) { | ||
145 | const accountBlock = await AccountBlocklistModel.loadByAccountAndTarget(accountId, targetAccountId) | ||
146 | if (!accountBlock) { | ||
147 | res.status(404) | ||
148 | .send({ error: 'Account block entry not found.' }) | ||
149 | .end() | ||
150 | |||
151 | return false | ||
152 | } | ||
153 | |||
154 | res.locals.accountBlock = accountBlock | ||
155 | |||
156 | return true | ||
157 | } | ||
158 | |||
159 | async function isUnblockServerExists (accountId: number, host: string, res: express.Response) { | ||
160 | const serverBlock = await ServerBlocklistModel.loadByAccountAndHost(accountId, host) | ||
161 | if (!serverBlock) { | ||
162 | res.status(404) | ||
163 | .send({ error: 'Server block entry not found.' }) | ||
164 | .end() | ||
165 | |||
166 | return false | ||
167 | } | ||
168 | |||
169 | res.locals.serverBlock = serverBlock | ||
170 | |||
171 | return true | ||
172 | } | ||
diff --git a/server/middlewares/validators/index.ts b/server/middlewares/validators/index.ts index 940547a3e..46c7f0f3a 100644 --- a/server/middlewares/validators/index.ts +++ b/server/middlewares/validators/index.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | export * from './account' | 1 | export * from './account' |
2 | export * from './blocklist' | ||
2 | export * from './oembed' | 3 | export * from './oembed' |
3 | export * from './activitypub' | 4 | export * from './activitypub' |
4 | export * from './pagination' | 5 | export * from './pagination' |
@@ -8,9 +9,6 @@ export * from './sort' | |||
8 | export * from './users' | 9 | export * from './users' |
9 | export * from './user-subscriptions' | 10 | export * from './user-subscriptions' |
10 | export * from './videos' | 11 | export * from './videos' |
11 | export * from './video-abuses' | ||
12 | export * from './video-blacklist' | ||
13 | export * from './video-channels' | ||
14 | export * from './webfinger' | 12 | export * from './webfinger' |
15 | export * from './search' | 13 | export * from './search' |
16 | export * from './video-imports' | 14 | export * from './server' |
diff --git a/server/middlewares/validators/search.ts b/server/middlewares/validators/search.ts index 8baf643a5..6a95d6095 100644 --- a/server/middlewares/validators/search.ts +++ b/server/middlewares/validators/search.ts | |||
@@ -2,8 +2,7 @@ import * as express from 'express' | |||
2 | import { areValidationErrors } from './utils' | 2 | import { areValidationErrors } from './utils' |
3 | import { logger } from '../../helpers/logger' | 3 | import { logger } from '../../helpers/logger' |
4 | import { query } from 'express-validator/check' | 4 | import { query } from 'express-validator/check' |
5 | import { isNumberArray, isStringArray, isNSFWQueryValid } from '../../helpers/custom-validators/search' | 5 | import { isDateValid } from '../../helpers/custom-validators/misc' |
6 | import { isBooleanValid, isDateValid, toArray } from '../../helpers/custom-validators/misc' | ||
7 | 6 | ||
8 | const videosSearchValidator = [ | 7 | const videosSearchValidator = [ |
9 | query('search').optional().not().isEmpty().withMessage('Should have a valid search'), | 8 | query('search').optional().not().isEmpty().withMessage('Should have a valid search'), |
@@ -35,44 +34,9 @@ const videoChannelsSearchValidator = [ | |||
35 | } | 34 | } |
36 | ] | 35 | ] |
37 | 36 | ||
38 | const commonVideosFiltersValidator = [ | ||
39 | query('categoryOneOf') | ||
40 | .optional() | ||
41 | .customSanitizer(toArray) | ||
42 | .custom(isNumberArray).withMessage('Should have a valid one of category array'), | ||
43 | query('licenceOneOf') | ||
44 | .optional() | ||
45 | .customSanitizer(toArray) | ||
46 | .custom(isNumberArray).withMessage('Should have a valid one of licence array'), | ||
47 | query('languageOneOf') | ||
48 | .optional() | ||
49 | .customSanitizer(toArray) | ||
50 | .custom(isStringArray).withMessage('Should have a valid one of language array'), | ||
51 | query('tagsOneOf') | ||
52 | .optional() | ||
53 | .customSanitizer(toArray) | ||
54 | .custom(isStringArray).withMessage('Should have a valid one of tags array'), | ||
55 | query('tagsAllOf') | ||
56 | .optional() | ||
57 | .customSanitizer(toArray) | ||
58 | .custom(isStringArray).withMessage('Should have a valid all of tags array'), | ||
59 | query('nsfw') | ||
60 | .optional() | ||
61 | .custom(isNSFWQueryValid).withMessage('Should have a valid NSFW attribute'), | ||
62 | |||
63 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
64 | logger.debug('Checking commons video filters query', { parameters: req.query }) | ||
65 | |||
66 | if (areValidationErrors(req, res)) return | ||
67 | |||
68 | return next() | ||
69 | } | ||
70 | ] | ||
71 | |||
72 | // --------------------------------------------------------------------------- | 37 | // --------------------------------------------------------------------------- |
73 | 38 | ||
74 | export { | 39 | export { |
75 | commonVideosFiltersValidator, | ||
76 | videoChannelsSearchValidator, | 40 | videoChannelsSearchValidator, |
77 | videosSearchValidator | 41 | videosSearchValidator |
78 | } | 42 | } |
diff --git a/server/middlewares/validators/server.ts b/server/middlewares/validators/server.ts new file mode 100644 index 000000000..a491dfeb3 --- /dev/null +++ b/server/middlewares/validators/server.ts | |||
@@ -0,0 +1,33 @@ | |||
1 | import * as express from 'express' | ||
2 | import { logger } from '../../helpers/logger' | ||
3 | import { areValidationErrors } from './utils' | ||
4 | import { isHostValid } from '../../helpers/custom-validators/servers' | ||
5 | import { ServerModel } from '../../models/server/server' | ||
6 | import { body } from 'express-validator/check' | ||
7 | |||
8 | const serverGetValidator = [ | ||
9 | body('host').custom(isHostValid).withMessage('Should have a valid host'), | ||
10 | |||
11 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
12 | logger.debug('Checking serverGetValidator parameters', { parameters: req.body }) | ||
13 | |||
14 | if (areValidationErrors(req, res)) return | ||
15 | |||
16 | const server = await ServerModel.loadByHost(req.body.host) | ||
17 | if (!server) { | ||
18 | return res.status(404) | ||
19 | .send({ error: 'Server host not found.' }) | ||
20 | .end() | ||
21 | } | ||
22 | |||
23 | res.locals.server = server | ||
24 | |||
25 | return next() | ||
26 | } | ||
27 | ] | ||
28 | |||
29 | // --------------------------------------------------------------------------- | ||
30 | |||
31 | export { | ||
32 | serverGetValidator | ||
33 | } | ||
diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index 08dcc2680..4c0577d8f 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts | |||
@@ -16,6 +16,8 @@ const SORTABLE_VIDEO_CHANNELS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.V | |||
16 | const SORTABLE_FOLLOWERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.FOLLOWERS) | 16 | const SORTABLE_FOLLOWERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.FOLLOWERS) |
17 | const SORTABLE_FOLLOWING_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.FOLLOWING) | 17 | const SORTABLE_FOLLOWING_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.FOLLOWING) |
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) | ||
20 | const SORTABLE_SERVERS_BLOCKLIST_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.SERVERS_BLOCKLIST) | ||
19 | 21 | ||
20 | const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) | 22 | const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) |
21 | const accountsSortValidator = checkSort(SORTABLE_ACCOUNTS_COLUMNS) | 23 | const accountsSortValidator = checkSort(SORTABLE_ACCOUNTS_COLUMNS) |
@@ -31,6 +33,8 @@ const videoChannelsSortValidator = checkSort(SORTABLE_VIDEO_CHANNELS_COLUMNS) | |||
31 | const followersSortValidator = checkSort(SORTABLE_FOLLOWERS_COLUMNS) | 33 | const followersSortValidator = checkSort(SORTABLE_FOLLOWERS_COLUMNS) |
32 | const followingSortValidator = checkSort(SORTABLE_FOLLOWING_COLUMNS) | 34 | const followingSortValidator = checkSort(SORTABLE_FOLLOWING_COLUMNS) |
33 | const userSubscriptionsSortValidator = checkSort(SORTABLE_USER_SUBSCRIPTIONS_COLUMNS) | 35 | const userSubscriptionsSortValidator = checkSort(SORTABLE_USER_SUBSCRIPTIONS_COLUMNS) |
36 | const accountsBlocklistSortValidator = checkSort(SORTABLE_ACCOUNTS_BLOCKLIST_COLUMNS) | ||
37 | const serversBlocklistSortValidator = checkSort(SORTABLE_SERVERS_BLOCKLIST_COLUMNS) | ||
34 | 38 | ||
35 | // --------------------------------------------------------------------------- | 39 | // --------------------------------------------------------------------------- |
36 | 40 | ||
@@ -48,5 +52,7 @@ export { | |||
48 | jobsSortValidator, | 52 | jobsSortValidator, |
49 | videoCommentThreadsSortValidator, | 53 | videoCommentThreadsSortValidator, |
50 | userSubscriptionsSortValidator, | 54 | userSubscriptionsSortValidator, |
51 | videoChannelsSearchSortValidator | 55 | videoChannelsSearchSortValidator, |
56 | accountsBlocklistSortValidator, | ||
57 | serversBlocklistSortValidator | ||
52 | } | 58 | } |
diff --git a/server/middlewares/validators/videos/index.ts b/server/middlewares/validators/videos/index.ts new file mode 100644 index 000000000..294783d85 --- /dev/null +++ b/server/middlewares/validators/videos/index.ts | |||
@@ -0,0 +1,8 @@ | |||
1 | export * from './video-abuses' | ||
2 | export * from './video-blacklist' | ||
3 | export * from './video-captions' | ||
4 | export * from './video-channels' | ||
5 | export * from './video-comments' | ||
6 | export * from './video-imports' | ||
7 | export * from './video-watch' | ||
8 | export * from './videos' | ||
diff --git a/server/middlewares/validators/video-abuses.ts b/server/middlewares/validators/videos/video-abuses.ts index f15d55a75..be26ca16a 100644 --- a/server/middlewares/validators/video-abuses.ts +++ b/server/middlewares/validators/videos/video-abuses.ts | |||
@@ -1,16 +1,16 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import 'express-validator' | 2 | import 'express-validator' |
3 | import { body, param } from 'express-validator/check' | 3 | import { body, param } from 'express-validator/check' |
4 | import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' | 4 | import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' |
5 | import { isVideoExist } from '../../helpers/custom-validators/videos' | 5 | import { isVideoExist } from '../../../helpers/custom-validators/videos' |
6 | import { logger } from '../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
7 | import { areValidationErrors } from './utils' | 7 | import { areValidationErrors } from '../utils' |
8 | import { | 8 | import { |
9 | isVideoAbuseExist, | 9 | isVideoAbuseExist, |
10 | isVideoAbuseModerationCommentValid, | 10 | isVideoAbuseModerationCommentValid, |
11 | isVideoAbuseReasonValid, | 11 | isVideoAbuseReasonValid, |
12 | isVideoAbuseStateValid | 12 | isVideoAbuseStateValid |
13 | } from '../../helpers/custom-validators/video-abuses' | 13 | } from '../../../helpers/custom-validators/video-abuses' |
14 | 14 | ||
15 | const videoAbuseReportValidator = [ | 15 | const videoAbuseReportValidator = [ |
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'), |
diff --git a/server/middlewares/validators/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts index 95a2b9f17..13da7acff 100644 --- a/server/middlewares/validators/video-blacklist.ts +++ b/server/middlewares/validators/videos/video-blacklist.ts | |||
@@ -1,10 +1,10 @@ | |||
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 { 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 | 8 | ||
9 | const videosBlacklistRemoveValidator = [ | 9 | const videosBlacklistRemoveValidator = [ |
10 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 10 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
diff --git a/server/middlewares/validators/video-captions.ts b/server/middlewares/validators/videos/video-captions.ts index 51ffd7f3c..63d84fbec 100644 --- a/server/middlewares/validators/video-captions.ts +++ b/server/middlewares/validators/videos/video-captions.ts | |||
@@ -1,13 +1,13 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { areValidationErrors } from './utils' | 2 | import { areValidationErrors } from '../utils' |
3 | import { checkUserCanManageVideo, isVideoExist } from '../../helpers/custom-validators/videos' | 3 | import { checkUserCanManageVideo, isVideoExist } from '../../../helpers/custom-validators/videos' |
4 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | 4 | import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' |
5 | import { body, param } from 'express-validator/check' | 5 | import { body, param } from 'express-validator/check' |
6 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 6 | import { CONSTRAINTS_FIELDS } from '../../../initializers' |
7 | import { UserRight } from '../../../shared' | 7 | import { UserRight } from '../../../../shared' |
8 | import { logger } from '../../helpers/logger' | 8 | import { logger } from '../../../helpers/logger' |
9 | import { isVideoCaptionExist, isVideoCaptionFile, isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' | 9 | import { isVideoCaptionExist, isVideoCaptionFile, isVideoCaptionLanguageValid } from '../../../helpers/custom-validators/video-captions' |
10 | import { cleanUpReqFiles } from '../../helpers/express-utils' | 10 | import { cleanUpReqFiles } from '../../../helpers/express-utils' |
11 | 11 | ||
12 | const addVideoCaptionValidator = [ | 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'), |
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts index 56a347b39..f039794e0 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/videos/video-channels.ts | |||
@@ -1,20 +1,20 @@ | |||
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 { UserRight } from '../../../shared' | 3 | import { UserRight } from '../../../../shared' |
4 | import { isAccountNameWithHostExist } from '../../helpers/custom-validators/accounts' | 4 | import { isAccountNameWithHostExist } from '../../../helpers/custom-validators/accounts' |
5 | import { | 5 | import { |
6 | isLocalVideoChannelNameExist, | 6 | isLocalVideoChannelNameExist, |
7 | isVideoChannelDescriptionValid, | 7 | isVideoChannelDescriptionValid, |
8 | isVideoChannelNameValid, | 8 | isVideoChannelNameValid, |
9 | isVideoChannelNameWithHostExist, | 9 | isVideoChannelNameWithHostExist, |
10 | isVideoChannelSupportValid | 10 | isVideoChannelSupportValid |
11 | } from '../../helpers/custom-validators/video-channels' | 11 | } from '../../../helpers/custom-validators/video-channels' |
12 | import { logger } from '../../helpers/logger' | 12 | import { logger } from '../../../helpers/logger' |
13 | import { UserModel } from '../../models/account/user' | 13 | import { UserModel } from '../../../models/account/user' |
14 | import { VideoChannelModel } from '../../models/video/video-channel' | 14 | import { VideoChannelModel } from '../../../models/video/video-channel' |
15 | import { areValidationErrors } from './utils' | 15 | import { areValidationErrors } from '../utils' |
16 | import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor' | 16 | import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor' |
17 | import { ActorModel } from '../../models/activitypub/actor' | 17 | import { ActorModel } from '../../../models/activitypub/actor' |
18 | 18 | ||
19 | const listVideoAccountChannelsValidator = [ | 19 | const listVideoAccountChannelsValidator = [ |
20 | param('accountName').exists().withMessage('Should have a valid account name'), | 20 | param('accountName').exists().withMessage('Should have a valid account name'), |
diff --git a/server/middlewares/validators/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts index 693852499..348d33082 100644 --- a/server/middlewares/validators/video-comments.ts +++ b/server/middlewares/validators/videos/video-comments.ts | |||
@@ -1,14 +1,14 @@ | |||
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 { UserRight } from '../../../shared' | 3 | import { UserRight } from '../../../../shared' |
4 | import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' | 4 | import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' |
5 | import { isValidVideoCommentText } from '../../helpers/custom-validators/video-comments' | 5 | import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments' |
6 | import { isVideoExist } from '../../helpers/custom-validators/videos' | 6 | import { isVideoExist } from '../../../helpers/custom-validators/videos' |
7 | import { logger } from '../../helpers/logger' | 7 | import { logger } from '../../../helpers/logger' |
8 | import { UserModel } from '../../models/account/user' | 8 | import { UserModel } from '../../../models/account/user' |
9 | import { VideoModel } from '../../models/video/video' | 9 | import { VideoModel } from '../../../models/video/video' |
10 | import { VideoCommentModel } from '../../models/video/video-comment' | 10 | import { VideoCommentModel } from '../../../models/video/video-comment' |
11 | import { areValidationErrors } from './utils' | 11 | import { areValidationErrors } from '../utils' |
12 | 12 | ||
13 | const listVideoCommentThreadsValidator = [ | 13 | const listVideoCommentThreadsValidator = [ |
14 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 14 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
diff --git a/server/middlewares/validators/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts index b2063b8da..48d20f904 100644 --- a/server/middlewares/validators/video-imports.ts +++ b/server/middlewares/validators/videos/video-imports.ts | |||
@@ -1,14 +1,14 @@ | |||
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 { isIdValid } from '../../helpers/custom-validators/misc' | 3 | import { isIdValid } 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 { getCommonVideoAttributes } from './videos' | 6 | import { getCommonVideoAttributes } from './videos' |
7 | import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../helpers/custom-validators/video-imports' | 7 | import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../../helpers/custom-validators/video-imports' |
8 | import { cleanUpReqFiles } from '../../helpers/express-utils' | 8 | import { cleanUpReqFiles } from '../../../helpers/express-utils' |
9 | import { isVideoChannelOfAccountExist, isVideoMagnetUriValid, isVideoNameValid } from '../../helpers/custom-validators/videos' | 9 | import { isVideoChannelOfAccountExist, isVideoMagnetUriValid, isVideoNameValid } from '../../../helpers/custom-validators/videos' |
10 | import { CONFIG } from '../../initializers/constants' | 10 | import { CONFIG } from '../../../initializers/constants' |
11 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 11 | import { CONSTRAINTS_FIELDS } from '../../../initializers' |
12 | 12 | ||
13 | const videoImportAddValidator = getCommonVideoAttributes().concat([ | 13 | const videoImportAddValidator = getCommonVideoAttributes().concat([ |
14 | body('channelId') | 14 | body('channelId') |
diff --git a/server/middlewares/validators/videos/video-watch.ts b/server/middlewares/validators/videos/video-watch.ts new file mode 100644 index 000000000..bca64662f --- /dev/null +++ b/server/middlewares/validators/videos/video-watch.ts | |||
@@ -0,0 +1,28 @@ | |||
1 | import { body, param } from 'express-validator/check' | ||
2 | import * as express from 'express' | ||
3 | import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' | ||
4 | import { isVideoExist } from '../../../helpers/custom-validators/videos' | ||
5 | import { areValidationErrors } from '../utils' | ||
6 | import { logger } from '../../../helpers/logger' | ||
7 | |||
8 | const videoWatchingValidator = [ | ||
9 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | ||
10 | body('currentTime') | ||
11 | .toInt() | ||
12 | .isInt().withMessage('Should have correct current time'), | ||
13 | |||
14 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
15 | logger.debug('Checking videoWatching parameters', { parameters: req.body }) | ||
16 | |||
17 | if (areValidationErrors(req, res)) return | ||
18 | if (!await isVideoExist(req.params.videoId, res, 'id')) return | ||
19 | |||
20 | return next() | ||
21 | } | ||
22 | ] | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
25 | |||
26 | export { | ||
27 | videoWatchingValidator | ||
28 | } | ||
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos/videos.ts index 67eabe468..9dc52a134 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos/videos.ts | |||
@@ -1,16 +1,17 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import 'express-validator' | 2 | import 'express-validator' |
3 | import { body, param, ValidationChain } from 'express-validator/check' | 3 | import { body, param, query, ValidationChain } from 'express-validator/check' |
4 | import { UserRight, VideoChangeOwnershipStatus, VideoPrivacy } from '../../../shared' | 4 | import { UserRight, VideoChangeOwnershipStatus, VideoPrivacy } from '../../../../shared' |
5 | import { | 5 | import { |
6 | isBooleanValid, | 6 | isBooleanValid, |
7 | isDateValid, | 7 | isDateValid, |
8 | isIdOrUUIDValid, | 8 | isIdOrUUIDValid, |
9 | isIdValid, | 9 | isIdValid, |
10 | isUUIDValid, | 10 | isUUIDValid, |
11 | toArray, | ||
11 | toIntOrNull, | 12 | toIntOrNull, |
12 | toValueOrNull | 13 | toValueOrNull |
13 | } from '../../helpers/custom-validators/misc' | 14 | } from '../../../helpers/custom-validators/misc' |
14 | import { | 15 | import { |
15 | checkUserCanManageVideo, | 16 | checkUserCanManageVideo, |
16 | isScheduleVideoUpdatePrivacyValid, | 17 | isScheduleVideoUpdatePrivacyValid, |
@@ -19,6 +20,7 @@ import { | |||
19 | isVideoDescriptionValid, | 20 | isVideoDescriptionValid, |
20 | isVideoExist, | 21 | isVideoExist, |
21 | isVideoFile, | 22 | isVideoFile, |
23 | isVideoFilterValid, | ||
22 | isVideoImage, | 24 | isVideoImage, |
23 | isVideoLanguageValid, | 25 | isVideoLanguageValid, |
24 | isVideoLicenceValid, | 26 | isVideoLicenceValid, |
@@ -27,21 +29,22 @@ import { | |||
27 | isVideoRatingTypeValid, | 29 | isVideoRatingTypeValid, |
28 | isVideoSupportValid, | 30 | isVideoSupportValid, |
29 | isVideoTagsValid | 31 | isVideoTagsValid |
30 | } from '../../helpers/custom-validators/videos' | 32 | } from '../../../helpers/custom-validators/videos' |
31 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' | 33 | import { getDurationFromVideoFile } from '../../../helpers/ffmpeg-utils' |
32 | import { logger } from '../../helpers/logger' | 34 | import { logger } from '../../../helpers/logger' |
33 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 35 | import { CONSTRAINTS_FIELDS } from '../../../initializers' |
34 | import { VideoShareModel } from '../../models/video/video-share' | 36 | import { VideoShareModel } from '../../../models/video/video-share' |
35 | import { authenticate } from '../oauth' | 37 | import { authenticate } from '../../oauth' |
36 | import { areValidationErrors } from './utils' | 38 | import { areValidationErrors } from '../utils' |
37 | import { cleanUpReqFiles } from '../../helpers/express-utils' | 39 | import { cleanUpReqFiles } from '../../../helpers/express-utils' |
38 | import { VideoModel } from '../../models/video/video' | 40 | import { VideoModel } from '../../../models/video/video' |
39 | import { UserModel } from '../../models/account/user' | 41 | import { UserModel } from '../../../models/account/user' |
40 | import { checkUserCanTerminateOwnershipChange, doesChangeVideoOwnershipExist } from '../../helpers/custom-validators/video-ownership' | 42 | import { checkUserCanTerminateOwnershipChange, doesChangeVideoOwnershipExist } from '../../../helpers/custom-validators/video-ownership' |
41 | import { VideoChangeOwnershipAccept } from '../../../shared/models/videos/video-change-ownership-accept.model' | 43 | import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/video-change-ownership-accept.model' |
42 | import { VideoChangeOwnershipModel } from '../../models/video/video-change-ownership' | 44 | import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ownership' |
43 | import { AccountModel } from '../../models/account/account' | 45 | import { AccountModel } from '../../../models/account/account' |
44 | import { VideoFetchType } from '../../helpers/video' | 46 | import { VideoFetchType } from '../../../helpers/video' |
47 | import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search' | ||
45 | 48 | ||
46 | const videosAddValidator = getCommonVideoAttributes().concat([ | 49 | const videosAddValidator = getCommonVideoAttributes().concat([ |
47 | body('videofile') | 50 | body('videofile') |
@@ -69,7 +72,6 @@ const videosAddValidator = getCommonVideoAttributes().concat([ | |||
69 | if (isAble === false) { | 72 | if (isAble === false) { |
70 | res.status(403) | 73 | res.status(403) |
71 | .json({ error: 'The user video quota is exceeded with this video.' }) | 74 | .json({ error: 'The user video quota is exceeded with this video.' }) |
72 | .end() | ||
73 | 75 | ||
74 | return cleanUpReqFiles(req) | 76 | return cleanUpReqFiles(req) |
75 | } | 77 | } |
@@ -82,7 +84,6 @@ const videosAddValidator = getCommonVideoAttributes().concat([ | |||
82 | logger.error('Invalid input file in videosAddValidator.', { err }) | 84 | logger.error('Invalid input file in videosAddValidator.', { err }) |
83 | res.status(400) | 85 | res.status(400) |
84 | .json({ error: 'Invalid input file.' }) | 86 | .json({ error: 'Invalid input file.' }) |
85 | .end() | ||
86 | 87 | ||
87 | return cleanUpReqFiles(req) | 88 | return cleanUpReqFiles(req) |
88 | } | 89 | } |
@@ -120,7 +121,6 @@ const videosUpdateValidator = getCommonVideoAttributes().concat([ | |||
120 | cleanUpReqFiles(req) | 121 | cleanUpReqFiles(req) |
121 | return res.status(409) | 122 | return res.status(409) |
122 | .json({ error: 'Cannot set "private" a video that was not private.' }) | 123 | .json({ error: 'Cannot set "private" a video that was not private.' }) |
123 | .end() | ||
124 | } | 124 | } |
125 | 125 | ||
126 | if (req.body.channelId && !await isVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) | 126 | if (req.body.channelId && !await isVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) |
@@ -150,7 +150,6 @@ const videosCustomGetValidator = (fetchType: VideoFetchType) => { | |||
150 | if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) { | 150 | if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) { |
151 | return res.status(403) | 151 | return res.status(403) |
152 | .json({ error: 'Cannot get this private or blacklisted video.' }) | 152 | .json({ error: 'Cannot get this private or blacklisted video.' }) |
153 | .end() | ||
154 | } | 153 | } |
155 | 154 | ||
156 | return next() | 155 | return next() |
@@ -239,8 +238,8 @@ const videosChangeOwnershipValidator = [ | |||
239 | const nextOwner = await AccountModel.loadLocalByName(req.body.username) | 238 | const nextOwner = await AccountModel.loadLocalByName(req.body.username) |
240 | if (!nextOwner) { | 239 | if (!nextOwner) { |
241 | res.status(400) | 240 | res.status(400) |
242 | .type('json') | 241 | .json({ error: 'Changing video ownership to a remote account is not supported yet' }) |
243 | .end() | 242 | |
244 | return | 243 | return |
245 | } | 244 | } |
246 | res.locals.nextOwner = nextOwner | 245 | res.locals.nextOwner = nextOwner |
@@ -271,7 +270,7 @@ const videosTerminateChangeOwnershipValidator = [ | |||
271 | } else { | 270 | } else { |
272 | res.status(403) | 271 | res.status(403) |
273 | .json({ error: 'Ownership already accepted or refused' }) | 272 | .json({ error: 'Ownership already accepted or refused' }) |
274 | .end() | 273 | |
275 | return | 274 | return |
276 | } | 275 | } |
277 | } | 276 | } |
@@ -288,7 +287,7 @@ const videosAcceptChangeOwnershipValidator = [ | |||
288 | if (isAble === false) { | 287 | if (isAble === false) { |
289 | res.status(403) | 288 | res.status(403) |
290 | .json({ error: 'The user video quota is exceeded with this video.' }) | 289 | .json({ error: 'The user video quota is exceeded with this video.' }) |
291 | .end() | 290 | |
292 | return | 291 | return |
293 | } | 292 | } |
294 | 293 | ||
@@ -363,6 +362,51 @@ function getCommonVideoAttributes () { | |||
363 | ] as (ValidationChain | express.Handler)[] | 362 | ] as (ValidationChain | express.Handler)[] |
364 | } | 363 | } |
365 | 364 | ||
365 | const commonVideosFiltersValidator = [ | ||
366 | query('categoryOneOf') | ||
367 | .optional() | ||
368 | .customSanitizer(toArray) | ||
369 | .custom(isNumberArray).withMessage('Should have a valid one of category array'), | ||
370 | query('licenceOneOf') | ||
371 | .optional() | ||
372 | .customSanitizer(toArray) | ||
373 | .custom(isNumberArray).withMessage('Should have a valid one of licence array'), | ||
374 | query('languageOneOf') | ||
375 | .optional() | ||
376 | .customSanitizer(toArray) | ||
377 | .custom(isStringArray).withMessage('Should have a valid one of language array'), | ||
378 | query('tagsOneOf') | ||
379 | .optional() | ||
380 | .customSanitizer(toArray) | ||
381 | .custom(isStringArray).withMessage('Should have a valid one of tags array'), | ||
382 | query('tagsAllOf') | ||
383 | .optional() | ||
384 | .customSanitizer(toArray) | ||
385 | .custom(isStringArray).withMessage('Should have a valid all of tags array'), | ||
386 | query('nsfw') | ||
387 | .optional() | ||
388 | .custom(isNSFWQueryValid).withMessage('Should have a valid NSFW attribute'), | ||
389 | query('filter') | ||
390 | .optional() | ||
391 | .custom(isVideoFilterValid).withMessage('Should have a valid filter attribute'), | ||
392 | |||
393 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
394 | logger.debug('Checking commons video filters query', { parameters: req.query }) | ||
395 | |||
396 | if (areValidationErrors(req, res)) return | ||
397 | |||
398 | const user: UserModel = res.locals.oauth ? res.locals.oauth.token.User : undefined | ||
399 | if (req.query.filter === 'all-local' && (!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) === false)) { | ||
400 | res.status(401) | ||
401 | .json({ error: 'You are not allowed to see all local videos.' }) | ||
402 | |||
403 | return | ||
404 | } | ||
405 | |||
406 | return next() | ||
407 | } | ||
408 | ] | ||
409 | |||
366 | // --------------------------------------------------------------------------- | 410 | // --------------------------------------------------------------------------- |
367 | 411 | ||
368 | export { | 412 | export { |
@@ -379,7 +423,9 @@ export { | |||
379 | videosTerminateChangeOwnershipValidator, | 423 | videosTerminateChangeOwnershipValidator, |
380 | videosAcceptChangeOwnershipValidator, | 424 | videosAcceptChangeOwnershipValidator, |
381 | 425 | ||
382 | getCommonVideoAttributes | 426 | getCommonVideoAttributes, |
427 | |||
428 | commonVideosFiltersValidator | ||
383 | } | 429 | } |
384 | 430 | ||
385 | // --------------------------------------------------------------------------- | 431 | // --------------------------------------------------------------------------- |
@@ -389,7 +435,6 @@ function areErrorsInScheduleUpdate (req: express.Request, res: express.Response) | |||
389 | if (!req.body.scheduleUpdate.updateAt) { | 435 | if (!req.body.scheduleUpdate.updateAt) { |
390 | res.status(400) | 436 | res.status(400) |
391 | .json({ error: 'Schedule update at is mandatory.' }) | 437 | .json({ error: 'Schedule update at is mandatory.' }) |
392 | .end() | ||
393 | 438 | ||
394 | return true | 439 | return true |
395 | } | 440 | } |