diff options
author | Chocobozzz <me@florianbigard.com> | 2018-11-16 15:02:48 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-11-16 15:49:16 +0100 |
commit | 8d4273463fb19d503b1aa0a32dc289f292ed614e (patch) | |
tree | f422773ecba3405bb5808bed8e25b62ac6b7ea08 /server/middlewares | |
parent | 5776f78e3b3f3a371ec30c7fcb11e7ca17f2f65e (diff) | |
download | PeerTube-8d4273463fb19d503b1aa0a32dc289f292ed614e.tar.gz PeerTube-8d4273463fb19d503b1aa0a32dc289f292ed614e.tar.zst PeerTube-8d4273463fb19d503b1aa0a32dc289f292ed614e.zip |
Check follow constraints when getting a video
Diffstat (limited to 'server/middlewares')
-rw-r--r-- | server/middlewares/oauth.ts | 16 | ||||
-rw-r--r-- | server/middlewares/validators/videos/videos.ts | 52 |
2 files changed, 57 insertions, 11 deletions
diff --git a/server/middlewares/oauth.ts b/server/middlewares/oauth.ts index 5233b66bd..8c1df2c3e 100644 --- a/server/middlewares/oauth.ts +++ b/server/middlewares/oauth.ts | |||
@@ -28,9 +28,24 @@ function authenticate (req: express.Request, res: express.Response, next: expres | |||
28 | }) | 28 | }) |
29 | } | 29 | } |
30 | 30 | ||
31 | function authenticatePromiseIfNeeded (req: express.Request, res: express.Response) { | ||
32 | return new Promise(resolve => { | ||
33 | // Already authenticated? (or tried to) | ||
34 | if (res.locals.oauth && res.locals.oauth.token.User) return resolve() | ||
35 | |||
36 | if (res.locals.authenticated === false) return res.sendStatus(401) | ||
37 | |||
38 | authenticate(req, res, () => { | ||
39 | return resolve() | ||
40 | }) | ||
41 | }) | ||
42 | } | ||
43 | |||
31 | function optionalAuthenticate (req: express.Request, res: express.Response, next: express.NextFunction) { | 44 | function optionalAuthenticate (req: express.Request, res: express.Response, next: express.NextFunction) { |
32 | if (req.header('authorization')) return authenticate(req, res, next) | 45 | if (req.header('authorization')) return authenticate(req, res, next) |
33 | 46 | ||
47 | res.locals.authenticated = false | ||
48 | |||
34 | return next() | 49 | return next() |
35 | } | 50 | } |
36 | 51 | ||
@@ -53,6 +68,7 @@ function token (req: express.Request, res: express.Response, next: express.NextF | |||
53 | 68 | ||
54 | export { | 69 | export { |
55 | authenticate, | 70 | authenticate, |
71 | authenticatePromiseIfNeeded, | ||
56 | optionalAuthenticate, | 72 | optionalAuthenticate, |
57 | token | 73 | token |
58 | } | 74 | } |
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index bf21bca8c..051a19e16 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts | |||
@@ -31,8 +31,8 @@ import { | |||
31 | } from '../../../helpers/custom-validators/videos' | 31 | } from '../../../helpers/custom-validators/videos' |
32 | import { getDurationFromVideoFile } from '../../../helpers/ffmpeg-utils' | 32 | import { getDurationFromVideoFile } from '../../../helpers/ffmpeg-utils' |
33 | import { logger } from '../../../helpers/logger' | 33 | import { logger } from '../../../helpers/logger' |
34 | import { CONSTRAINTS_FIELDS } from '../../../initializers' | 34 | import { CONFIG, CONSTRAINTS_FIELDS } from '../../../initializers' |
35 | import { authenticate } from '../../oauth' | 35 | import { authenticatePromiseIfNeeded } from '../../oauth' |
36 | import { areValidationErrors } from '../utils' | 36 | import { areValidationErrors } from '../utils' |
37 | import { cleanUpReqFiles } from '../../../helpers/express-utils' | 37 | import { cleanUpReqFiles } from '../../../helpers/express-utils' |
38 | import { VideoModel } from '../../../models/video/video' | 38 | import { VideoModel } from '../../../models/video/video' |
@@ -43,6 +43,7 @@ import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ow | |||
43 | import { AccountModel } from '../../../models/account/account' | 43 | import { AccountModel } from '../../../models/account/account' |
44 | import { VideoFetchType } from '../../../helpers/video' | 44 | import { VideoFetchType } from '../../../helpers/video' |
45 | import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search' | 45 | import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search' |
46 | import { getServerActor } from '../../../helpers/utils' | ||
46 | 47 | ||
47 | const videosAddValidator = getCommonVideoAttributes().concat([ | 48 | const videosAddValidator = getCommonVideoAttributes().concat([ |
48 | body('videofile') | 49 | body('videofile') |
@@ -127,6 +128,31 @@ const videosUpdateValidator = getCommonVideoAttributes().concat([ | |||
127 | } | 128 | } |
128 | ]) | 129 | ]) |
129 | 130 | ||
131 | async function checkVideoFollowConstraints (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
132 | const video: VideoModel = res.locals.video | ||
133 | |||
134 | // Anybody can watch local videos | ||
135 | if (video.isOwned() === true) return next() | ||
136 | |||
137 | // Logged user | ||
138 | if (res.locals.oauth) { | ||
139 | // Users can search or watch remote videos | ||
140 | if (CONFIG.SEARCH.REMOTE_URI.USERS === true) return next() | ||
141 | } | ||
142 | |||
143 | // Anybody can search or watch remote videos | ||
144 | if (CONFIG.SEARCH.REMOTE_URI.ANONYMOUS === true) return next() | ||
145 | |||
146 | // Check our instance follows an actor that shared this video | ||
147 | const serverActor = await getServerActor() | ||
148 | if (await VideoModel.checkVideoHasInstanceFollow(video.id, serverActor.id) === true) return next() | ||
149 | |||
150 | return res.status(403) | ||
151 | .json({ | ||
152 | error: 'Cannot get this video regarding follow constraints.' | ||
153 | }) | ||
154 | } | ||
155 | |||
130 | const videosCustomGetValidator = (fetchType: VideoFetchType) => { | 156 | const videosCustomGetValidator = (fetchType: VideoFetchType) => { |
131 | return [ | 157 | return [ |
132 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 158 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
@@ -141,17 +167,20 @@ const videosCustomGetValidator = (fetchType: VideoFetchType) => { | |||
141 | 167 | ||
142 | // Video private or blacklisted | 168 | // Video private or blacklisted |
143 | if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) { | 169 | if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) { |
144 | return authenticate(req, res, () => { | 170 | await authenticatePromiseIfNeeded(req, res) |
145 | const user: UserModel = res.locals.oauth.token.User | 171 | |
172 | const user: UserModel = res.locals.oauth ? res.locals.oauth.token.User : null | ||
146 | 173 | ||
147 | // Only the owner or a user that have blacklist rights can see the video | 174 | // Only the owner or a user that have blacklist rights can see the video |
148 | if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) { | 175 | if ( |
149 | return res.status(403) | 176 | !user || |
150 | .json({ error: 'Cannot get this private or blacklisted video.' }) | 177 | (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) |
151 | } | 178 | ) { |
179 | return res.status(403) | ||
180 | .json({ error: 'Cannot get this private or blacklisted video.' }) | ||
181 | } | ||
152 | 182 | ||
153 | return next() | 183 | return next() |
154 | }) | ||
155 | } | 184 | } |
156 | 185 | ||
157 | // Video is public, anyone can access it | 186 | // Video is public, anyone can access it |
@@ -376,6 +405,7 @@ export { | |||
376 | videosAddValidator, | 405 | videosAddValidator, |
377 | videosUpdateValidator, | 406 | videosUpdateValidator, |
378 | videosGetValidator, | 407 | videosGetValidator, |
408 | checkVideoFollowConstraints, | ||
379 | videosCustomGetValidator, | 409 | videosCustomGetValidator, |
380 | videosRemoveValidator, | 410 | videosRemoveValidator, |
381 | 411 | ||