aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/accounts.ts3
-rw-r--r--server/controllers/api/users/my-subscriptions.ts11
-rw-r--r--server/controllers/api/video-channel.ts3
-rw-r--r--server/middlewares/validators/user-subscriptions.ts13
-rw-r--r--server/models/activitypub/actor-follow.ts31
-rw-r--r--server/models/video/video-channel.ts24
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'
16import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators' 16import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator, userSubscriptionListValidator } from '../../../middlewares/validators'
17import { VideoModel } from '../../../models/video/video' 17import { VideoModel } from '../../../models/video/video'
18import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' 18import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
19import { VideoFilter } from '../../../../shared/models/videos/video-query.type' 19import { 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
7import { toArray } from '../../helpers/custom-validators/misc' 7import { toArray } from '../../helpers/custom-validators/misc'
8import { WEBSERVER } from '../../initializers/constants' 8import { WEBSERVER } from '../../initializers/constants'
9 9
10const 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
10const userSubscriptionAddValidator = [ 22const 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
65export { 77export {
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'
20import { FollowState } from '../../../shared/models/actors' 21import { FollowState } from '../../../shared/models/actors'
21import { ActorFollow } from '../../../shared/models/actors/follow.model' 22import { ActorFollow } from '../../../shared/models/actors/follow.model'
22import { logger } from '../../helpers/logger' 23import { logger } from '../../helpers/logger'
23import { ACTOR_FOLLOW_SCORE, FOLLOW_STATES, SERVER_ACTOR_NAME } from '../../initializers/constants' 24import { ACTOR_FOLLOW_SCORE, FOLLOW_STATES, SERVER_ACTOR_NAME } from '../../initializers/constants'
24import { ServerModel } from '../server/server' 25import { ServerModel } from '../server/server'
25import { createSafeIn, getFollowsSort, getSort } from '../utils' 26import { createSafeIn, getFollowsSort, getSort, searchAttribute } from '../utils'
26import { ActorModel, unusedActorAttributesForAPI } from './actor' 27import { ActorModel, unusedActorAttributesForAPI } from './actor'
27import { VideoChannelModel } from '../video/video-channel' 28import { VideoChannelModel } from '../video/video-channel'
28import { AccountModel } from '../account/account' 29import { 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 ]