aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models
diff options
context:
space:
mode:
Diffstat (limited to 'server/models')
-rw-r--r--server/models/utils.ts51
-rw-r--r--server/models/video/video-abuse.ts66
2 files changed, 113 insertions, 4 deletions
diff --git a/server/models/utils.ts b/server/models/utils.ts
index bdf2291f0..3e3825b32 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -219,6 +219,54 @@ function searchAttribute (sourceField, targetField) {
219 } 219 }
220} 220}
221 221
222interface QueryStringFilterPrefixes {
223 [key: string]: string | { prefix: string, handler: Function, multiple?: boolean }
224}
225
226function parseQueryStringFilter (q: string, prefixes: QueryStringFilterPrefixes) {
227 const tokens = q // tokenize only if we have a querystring
228 ? [].concat.apply([], q.split('"').map((v, i) => i % 2 ? v : v.split(' '))).filter(Boolean)
229 : []
230
231 // TODO: when Typescript supports Object.fromEntries, replace with the Object method
232 function fromEntries<T> (entries: [keyof T, T[keyof T]][]): T {
233 return entries.reduce(
234 (acc, [ key, value ]) => ({ ...acc, [key]: value }),
235 {} as T
236 )
237 }
238
239 const objectMap = (obj, fn) => fromEntries(
240 Object.entries(obj).map(
241 ([ k, v ], i) => [ k, fn(v, k, i) ]
242 )
243 )
244
245 return {
246 // search is the querystring minus defined filters
247 search: tokens.filter(e => !Object.values(prefixes).some(p => {
248 if (typeof p === "string") {
249 return e.startsWith(p)
250 } else {
251 return e.startsWith(p.prefix)
252 }
253 })).join(' '),
254 // filters defined in prefixes are added under their own name
255 ...objectMap(prefixes, v => {
256 if (typeof v === "string") {
257 return tokens.filter(e => e.startsWith(v)).map(e => e.slice(v.length))
258 } else {
259 const _tokens = tokens.filter(e => e.startsWith(v.prefix)).map(e => e.slice(v.prefix.length)).map(v.handler)
260 return !v.multiple
261 ? _tokens.length > 0
262 ? _tokens[0]
263 : ''
264 : _tokens
265 }
266 })
267 }
268}
269
222// --------------------------------------------------------------------------- 270// ---------------------------------------------------------------------------
223 271
224export { 272export {
@@ -241,7 +289,8 @@ export {
241 getFollowsSort, 289 getFollowsSort,
242 buildDirectionAndField, 290 buildDirectionAndField,
243 createSafeIn, 291 createSafeIn,
244 searchAttribute 292 searchAttribute,
293 parseQueryStringFilter
245} 294}
246 295
247// --------------------------------------------------------------------------- 296// ---------------------------------------------------------------------------
diff --git a/server/models/video/video-abuse.ts b/server/models/video/video-abuse.ts
index 628f1caa6..b1f8fed90 100644
--- a/server/models/video/video-abuse.ts
+++ b/server/models/video/video-abuse.ts
@@ -9,7 +9,7 @@ import {
9 isVideoAbuseStateValid 9 isVideoAbuseStateValid
10} from '../../helpers/custom-validators/video-abuses' 10} from '../../helpers/custom-validators/video-abuses'
11import { AccountModel } from '../account/account' 11import { AccountModel } from '../account/account'
12import { buildBlockedAccountSQL, getSort, throwIfNotValid, searchAttribute } from '../utils' 12import { buildBlockedAccountSQL, getSort, throwIfNotValid, searchAttribute, parseQueryStringFilter } from '../utils'
13import { VideoModel } from './video' 13import { VideoModel } from './video'
14import { VideoAbuseState, VideoDetails } from '../../../shared' 14import { VideoAbuseState, VideoDetails } from '../../../shared'
15import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants' 15import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
@@ -26,10 +26,17 @@ export enum ScopeNames {
26 26
27@Scopes(() => ({ 27@Scopes(() => ({
28 [ScopeNames.FOR_API]: (options: { 28 [ScopeNames.FOR_API]: (options: {
29 // search
29 search?: string 30 search?: string
30 searchReporter?: string 31 searchReporter?: string
32 searchReportee?: string
31 searchVideo?: string 33 searchVideo?: string
32 searchVideoChannel?: string 34 searchVideoChannel?: string
35 // filters
36 id?: number
37 state?: VideoAbuseState
38 is?: any
39 // accountIds
33 serverAccountId: number 40 serverAccountId: number
34 userAccountId: number 41 userAccountId: number
35 }) => { 42 }) => {
@@ -71,6 +78,24 @@ export enum ScopeNames {
71 }) 78 })
72 } 79 }
73 80
81 if (options.id) {
82 where = Object.assign(where, {
83 id: options.id
84 })
85 }
86
87 if (options.state) {
88 where = Object.assign(where, {
89 state: options.state
90 })
91 }
92
93 if (options.is) {
94 where = Object.assign(where, {
95 ...options.is
96 })
97 }
98
74 return { 99 return {
75 attributes: { 100 attributes: {
76 include: [ 101 include: [
@@ -167,7 +192,13 @@ export enum ScopeNames {
167 }, 192 },
168 { 193 {
169 model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }), 194 model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),
170 where: searchAttribute(options.searchVideoChannel, 'name') 195 where: searchAttribute(options.searchVideoChannel, 'name'),
196 include: [
197 {
198 model: AccountModel,
199 where: searchAttribute(options.searchReportee, 'name')
200 }
201 ]
171 }, 202 },
172 { 203 {
173 attributes: [ 'id', 'reason', 'unfederated' ], 204 attributes: [ 'id', 'reason', 'unfederated' ],
@@ -280,7 +311,36 @@ export class VideoAbuseModel extends Model<VideoAbuseModel> {
280 } 311 }
281 312
282 const filters = { 313 const filters = {
283 search, 314 ...parseQueryStringFilter(search, {
315 id: {
316 prefix: '#',
317 handler: v => v
318 },
319 state: {
320 prefix: 'state:',
321 handler: v => {
322 if (v === "accepted") return VideoAbuseState.ACCEPTED
323 if (v === "pending") return VideoAbuseState.PENDING
324 if (v === "rejected") return VideoAbuseState.REJECTED
325 return undefined
326 }
327 },
328 is: {
329 prefix: 'is:',
330 handler: v => {
331 if (v === "deleted") return { deletedVideo: { [Op.not]: null } }
332 return undefined
333 }
334 },
335 searchReporter: {
336 prefix: 'reporter:',
337 handler: v => v
338 },
339 searchReportee: {
340 prefix: 'reportee:',
341 handler: v => v
342 }
343 }),
284 serverAccountId, 344 serverAccountId,
285 userAccountId 345 userAccountId
286 } 346 }