diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/accounts.ts | 3 | ||||
-rw-r--r-- | server/controllers/api/users/my-subscriptions.ts | 11 | ||||
-rw-r--r-- | server/controllers/api/video-channel.ts | 3 | ||||
-rw-r--r-- | server/middlewares/validators/user-subscriptions.ts | 13 | ||||
-rw-r--r-- | server/models/activitypub/actor-follow.ts | 31 | ||||
-rw-r--r-- | server/models/video/video-channel.ts | 24 |
6 files changed, 70 insertions, 15 deletions
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index ccdc610a2..b1c05c6c0 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -120,7 +120,8 @@ async function listAccountChannels (req: express.Request, res: express.Response) | |||
120 | start: req.query.start, | 120 | start: req.query.start, |
121 | count: req.query.count, | 121 | count: req.query.count, |
122 | sort: req.query.sort, | 122 | sort: req.query.sort, |
123 | withStats: req.query.withStats | 123 | withStats: req.query.withStats, |
124 | search: req.query.search | ||
124 | } | 125 | } |
125 | 126 | ||
126 | const resultList = await VideoChannelModel.listByAccount(options) | 127 | const resultList = await VideoChannelModel.listByAccount(options) |
diff --git a/server/controllers/api/users/my-subscriptions.ts b/server/controllers/api/users/my-subscriptions.ts index efe1b9bc3..d207a19ae 100644 --- a/server/controllers/api/users/my-subscriptions.ts +++ b/server/controllers/api/users/my-subscriptions.ts | |||
@@ -13,7 +13,7 @@ import { | |||
13 | userSubscriptionAddValidator, | 13 | userSubscriptionAddValidator, |
14 | userSubscriptionGetValidator | 14 | userSubscriptionGetValidator |
15 | } from '../../../middlewares' | 15 | } from '../../../middlewares' |
16 | import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators' | 16 | import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator, userSubscriptionListValidator } from '../../../middlewares/validators' |
17 | import { VideoModel } from '../../../models/video/video' | 17 | import { VideoModel } from '../../../models/video/video' |
18 | import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' | 18 | import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' |
19 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' | 19 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' |
@@ -45,6 +45,7 @@ mySubscriptionsRouter.get('/me/subscriptions', | |||
45 | userSubscriptionsSortValidator, | 45 | userSubscriptionsSortValidator, |
46 | setDefaultSort, | 46 | setDefaultSort, |
47 | setDefaultPagination, | 47 | setDefaultPagination, |
48 | userSubscriptionListValidator, | ||
48 | asyncMiddleware(getUserSubscriptions) | 49 | asyncMiddleware(getUserSubscriptions) |
49 | ) | 50 | ) |
50 | 51 | ||
@@ -141,7 +142,13 @@ async function getUserSubscriptions (req: express.Request, res: express.Response | |||
141 | const user = res.locals.oauth.token.User | 142 | const user = res.locals.oauth.token.User |
142 | const actorId = user.Account.Actor.id | 143 | const actorId = user.Account.Actor.id |
143 | 144 | ||
144 | const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort) | 145 | const resultList = await ActorFollowModel.listSubscriptionsForApi({ |
146 | actorId, | ||
147 | start: req.query.start, | ||
148 | count: req.query.count, | ||
149 | sort: req.query.sort, | ||
150 | search: req.query.search | ||
151 | }) | ||
145 | 152 | ||
146 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 153 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
147 | } | 154 | } |
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index d96998209..f705034fd 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts | |||
@@ -119,8 +119,7 @@ async function listVideoChannels (req: express.Request, res: express.Response) { | |||
119 | actorId: serverActor.id, | 119 | actorId: serverActor.id, |
120 | start: req.query.start, | 120 | start: req.query.start, |
121 | count: req.query.count, | 121 | count: req.query.count, |
122 | sort: req.query.sort, | 122 | sort: req.query.sort |
123 | search: req.query.search | ||
124 | }) | 123 | }) |
125 | 124 | ||
126 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 125 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
diff --git a/server/middlewares/validators/user-subscriptions.ts b/server/middlewares/validators/user-subscriptions.ts index 5d4cc94c5..a54ecb704 100644 --- a/server/middlewares/validators/user-subscriptions.ts +++ b/server/middlewares/validators/user-subscriptions.ts | |||
@@ -7,6 +7,18 @@ import { areValidActorHandles, isValidActorHandle } from '../../helpers/custom-v | |||
7 | import { toArray } from '../../helpers/custom-validators/misc' | 7 | import { toArray } from '../../helpers/custom-validators/misc' |
8 | import { WEBSERVER } from '../../initializers/constants' | 8 | import { WEBSERVER } from '../../initializers/constants' |
9 | 9 | ||
10 | const userSubscriptionListValidator = [ | ||
11 | query('search').optional().not().isEmpty().withMessage('Should have a valid search'), | ||
12 | |||
13 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
14 | logger.debug('Checking userSubscriptionListValidator parameters', { parameters: req.query }) | ||
15 | |||
16 | if (areValidationErrors(req, res)) return | ||
17 | |||
18 | return next() | ||
19 | } | ||
20 | ] | ||
21 | |||
10 | const userSubscriptionAddValidator = [ | 22 | const userSubscriptionAddValidator = [ |
11 | body('uri').custom(isValidActorHandle).withMessage('Should have a valid URI to follow (username@domain)'), | 23 | body('uri').custom(isValidActorHandle).withMessage('Should have a valid URI to follow (username@domain)'), |
12 | 24 | ||
@@ -64,6 +76,7 @@ const userSubscriptionGetValidator = [ | |||
64 | 76 | ||
65 | export { | 77 | export { |
66 | areSubscriptionsExistValidator, | 78 | areSubscriptionsExistValidator, |
79 | userSubscriptionListValidator, | ||
67 | userSubscriptionAddValidator, | 80 | userSubscriptionAddValidator, |
68 | userSubscriptionGetValidator | 81 | userSubscriptionGetValidator |
69 | } | 82 | } |
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts index 3e85cc329..529cb35cc 100644 --- a/server/models/activitypub/actor-follow.ts +++ b/server/models/activitypub/actor-follow.ts | |||
@@ -15,14 +15,15 @@ import { | |||
15 | Max, | 15 | Max, |
16 | Model, | 16 | Model, |
17 | Table, | 17 | Table, |
18 | UpdatedAt | 18 | UpdatedAt, |
19 | Sequelize | ||
19 | } from 'sequelize-typescript' | 20 | } from 'sequelize-typescript' |
20 | import { FollowState } from '../../../shared/models/actors' | 21 | import { FollowState } from '../../../shared/models/actors' |
21 | import { ActorFollow } from '../../../shared/models/actors/follow.model' | 22 | import { ActorFollow } from '../../../shared/models/actors/follow.model' |
22 | import { logger } from '../../helpers/logger' | 23 | import { logger } from '../../helpers/logger' |
23 | import { ACTOR_FOLLOW_SCORE, FOLLOW_STATES, SERVER_ACTOR_NAME } from '../../initializers/constants' | 24 | import { ACTOR_FOLLOW_SCORE, FOLLOW_STATES, SERVER_ACTOR_NAME } from '../../initializers/constants' |
24 | import { ServerModel } from '../server/server' | 25 | import { ServerModel } from '../server/server' |
25 | import { createSafeIn, getFollowsSort, getSort } from '../utils' | 26 | import { createSafeIn, getFollowsSort, getSort, searchAttribute } from '../utils' |
26 | import { ActorModel, unusedActorAttributesForAPI } from './actor' | 27 | import { ActorModel, unusedActorAttributesForAPI } from './actor' |
27 | import { VideoChannelModel } from '../video/video-channel' | 28 | import { VideoChannelModel } from '../video/video-channel' |
28 | import { AccountModel } from '../account/account' | 29 | import { AccountModel } from '../account/account' |
@@ -440,16 +441,34 @@ export class ActorFollowModel extends Model<ActorFollowModel> { | |||
440 | }) | 441 | }) |
441 | } | 442 | } |
442 | 443 | ||
443 | static listSubscriptionsForApi (actorId: number, start: number, count: number, sort: string) { | 444 | static listSubscriptionsForApi (options: { |
445 | actorId: number | ||
446 | start: number | ||
447 | count: number | ||
448 | sort: string | ||
449 | search?: string | ||
450 | }) { | ||
451 | const { actorId, start, count, sort } = options | ||
452 | const where = { | ||
453 | actorId: actorId | ||
454 | } | ||
455 | |||
456 | if (options.search) { | ||
457 | Object.assign(where, { | ||
458 | [Op.or]: [ | ||
459 | searchAttribute(options.search, '$ActorFollowing.preferredUsername$'), | ||
460 | searchAttribute(options.search, '$ActorFollowing.VideoChannel.name$') | ||
461 | ] | ||
462 | }) | ||
463 | } | ||
464 | |||
444 | const query = { | 465 | const query = { |
445 | attributes: [], | 466 | attributes: [], |
446 | distinct: true, | 467 | distinct: true, |
447 | offset: start, | 468 | offset: start, |
448 | limit: count, | 469 | limit: count, |
449 | order: getSort(sort), | 470 | order: getSort(sort), |
450 | where: { | 471 | where, |
451 | actorId: actorId | ||
452 | }, | ||
453 | include: [ | 472 | include: [ |
454 | { | 473 | { |
455 | attributes: [ 'id' ], | 474 | attributes: [ 'id' ], |
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index f3401fb9c..9da965bbc 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -315,9 +315,8 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
315 | start: number | 315 | start: number |
316 | count: number | 316 | count: number |
317 | sort: string | 317 | sort: string |
318 | search?: string | ||
319 | }) { | 318 | }) { |
320 | const { actorId, search } = parameters | 319 | const { actorId } = parameters |
321 | 320 | ||
322 | const query = { | 321 | const query = { |
323 | offset: parameters.start, | 322 | offset: parameters.start, |
@@ -326,7 +325,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
326 | } | 325 | } |
327 | 326 | ||
328 | const scopes = { | 327 | const scopes = { |
329 | method: [ ScopeNames.FOR_API, { actorId, search } as AvailableForListOptions ] | 328 | method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ] |
330 | } | 329 | } |
331 | return VideoChannelModel | 330 | return VideoChannelModel |
332 | .scope(scopes) | 331 | .scope(scopes) |
@@ -405,7 +404,23 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
405 | count: number | 404 | count: number |
406 | sort: string | 405 | sort: string |
407 | withStats?: boolean | 406 | withStats?: boolean |
407 | search?: string | ||
408 | }) { | 408 | }) { |
409 | const escapedSearch = VideoModel.sequelize.escape(options.search) | ||
410 | const escapedLikeSearch = VideoModel.sequelize.escape('%' + options.search + '%') | ||
411 | const where = options.search | ||
412 | ? { | ||
413 | [Op.or]: [ | ||
414 | Sequelize.literal( | ||
415 | 'lower(immutable_unaccent("VideoChannelModel"."name")) % lower(immutable_unaccent(' + escapedSearch + '))' | ||
416 | ), | ||
417 | Sequelize.literal( | ||
418 | 'lower(immutable_unaccent("VideoChannelModel"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' | ||
419 | ) | ||
420 | ] | ||
421 | } | ||
422 | : null | ||
423 | |||
409 | const query = { | 424 | const query = { |
410 | offset: options.start, | 425 | offset: options.start, |
411 | limit: options.count, | 426 | limit: options.count, |
@@ -418,7 +433,8 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
418 | }, | 433 | }, |
419 | required: true | 434 | required: true |
420 | } | 435 | } |
421 | ] | 436 | ], |
437 | where | ||
422 | } | 438 | } |
423 | 439 | ||
424 | const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ] | 440 | const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ] |