Add filter inputs for blacklisted videos and muted accounts/servers
authorRigel Kent <sendmemail@rigelk.eu>
Sun, 19 Apr 2020 12:11:40 +0000 (14:11 +0200)
committerRigel Kent <par@rigelk.eu>
Fri, 1 May 2020 14:41:02 +0000 (16:41 +0200)
19 files changed:
client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
client/src/app/+admin/moderation/moderation.component.scss
client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss
client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html
client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts
client/src/app/shared/blocklist/blocklist.service.ts
client/src/app/shared/video-blacklist/video-blacklist.service.ts
server/controllers/api/server/server-blocklist.ts
server/controllers/api/users/my-blocklist.ts
server/controllers/api/videos/blacklist.ts
server/middlewares/validators/videos/video-blacklist.ts
server/models/account/account-blocklist.ts
server/models/server/server-blocklist.ts
server/models/utils.ts
server/models/video/video-abuse.ts
server/models/video/video-blacklist.ts

index 6d77c8290fb1fb29c560363b73a9526d2bf563bd..d340b5e57296cf32de5b7bc7955423e75012612e 100644 (file)
@@ -1,9 +1,19 @@
 <p-table
-  [value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
+  [value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
   [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts"
 >
+  <ng-template pTemplate="caption">
+    <div class="caption">
+      <div class="ml-auto">
+        <input
+          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
+          (keyup)="onSearch($event)"
+        >
+      </div>
+    </div>
+  </ng-template>
 
   <ng-template pTemplate="header">
     <tr>
index a3910177f8f43cf440d07a0680f52025eb3bb48f..607b1cbe0f9fc08bcd56304839e8a2db7631020a 100644 (file)
@@ -7,13 +7,14 @@ import { AccountBlock, BlocklistService } from '@app/shared/blocklist'
 
 @Component({
   selector: 'my-instance-account-blocklist',
-  styleUrls: [ './instance-account-blocklist.component.scss' ],
+  styleUrls: [ '../moderation.component.scss', './instance-account-blocklist.component.scss' ],
   templateUrl: './instance-account-blocklist.component.html'
 })
 export class InstanceAccountBlocklistComponent extends RestTable implements OnInit {
   blockedAccounts: AccountBlock[] = []
   totalRecords = 0
-  rowsPerPage = 10
+  rowsPerPageOptions = [ 20, 50, 100 ]
+  rowsPerPage = this.rowsPerPageOptions[0]
   sort: SortMeta = { field: 'createdAt', order: -1 }
   pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
 
@@ -49,7 +50,11 @@ export class InstanceAccountBlocklistComponent extends RestTable implements OnIn
   }
 
   protected loadData () {
-    return this.blocklistService.getInstanceAccountBlocklist(this.pagination, this.sort)
+    return this.blocklistService.getInstanceAccountBlocklist({
+      pagination: this.pagination,
+      sort: this.sort,
+      search: this.search
+    })
       .subscribe(
         resultList => {
           this.blockedAccounts = resultList.data
index 19b33a0f50b0580d1ea7aa28b4ad27974282b42e..b6c87fdc8ffe3a28506592af561ca4f56768e826 100644 (file)
@@ -1,12 +1,18 @@
 <p-table
-  [value]="blockedServers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
+  [value]="blockedServers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
   [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted instances"
 >
   <ng-template pTemplate="caption">
     <div class="caption">
-      <a class="ml-auto block-button" (click)="addServersToBlock()" (key.enter)="addServersToBlock()">
+      <div class="ml-auto">
+        <input
+          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
+          (keyup)="onSearch($event)"
+        >
+      </div>
+      <a class="ml-2 block-button" (click)="addServersToBlock()" (key.enter)="addServersToBlock()">
         <my-global-icon iconName="add"></my-global-icon>
         <ng-container i18n>Mute domain</ng-container>
       </a>
index 431729ef2136655187c5ecb0eca144889fe1bc42..4efadc3861191ed60e6f817472cd6c84164f5ea4 100644 (file)
@@ -9,7 +9,7 @@ import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-doma
 
 @Component({
   selector: 'my-instance-server-blocklist',
-  styleUrls: [ './instance-server-blocklist.component.scss' ],
+  styleUrls: [ '../moderation.component.scss', './instance-server-blocklist.component.scss' ],
   templateUrl: './instance-server-blocklist.component.html'
 })
 export class InstanceServerBlocklistComponent extends RestTable implements OnInit {
@@ -17,7 +17,8 @@ export class InstanceServerBlocklistComponent extends RestTable implements OnIni
 
   blockedServers: ServerBlock[] = []
   totalRecords = 0
-  rowsPerPage = 10
+  rowsPerPageOptions = [ 20, 50, 100 ]
+  rowsPerPage = this.rowsPerPageOptions[0]
   sort: SortMeta = { field: 'createdAt', order: -1 }
   pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
 
@@ -72,7 +73,11 @@ export class InstanceServerBlocklistComponent extends RestTable implements OnIni
   }
 
   protected loadData () {
-    return this.blocklistService.getInstanceServerBlocklist(this.pagination, this.sort)
+    return this.blocklistService.getInstanceServerBlocklist({
+      pagination: this.pagination,
+      sort: this.sort,
+      search: this.search
+    })
       .subscribe(
         resultList => {
           this.blockedServers = resultList.data
index a4ee6542398d71089b77fc0ee55be5cde8861e1e..97af74541c952e597ac30ec03015982061173dcf 100644 (file)
@@ -7,6 +7,14 @@
   margin-right: 30px;
 }
 
+.caption {
+  justify-content: flex-end;
+
+  input {
+    @include peertube-input-text(250px);
+  }
+}
+
 .moderation-expanded {
   font-size: 90%;
 
index a9251e2f0750dbc6c550dda1ae6f6d7f9c326c33..d6bc34935c07251c7cc64389e79ff833e6a33881 100644 (file)
@@ -1,14 +1,6 @@
 @import 'mixins';
 @import 'miniature';
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-  }
-}
-
 .video-details-date-updated {
   font-size: 90%;
   margin-top: .1rem;
index 90a786ad01495f9749def51d06f77704b5bd779e..6375dacd9378dc6e2913bc3da06854ee1ee7c7c5 100644 (file)
@@ -1,9 +1,20 @@
 <p-table
-  [value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
+  [value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
   [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blacklisted videos"
 >
+  <ng-template pTemplate="caption">
+    <div class="caption">
+      <div class="ml-auto">
+        <input
+          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
+          (keyup)="onSearch($event)"
+        >
+      </div>
+    </div>
+  </ng-template>
+
   <ng-template pTemplate="header">
     <tr>
       <th style="width: 40px"></th>
@@ -33,7 +44,7 @@
             <div class="video-table-video-text">
               <div>
                 {{ videoBlacklist.video.name }}
-                <span class="glyphicon glyphicon-new-window"></span>
+                <span i18n-title title="Video was blacklisted" class="glyphicon glyphicon-ban-circle"></span>
               </div>
               <div class="text-muted">by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }} </div>
             </div>
       </ng-container>
 
       <td class="action-cell">
-        <my-action-dropdown i18n-label  placement="bottom-right" label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"></my-action-dropdown>
+        <my-action-dropdown
+          [ngClass]="{ 'show': expanded }" placement="bottom-right" container="body"
+          i18n-label label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"
+        ></my-action-dropdown>
       </td>
     </tr>
   </ng-template>
   <ng-template pTemplate="rowexpansion" let-videoBlacklist>
     <tr>
       <td class="expand-cell" colspan="6">
-        <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
-        <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
+        <div class="d-flex moderation-expanded">
+          <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
+          <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
+        </div>
       </td>
     </tr>
   </ng-template>
index c38d308653dcec50588b995826615531280efdb0..e9925f9bf421ac492681241a74d9691f8a6dedcc 100644 (file)
@@ -17,7 +17,8 @@ import { MarkdownService } from '@app/shared/renderer'
 export class VideoBlacklistListComponent extends RestTable implements OnInit {
   blacklist: (VideoBlacklist & { reasonHtml?: string })[] = []
   totalRecords = 0
-  rowsPerPage = 10
+  rowsPerPageOptions = [ 20, 50, 100 ]
+  rowsPerPage = this.rowsPerPageOptions[0]
   sort: SortMeta = { field: 'createdAt', order: -1 }
   pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
   listBlacklistTypeFilter: VideoBlacklistType = undefined
@@ -38,7 +39,7 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
   ngOnInit () {
     this.serverService.getConfig()
         .subscribe(config => {
-          // don't filter if auto-blacklist not enabled as this will be the only list
+          // don't filter if auto-blacklist is not enabled as this will be the only list
           if (config.autoBlacklist.videos.ofUsers.enabled) {
             this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL
           }
@@ -91,7 +92,12 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
   }
 
   protected loadData () {
-    this.videoBlacklistService.listBlacklist(this.pagination, this.sort, this.listBlacklistTypeFilter)
+    this.videoBlacklistService.listBlacklist({
+      pagination: this.pagination,
+      sort: this.sort,
+      search: this.search,
+      type: this.listBlacklistTypeFilter
+    })
       .subscribe(
         async resultList => {
           this.totalRecords = resultList.total
index c1f7312f0a0dc7d787007118e40ade727d13e778..5cf265bc1f3f22c7c224e705d3b66bc91801830b 100644 (file)
@@ -76,10 +76,14 @@ export class BlocklistService {
 
   /*********************** Instance -> Account blocklist ***********************/
 
-  getInstanceAccountBlocklist (pagination: RestPagination, sort: SortMeta) {
+  getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) {
+    const { pagination, sort, search } = options
+
     let params = new HttpParams()
     params = this.restService.addRestGetParams(params, pagination, sort)
 
+    if (search) params = params.append('search', search)
+
     return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts', { params })
                .pipe(
                  map(res => this.restExtractor.convertResultListDateToHuman(res)),
@@ -104,10 +108,14 @@ export class BlocklistService {
 
   /*********************** Instance -> Server blocklist ***********************/
 
-  getInstanceServerBlocklist (pagination: RestPagination, sort: SortMeta) {
+  getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) {
+    const { pagination, sort, search } = options
+
     let params = new HttpParams()
     params = this.restService.addRestGetParams(params, pagination, sort)
 
+    if (search) params = params.append('search', search)
+
     return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/servers', { params })
                .pipe(
                  map(res => this.restExtractor.convertResultListDateToHuman(res)),
index 116177c4a059e9cbe016a6d119d8a295b6a66107..c0e13a651a3468d0e581844e3577811835bd1bb5 100644 (file)
@@ -19,13 +19,19 @@ export class VideoBlacklistService {
     private restExtractor: RestExtractor
   ) {}
 
-  listBlacklist (pagination: RestPagination, sort: SortMeta, type?: VideoBlacklistType): Observable<ResultList<VideoBlacklist>> {
+  listBlacklist (options: {
+    pagination: RestPagination,
+    sort: SortMeta,
+    search?: string
+    type?: VideoBlacklistType
+  }): Observable<ResultList<VideoBlacklist>> {
+    const { pagination, sort, search, type } = options
+
     let params = new HttpParams()
     params = this.restService.addRestGetParams(params, pagination, sort)
 
-    if (type) {
-      params = params.set('type', type.toString())
-    }
+    if (search) params = params.append('search', search)
+    if (type) params = params.append('type', type.toString())
 
     return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params })
                .pipe(
index d165db19164fb3142237bebb4456f34bf4c4d3a6..ffb7814fa1d128d97d3ddef92d32fce97108a430 100644 (file)
@@ -82,7 +82,13 @@ export {
 async function listBlockedAccounts (req: express.Request, res: express.Response) {
   const serverActor = await getServerActor()
 
-  const resultList = await AccountBlocklistModel.listForApi(serverActor.Account.id, req.query.start, req.query.count, req.query.sort)
+  const resultList = await AccountBlocklistModel.listForApi({
+    start: req.query.start,
+    count: req.query.count,
+    sort: req.query.sort,
+    search: req.query.search,
+    accountId: serverActor.Account.id
+  })
 
   return res.json(getFormattedObjects(resultList.data, resultList.total))
 }
@@ -107,7 +113,13 @@ async function unblockAccount (req: express.Request, res: express.Response) {
 async function listBlockedServers (req: express.Request, res: express.Response) {
   const serverActor = await getServerActor()
 
-  const resultList = await ServerBlocklistModel.listForApi(serverActor.Account.id, req.query.start, req.query.count, req.query.sort)
+  const resultList = await ServerBlocklistModel.listForApi({
+    start: req.query.start,
+    count: req.query.count,
+    sort: req.query.sort,
+    search: req.query.search,
+    accountId: serverActor.Account.id
+  })
 
   return res.json(getFormattedObjects(resultList.data, resultList.total))
 }
index 713c16022322a25fed2a8ab09037fd1fd4cd02a4..3a44376f2d3424ac637b9dabf4ffe72476ed5003 100644 (file)
@@ -74,7 +74,13 @@ export {
 async function listBlockedAccounts (req: express.Request, res: express.Response) {
   const user = res.locals.oauth.token.User
 
-  const resultList = await AccountBlocklistModel.listForApi(user.Account.id, req.query.start, req.query.count, req.query.sort)
+  const resultList = await AccountBlocklistModel.listForApi({
+    start: req.query.start,
+    count: req.query.count,
+    sort: req.query.sort,
+    search: req.query.search,
+    accountId: user.Account.id
+  })
 
   return res.json(getFormattedObjects(resultList.data, resultList.total))
 }
@@ -99,7 +105,13 @@ async function unblockAccount (req: express.Request, res: express.Response) {
 async function listBlockedServers (req: express.Request, res: express.Response) {
   const user = res.locals.oauth.token.User
 
-  const resultList = await ServerBlocklistModel.listForApi(user.Account.id, req.query.start, req.query.count, req.query.sort)
+  const resultList = await ServerBlocklistModel.listForApi({
+    start: req.query.start,
+    count: req.query.count,
+    sort: req.query.sort,
+    search: req.query.search,
+    accountId: user.Account.id
+  })
 
   return res.json(getFormattedObjects(resultList.data, resultList.total))
 }
index 2a667480d468397438ec5e48d4f074ecafe13471..c4aa79cd21c20708a8931dbff17cb681c7ce369b 100644 (file)
@@ -102,7 +102,13 @@ async function updateVideoBlacklistController (req: express.Request, res: expres
 }
 
 async function listBlacklist (req: express.Request, res: express.Response) {
-  const resultList = await VideoBlacklistModel.listForApi(req.query.start, req.query.count, req.query.sort, req.query.type)
+  const resultList = await VideoBlacklistModel.listForApi({
+    start: req.query.start,
+    count: req.query.count,
+    sort: req.query.sort,
+    search: req.query.search,
+    type: req.query.type
+  })
 
   return res.json(getFormattedObjects(resultList.data, resultList.total))
 }
index 5440e57e7b9b870365a60bc9f3ec20acba1ffaf1..4bd6a8333dd8a81486e1294cee31d65335547a17 100644 (file)
@@ -69,6 +69,10 @@ const videosBlacklistFiltersValidator = [
   query('type')
     .optional()
     .custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'),
+  query('search')
+    .optional()
+    .not()
+    .isEmpty().withMessage('Should have a valid search'),
 
   (req: express.Request, res: express.Response, next: express.NextFunction) => {
     logger.debug('Checking videos blacklist filters query', { parameters: req.query })
index e2f66d733c514e444baa071b71e50e8da24a6664..fe2d5d010331147800195802408871c96448b0cf 100644 (file)
@@ -1,6 +1,6 @@
 import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
 import { AccountModel } from './account'
-import { getSort } from '../utils'
+import { getSort, searchAttribute } from '../utils'
 import { AccountBlock } from '../../../shared/models/blocklist'
 import { Op } from 'sequelize'
 import * as Bluebird from 'bluebird'
@@ -111,16 +111,36 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
     return AccountBlocklistModel.findOne(query)
   }
 
-  static listForApi (accountId: number, start: number, count: number, sort: string) {
+  static listForApi (parameters: {
+    start: number
+    count: number
+    sort: string
+    search?: string
+    accountId: number
+  }) {
+    const { start, count, sort, search, accountId } = parameters
+
     const query = {
       offset: start,
       limit: count,
-      order: getSort(sort),
-      where: {
-        accountId
-      }
+      order: getSort(sort)
+    }
+
+    const where = {
+      accountId
     }
 
+    if (search) {
+      Object.assign(where, {
+        [Op.or]: [
+          { ...searchAttribute(search, '$BlockedAccount.name$') },
+          { ...searchAttribute(search, '$BlockedAccount.Actor.url$') }
+        ]
+      })
+    }
+
+    Object.assign(query, { where })
+
     return AccountBlocklistModel
       .scope([ ScopeNames.WITH_ACCOUNTS ])
       .findAndCountAll<MAccountBlocklistAccounts>(query)
index 883ae47ab0c84e61d7d65299b3e1f386ba79d358..764203d2c47a62eba78c69e8126f26feeed5909a 100644 (file)
@@ -2,7 +2,7 @@ import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, Updated
 import { AccountModel } from '../account/account'
 import { ServerModel } from './server'
 import { ServerBlock } from '../../../shared/models/blocklist'
-import { getSort } from '../utils'
+import { getSort, searchAttribute } from '../utils'
 import * as Bluebird from 'bluebird'
 import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/typings/models'
 import { Op } from 'sequelize'
@@ -120,16 +120,27 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
     return ServerBlocklistModel.findOne(query)
   }
 
-  static listForApi (accountId: number, start: number, count: number, sort: string) {
+  static listForApi (parameters: {
+    start: number
+    count: number
+    sort: string
+    search?: string
+    accountId: number
+  }) {
+    const { start, count, sort, search, accountId } = parameters
+
     const query = {
       offset: start,
       limit: count,
       order: getSort(sort),
       where: {
-        accountId
+        accountId,
+        ...searchAttribute(search, '$BlockedServer.host$')
       }
     }
 
+    console.log(search)
+
     return ServerBlocklistModel
       .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_SERVER ])
       .findAndCountAll<MServerBlocklistAccountServer>(query)
index 06ff058649965d2f1e2d1a2c85ede33245ffe808..7137419a2e3d34b2543befb5e5d7012e162c06e1 100644 (file)
@@ -1,7 +1,7 @@
 import { Model, Sequelize } from 'sequelize-typescript'
 import validator from 'validator'
 import { Col } from 'sequelize/types/lib/utils'
-import { literal, OrderItem } from 'sequelize'
+import { literal, OrderItem, Op } from 'sequelize'
 
 type Primitive = string | Function | number | boolean | Symbol | undefined | null
 type DeepOmitHelper<T, K extends keyof T> = {
@@ -207,6 +207,16 @@ function buildDirectionAndField (value: string) {
   return { direction, field }
 }
 
+function searchAttribute (sourceField, targetField) {
+  return sourceField
+    ? {
+      [targetField]: {
+        [Op.iLike]: `%${sourceField}%`
+      }
+    }
+    : {}
+}
+
 // ---------------------------------------------------------------------------
 
 export {
@@ -228,7 +238,8 @@ export {
   parseAggregateResult,
   getFollowsSort,
   buildDirectionAndField,
-  createSafeIn
+  createSafeIn,
+  searchAttribute
 }
 
 // ---------------------------------------------------------------------------
index d68608ca668cc33a757c1d49b0a1b42b43db8803..e8c3bd8234be926693699c1474b98a514f537476 100644 (file)
@@ -9,7 +9,7 @@ import {
   isVideoAbuseStateValid
 } from '../../helpers/custom-validators/video-abuses'
 import { AccountModel } from '../account/account'
-import { buildBlockedAccountSQL, getSort, throwIfNotValid } from '../utils'
+import { buildBlockedAccountSQL, getSort, throwIfNotValid, searchAttribute } from '../utils'
 import { VideoModel } from './video'
 import { VideoAbuseState, VideoDetails } from '../../../shared'
 import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
@@ -17,8 +17,8 @@ import { MUserAccountId, MVideoAbuse, MVideoAbuseFormattable, MVideoAbuseVideo }
 import * as Bluebird from 'bluebird'
 import { literal, Op } from 'sequelize'
 import { ThumbnailModel } from './thumbnail'
-import { VideoChannelModel } from './video-channel'
 import { VideoBlacklistModel } from './video-blacklist'
+import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
 
 export enum ScopeNames {
   FOR_API = 'FOR_API'
@@ -33,12 +33,6 @@ export enum ScopeNames {
     serverAccountId: number
     userAccountId: any
   }) => {
-    const search = (sourceField, targetField) => sourceField ? ({
-      [targetField]: {
-        [Op.iLike]: `%${sourceField}%`
-      }
-    }) : {}
-
     let where = {
       reporterAccountId: {
         [Op.notIn]: literal('(' + buildBlockedAccountSQL(options.serverAccountId, options.userAccountId) + ')')
@@ -148,19 +142,19 @@ export enum ScopeNames {
         {
           model: AccountModel,
           required: true,
-          where: { ...search(options.searchReporter, 'name') }
+          where: { ...searchAttribute(options.searchReporter, 'name') }
         },
         {
           model: VideoModel,
           required: false,
-          where: { ...search(options.searchVideo, 'name') },
+          where: { ...searchAttribute(options.searchVideo, 'name') },
           include: [
             {
               model: ThumbnailModel
             },
             {
-              model: VideoChannelModel.scope([ 'WITH_ACTOR', 'WITH_ACCOUNT' ]),
-              where: { ...search(options.searchVideoChannel, 'name') }
+              model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),
+              where: { ...searchAttribute(options.searchVideoChannel, 'name') }
             },
             {
               attributes: [ 'id', 'reason', 'unfederated' ],
index 694983cb316a0d623a1aaddce51bb1f6f14b18dc..680eba471e5f693c55771115e9eb27a70adf4d87 100644 (file)
@@ -1,5 +1,5 @@
 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
-import { getBlacklistSort, SortType, throwIfNotValid } from '../utils'
+import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '../utils'
 import { VideoModel } from './video'
 import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
 import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
@@ -54,7 +54,15 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
   })
   Video: VideoModel
 
-  static listForApi (start: number, count: number, sort: SortType, type?: VideoBlacklistType) {
+  static listForApi (parameters: {
+    start: number
+    count: number
+    sort: SortType
+    search?: string
+    type?: VideoBlacklistType
+  }) {
+    const { start, count, sort, search, type } = parameters
+
     function buildBaseQuery (): FindOptions {
       return {
         offset: start,
@@ -70,6 +78,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
       {
         model: VideoModel,
         required: true,
+        where: { ...searchAttribute(search, 'name') },
         include: [
           {
             model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),