diff options
author | Chocobozzz <me@florianbigard.com> | 2021-10-20 09:05:43 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-10-20 09:25:44 +0200 |
commit | 978c87e7f58b6673fe60f04f1767bc9e02ea4936 (patch) | |
tree | e7d48735d4099fec8c7732f33e7dadb09c0eac80 /server | |
parent | 7e76cc380040e40a2292a9dc825f037c9b538030 (diff) | |
download | PeerTube-978c87e7f58b6673fe60f04f1767bc9e02ea4936.tar.gz PeerTube-978c87e7f58b6673fe60f04f1767bc9e02ea4936.tar.zst PeerTube-978c87e7f58b6673fe60f04f1767bc9e02ea4936.zip |
Add channel filters for my videos/followers
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/users/me.ts | 4 | ||||
-rw-r--r-- | server/middlewares/validators/users.ts | 27 | ||||
-rw-r--r-- | server/models/video/video.ts | 9 | ||||
-rw-r--r-- | server/tests/api/check-params/videos.ts | 14 | ||||
-rw-r--r-- | server/tests/api/users/users.ts | 25 |
5 files changed, 75 insertions, 4 deletions
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index 83b774d3c..6bacdbbb6 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts | |||
@@ -25,7 +25,7 @@ import { | |||
25 | usersUpdateMeValidator, | 25 | usersUpdateMeValidator, |
26 | usersVideoRatingValidator | 26 | usersVideoRatingValidator |
27 | } from '../../../middlewares' | 27 | } from '../../../middlewares' |
28 | import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators' | 28 | import { deleteMeValidator, usersVideosValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators' |
29 | import { updateAvatarValidator } from '../../../middlewares/validators/actor-image' | 29 | import { updateAvatarValidator } from '../../../middlewares/validators/actor-image' |
30 | import { AccountModel } from '../../../models/account/account' | 30 | import { AccountModel } from '../../../models/account/account' |
31 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | 31 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' |
@@ -69,6 +69,7 @@ meRouter.get('/me/videos', | |||
69 | videosSortValidator, | 69 | videosSortValidator, |
70 | setDefaultVideosSort, | 70 | setDefaultVideosSort, |
71 | setDefaultPagination, | 71 | setDefaultPagination, |
72 | asyncMiddleware(usersVideosValidator), | ||
72 | asyncMiddleware(getUserVideos) | 73 | asyncMiddleware(getUserVideos) |
73 | ) | 74 | ) |
74 | 75 | ||
@@ -113,6 +114,7 @@ async function getUserVideos (req: express.Request, res: express.Response) { | |||
113 | count: req.query.count, | 114 | count: req.query.count, |
114 | sort: req.query.sort, | 115 | sort: req.query.sort, |
115 | search: req.query.search, | 116 | search: req.query.search, |
117 | channelId: res.locals.videoChannel?.id, | ||
116 | isLive: req.query.isLive | 118 | isLive: req.query.isLive |
117 | }, 'filter:api.user.me.videos.list.params') | 119 | }, 'filter:api.user.me.videos.list.params') |
118 | 120 | ||
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index c6eeeaf18..8f1a7801f 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -4,7 +4,7 @@ import { omit } from 'lodash' | |||
4 | import { Hooks } from '@server/lib/plugins/hooks' | 4 | import { Hooks } from '@server/lib/plugins/hooks' |
5 | import { MUserDefault } from '@server/types/models' | 5 | import { MUserDefault } from '@server/types/models' |
6 | import { HttpStatusCode, UserRegister, UserRole } from '@shared/models' | 6 | import { HttpStatusCode, UserRegister, UserRole } from '@shared/models' |
7 | import { toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' | 7 | import { isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' |
8 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' | 8 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' |
9 | import { | 9 | import { |
10 | isUserAdminFlagsValid, | 10 | isUserAdminFlagsValid, |
@@ -31,7 +31,7 @@ import { Redis } from '../../lib/redis' | |||
31 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup' | 31 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup' |
32 | import { ActorModel } from '../../models/actor/actor' | 32 | import { ActorModel } from '../../models/actor/actor' |
33 | import { UserModel } from '../../models/user/user' | 33 | import { UserModel } from '../../models/user/user' |
34 | import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from './shared' | 34 | import { areValidationErrors, doesVideoChannelIdExist, doesVideoExist, isValidVideoIdParam } from './shared' |
35 | 35 | ||
36 | const usersListValidator = [ | 36 | const usersListValidator = [ |
37 | query('blocked') | 37 | query('blocked') |
@@ -318,6 +318,28 @@ const usersVideoRatingValidator = [ | |||
318 | } | 318 | } |
319 | ] | 319 | ] |
320 | 320 | ||
321 | const usersVideosValidator = [ | ||
322 | query('isLive') | ||
323 | .optional() | ||
324 | .customSanitizer(toBooleanOrNull) | ||
325 | .custom(isBooleanValid).withMessage('Should have a valid live boolean'), | ||
326 | |||
327 | query('channelId') | ||
328 | .optional() | ||
329 | .customSanitizer(toIntOrNull) | ||
330 | .custom(isIdValid).withMessage('Should have a valid channel id'), | ||
331 | |||
332 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
333 | logger.debug('Checking usersVideosValidator parameters', { parameters: req.params }) | ||
334 | |||
335 | if (areValidationErrors(req, res)) return | ||
336 | |||
337 | if (req.query.channelId && !await doesVideoChannelIdExist(req.query.channelId, res)) return | ||
338 | |||
339 | return next() | ||
340 | } | ||
341 | ] | ||
342 | |||
321 | const ensureUserRegistrationAllowed = [ | 343 | const ensureUserRegistrationAllowed = [ |
322 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 344 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
323 | const allowedParams = { | 345 | const allowedParams = { |
@@ -513,6 +535,7 @@ export { | |||
513 | ensureUserRegistrationAllowed, | 535 | ensureUserRegistrationAllowed, |
514 | ensureUserRegistrationAllowedForIP, | 536 | ensureUserRegistrationAllowedForIP, |
515 | usersGetValidator, | 537 | usersGetValidator, |
538 | usersVideosValidator, | ||
516 | usersAskResetPasswordValidator, | 539 | usersAskResetPasswordValidator, |
517 | usersResetPasswordValidator, | 540 | usersResetPasswordValidator, |
518 | usersAskSendVerifyEmailValidator, | 541 | usersAskSendVerifyEmailValidator, |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index d2daf18ee..4044287ee 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -978,10 +978,12 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
978 | start: number | 978 | start: number |
979 | count: number | 979 | count: number |
980 | sort: string | 980 | sort: string |
981 | |||
982 | channelId?: number | ||
981 | isLive?: boolean | 983 | isLive?: boolean |
982 | search?: string | 984 | search?: string |
983 | }) { | 985 | }) { |
984 | const { accountId, start, count, sort, search, isLive } = options | 986 | const { accountId, channelId, start, count, sort, search, isLive } = options |
985 | 987 | ||
986 | function buildBaseQuery (): FindOptions { | 988 | function buildBaseQuery (): FindOptions { |
987 | const where: WhereOptions = {} | 989 | const where: WhereOptions = {} |
@@ -996,6 +998,10 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
996 | where.isLive = isLive | 998 | where.isLive = isLive |
997 | } | 999 | } |
998 | 1000 | ||
1001 | const channelWhere = channelId | ||
1002 | ? { id: channelId } | ||
1003 | : {} | ||
1004 | |||
999 | const baseQuery = { | 1005 | const baseQuery = { |
1000 | offset: start, | 1006 | offset: start, |
1001 | limit: count, | 1007 | limit: count, |
@@ -1005,6 +1011,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1005 | { | 1011 | { |
1006 | model: VideoChannelModel, | 1012 | model: VideoChannelModel, |
1007 | required: true, | 1013 | required: true, |
1014 | where: channelWhere, | ||
1008 | include: [ | 1015 | include: [ |
1009 | { | 1016 | { |
1010 | model: AccountModel, | 1017 | model: AccountModel, |
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index e11ca0c82..d02b6e156 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -119,6 +119,20 @@ describe('Test videos API validator', function () { | |||
119 | await checkBadSortPagination(server.url, path, server.accessToken) | 119 | await checkBadSortPagination(server.url, path, server.accessToken) |
120 | }) | 120 | }) |
121 | 121 | ||
122 | it('Should fail with an invalid channel', async function () { | ||
123 | await makeGetRequest({ url: server.url, token: server.accessToken, path, query: { channelId: 'toto' } }) | ||
124 | }) | ||
125 | |||
126 | it('Should fail with an unknown channel', async function () { | ||
127 | await makeGetRequest({ | ||
128 | url: server.url, | ||
129 | token: server.accessToken, | ||
130 | path, | ||
131 | query: { channelId: 89898 }, | ||
132 | expectedStatus: HttpStatusCode.NOT_FOUND_404 | ||
133 | }) | ||
134 | }) | ||
135 | |||
122 | it('Should success with the correct parameters', async function () { | 136 | it('Should success with the correct parameters', async function () { |
123 | await makeGetRequest({ url: server.url, token: server.accessToken, path, expectedStatus: HttpStatusCode.OK_200 }) | 137 | await makeGetRequest({ url: server.url, token: server.accessToken, path, expectedStatus: HttpStatusCode.OK_200 }) |
124 | }) | 138 | }) |
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 085d9d870..6c41e7d56 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts | |||
@@ -318,6 +318,8 @@ describe('Test users', function () { | |||
318 | fixture: 'video_short.webm' | 318 | fixture: 'video_short.webm' |
319 | } | 319 | } |
320 | await server.videos.upload({ token: userToken, attributes }) | 320 | await server.videos.upload({ token: userToken, attributes }) |
321 | |||
322 | await server.channels.create({ token: userToken, attributes: { name: 'other_channel' } }) | ||
321 | }) | 323 | }) |
322 | 324 | ||
323 | it('Should have video quota updated', async function () { | 325 | it('Should have video quota updated', async function () { |
@@ -340,6 +342,29 @@ describe('Test users', function () { | |||
340 | expect(video.previewPath).to.not.be.null | 342 | expect(video.previewPath).to.not.be.null |
341 | }) | 343 | }) |
342 | 344 | ||
345 | it('Should be able to filter by channel in my videos', async function () { | ||
346 | const myInfo = await server.users.getMyInfo({ token: userToken }) | ||
347 | const mainChannel = myInfo.videoChannels.find(c => c.name !== 'other_channel') | ||
348 | const otherChannel = myInfo.videoChannels.find(c => c.name === 'other_channel') | ||
349 | |||
350 | { | ||
351 | const { total, data } = await server.videos.listMyVideos({ token: userToken, channelId: mainChannel.id }) | ||
352 | expect(total).to.equal(1) | ||
353 | expect(data).to.have.lengthOf(1) | ||
354 | |||
355 | const video: Video = data[0] | ||
356 | expect(video.name).to.equal('super user video') | ||
357 | expect(video.thumbnailPath).to.not.be.null | ||
358 | expect(video.previewPath).to.not.be.null | ||
359 | } | ||
360 | |||
361 | { | ||
362 | const { total, data } = await server.videos.listMyVideos({ token: userToken, channelId: otherChannel.id }) | ||
363 | expect(total).to.equal(0) | ||
364 | expect(data).to.have.lengthOf(0) | ||
365 | } | ||
366 | }) | ||
367 | |||
343 | it('Should be able to search in my videos', async function () { | 368 | it('Should be able to search in my videos', async function () { |
344 | { | 369 | { |
345 | const { total, data } = await server.videos.listMyVideos({ token: userToken, sort: '-createdAt', search: 'user video' }) | 370 | const { total, data } = await server.videos.listMyVideos({ token: userToken, sort: '-createdAt', search: 'user video' }) |