aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html12
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts11
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html10
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts11
-rw-r--r--client/src/app/+admin/moderation/moderation.component.scss8
-rw-r--r--client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss8
-rw-r--r--client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html26
-rw-r--r--client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts12
-rw-r--r--client/src/app/shared/blocklist/blocklist.service.ts12
-rw-r--r--client/src/app/shared/video-blacklist/video-blacklist.service.ts14
-rw-r--r--server/controllers/api/server/server-blocklist.ts16
-rw-r--r--server/controllers/api/users/my-blocklist.ts16
-rw-r--r--server/controllers/api/videos/blacklist.ts8
-rw-r--r--server/middlewares/validators/videos/video-blacklist.ts4
-rw-r--r--server/models/account/account-blocklist.ts32
-rw-r--r--server/models/server/server-blocklist.ts17
-rw-r--r--server/models/utils.ts15
-rw-r--r--server/models/video/video-abuse.ts18
-rw-r--r--server/models/video/video-blacklist.ts13
19 files changed, 202 insertions, 61 deletions
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
index 6d77c8290..d340b5e57 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
@@ -1,9 +1,19 @@
1<p-table 1<p-table
2 [value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" 2 [value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" 3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate 4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate
5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts" 5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts"
6> 6>
7 <ng-template pTemplate="caption">
8 <div class="caption">
9 <div class="ml-auto">
10 <input
11 type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
12 (keyup)="onSearch($event)"
13 >
14 </div>
15 </div>
16 </ng-template>
7 17
8 <ng-template pTemplate="header"> 18 <ng-template pTemplate="header">
9 <tr> 19 <tr>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
index a3910177f..607b1cbe0 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
@@ -7,13 +7,14 @@ import { AccountBlock, BlocklistService } from '@app/shared/blocklist'
7 7
8@Component({ 8@Component({
9 selector: 'my-instance-account-blocklist', 9 selector: 'my-instance-account-blocklist',
10 styleUrls: [ './instance-account-blocklist.component.scss' ], 10 styleUrls: [ '../moderation.component.scss', './instance-account-blocklist.component.scss' ],
11 templateUrl: './instance-account-blocklist.component.html' 11 templateUrl: './instance-account-blocklist.component.html'
12}) 12})
13export class InstanceAccountBlocklistComponent extends RestTable implements OnInit { 13export class InstanceAccountBlocklistComponent extends RestTable implements OnInit {
14 blockedAccounts: AccountBlock[] = [] 14 blockedAccounts: AccountBlock[] = []
15 totalRecords = 0 15 totalRecords = 0
16 rowsPerPage = 10 16 rowsPerPageOptions = [ 20, 50, 100 ]
17 rowsPerPage = this.rowsPerPageOptions[0]
17 sort: SortMeta = { field: 'createdAt', order: -1 } 18 sort: SortMeta = { field: 'createdAt', order: -1 }
18 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
19 20
@@ -49,7 +50,11 @@ export class InstanceAccountBlocklistComponent extends RestTable implements OnIn
49 } 50 }
50 51
51 protected loadData () { 52 protected loadData () {
52 return this.blocklistService.getInstanceAccountBlocklist(this.pagination, this.sort) 53 return this.blocklistService.getInstanceAccountBlocklist({
54 pagination: this.pagination,
55 sort: this.sort,
56 search: this.search
57 })
53 .subscribe( 58 .subscribe(
54 resultList => { 59 resultList => {
55 this.blockedAccounts = resultList.data 60 this.blockedAccounts = resultList.data
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
index 19b33a0f5..b6c87fdc8 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
@@ -1,12 +1,18 @@
1<p-table 1<p-table
2 [value]="blockedServers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" 2 [value]="blockedServers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" 3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate 4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate
5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted instances" 5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted instances"
6> 6>
7 <ng-template pTemplate="caption"> 7 <ng-template pTemplate="caption">
8 <div class="caption"> 8 <div class="caption">
9 <a class="ml-auto block-button" (click)="addServersToBlock()" (key.enter)="addServersToBlock()"> 9 <div class="ml-auto">
10 <input
11 type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
12 (keyup)="onSearch($event)"
13 >
14 </div>
15 <a class="ml-2 block-button" (click)="addServersToBlock()" (key.enter)="addServersToBlock()">
10 <my-global-icon iconName="add"></my-global-icon> 16 <my-global-icon iconName="add"></my-global-icon>
11 <ng-container i18n>Mute domain</ng-container> 17 <ng-container i18n>Mute domain</ng-container>
12 </a> 18 </a>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
index 431729ef2..4efadc386 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
@@ -9,7 +9,7 @@ import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-doma
9 9
10@Component({ 10@Component({
11 selector: 'my-instance-server-blocklist', 11 selector: 'my-instance-server-blocklist',
12 styleUrls: [ './instance-server-blocklist.component.scss' ], 12 styleUrls: [ '../moderation.component.scss', './instance-server-blocklist.component.scss' ],
13 templateUrl: './instance-server-blocklist.component.html' 13 templateUrl: './instance-server-blocklist.component.html'
14}) 14})
15export class InstanceServerBlocklistComponent extends RestTable implements OnInit { 15export class InstanceServerBlocklistComponent extends RestTable implements OnInit {
@@ -17,7 +17,8 @@ export class InstanceServerBlocklistComponent extends RestTable implements OnIni
17 17
18 blockedServers: ServerBlock[] = [] 18 blockedServers: ServerBlock[] = []
19 totalRecords = 0 19 totalRecords = 0
20 rowsPerPage = 10 20 rowsPerPageOptions = [ 20, 50, 100 ]
21 rowsPerPage = this.rowsPerPageOptions[0]
21 sort: SortMeta = { field: 'createdAt', order: -1 } 22 sort: SortMeta = { field: 'createdAt', order: -1 }
22 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 23 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
23 24
@@ -72,7 +73,11 @@ export class InstanceServerBlocklistComponent extends RestTable implements OnIni
72 } 73 }
73 74
74 protected loadData () { 75 protected loadData () {
75 return this.blocklistService.getInstanceServerBlocklist(this.pagination, this.sort) 76 return this.blocklistService.getInstanceServerBlocklist({
77 pagination: this.pagination,
78 sort: this.sort,
79 search: this.search
80 })
76 .subscribe( 81 .subscribe(
77 resultList => { 82 resultList => {
78 this.blockedServers = resultList.data 83 this.blockedServers = resultList.data
diff --git a/client/src/app/+admin/moderation/moderation.component.scss b/client/src/app/+admin/moderation/moderation.component.scss
index a4ee65423..97af74541 100644
--- a/client/src/app/+admin/moderation/moderation.component.scss
+++ b/client/src/app/+admin/moderation/moderation.component.scss
@@ -7,6 +7,14 @@
7 margin-right: 30px; 7 margin-right: 30px;
8} 8}
9 9
10.caption {
11 justify-content: flex-end;
12
13 input {
14 @include peertube-input-text(250px);
15 }
16}
17
10.moderation-expanded { 18.moderation-expanded {
11 font-size: 90%; 19 font-size: 90%;
12 20
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss
index a9251e2f0..d6bc34935 100644
--- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss
+++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss
@@ -1,14 +1,6 @@
1@import 'mixins'; 1@import 'mixins';
2@import 'miniature'; 2@import 'miniature';
3 3
4.caption {
5 justify-content: flex-end;
6
7 input {
8 @include peertube-input-text(250px);
9 }
10}
11
12.video-details-date-updated { 4.video-details-date-updated {
13 font-size: 90%; 5 font-size: 90%;
14 margin-top: .1rem; 6 margin-top: .1rem;
diff --git a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html
index 90a786ad0..6375dacd9 100644
--- a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html
+++ b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html
@@ -1,9 +1,20 @@
1<p-table 1<p-table
2 [value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" 2 [value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" 3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate 4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate
5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blacklisted videos" 5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blacklisted videos"
6> 6>
7 <ng-template pTemplate="caption">
8 <div class="caption">
9 <div class="ml-auto">
10 <input
11 type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
12 (keyup)="onSearch($event)"
13 >
14 </div>
15 </div>
16 </ng-template>
17
7 <ng-template pTemplate="header"> 18 <ng-template pTemplate="header">
8 <tr> 19 <tr>
9 <th style="width: 40px"></th> 20 <th style="width: 40px"></th>
@@ -33,7 +44,7 @@
33 <div class="video-table-video-text"> 44 <div class="video-table-video-text">
34 <div> 45 <div>
35 {{ videoBlacklist.video.name }} 46 {{ videoBlacklist.video.name }}
36 <span class="glyphicon glyphicon-new-window"></span> 47 <span i18n-title title="Video was blacklisted" class="glyphicon glyphicon-ban-circle"></span>
37 </div> 48 </div>
38 <div class="text-muted">by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }} </div> 49 <div class="text-muted">by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }} </div>
39 </div> 50 </div>
@@ -53,7 +64,10 @@
53 </ng-container> 64 </ng-container>
54 65
55 <td class="action-cell"> 66 <td class="action-cell">
56 <my-action-dropdown i18n-label placement="bottom-right" label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"></my-action-dropdown> 67 <my-action-dropdown
68 [ngClass]="{ 'show': expanded }" placement="bottom-right" container="body"
69 i18n-label label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"
70 ></my-action-dropdown>
57 </td> 71 </td>
58 </tr> 72 </tr>
59 </ng-template> 73 </ng-template>
@@ -61,8 +75,10 @@
61 <ng-template pTemplate="rowexpansion" let-videoBlacklist> 75 <ng-template pTemplate="rowexpansion" let-videoBlacklist>
62 <tr> 76 <tr>
63 <td class="expand-cell" colspan="6"> 77 <td class="expand-cell" colspan="6">
64 <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span> 78 <div class="d-flex moderation-expanded">
65 <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span> 79 <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
80 <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
81 </div>
66 </td> 82 </td>
67 </tr> 83 </tr>
68 </ng-template> 84 </ng-template>
diff --git a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts
index c38d30865..e9925f9bf 100644
--- a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts
+++ b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts
@@ -17,7 +17,8 @@ import { MarkdownService } from '@app/shared/renderer'
17export class VideoBlacklistListComponent extends RestTable implements OnInit { 17export class VideoBlacklistListComponent extends RestTable implements OnInit {
18 blacklist: (VideoBlacklist & { reasonHtml?: string })[] = [] 18 blacklist: (VideoBlacklist & { reasonHtml?: string })[] = []
19 totalRecords = 0 19 totalRecords = 0
20 rowsPerPage = 10 20 rowsPerPageOptions = [ 20, 50, 100 ]
21 rowsPerPage = this.rowsPerPageOptions[0]
21 sort: SortMeta = { field: 'createdAt', order: -1 } 22 sort: SortMeta = { field: 'createdAt', order: -1 }
22 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 23 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
23 listBlacklistTypeFilter: VideoBlacklistType = undefined 24 listBlacklistTypeFilter: VideoBlacklistType = undefined
@@ -38,7 +39,7 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
38 ngOnInit () { 39 ngOnInit () {
39 this.serverService.getConfig() 40 this.serverService.getConfig()
40 .subscribe(config => { 41 .subscribe(config => {
41 // don't filter if auto-blacklist not enabled as this will be the only list 42 // don't filter if auto-blacklist is not enabled as this will be the only list
42 if (config.autoBlacklist.videos.ofUsers.enabled) { 43 if (config.autoBlacklist.videos.ofUsers.enabled) {
43 this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL 44 this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL
44 } 45 }
@@ -91,7 +92,12 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
91 } 92 }
92 93
93 protected loadData () { 94 protected loadData () {
94 this.videoBlacklistService.listBlacklist(this.pagination, this.sort, this.listBlacklistTypeFilter) 95 this.videoBlacklistService.listBlacklist({
96 pagination: this.pagination,
97 sort: this.sort,
98 search: this.search,
99 type: this.listBlacklistTypeFilter
100 })
95 .subscribe( 101 .subscribe(
96 async resultList => { 102 async resultList => {
97 this.totalRecords = resultList.total 103 this.totalRecords = resultList.total
diff --git a/client/src/app/shared/blocklist/blocklist.service.ts b/client/src/app/shared/blocklist/blocklist.service.ts
index c1f7312f0..5cf265bc1 100644
--- a/client/src/app/shared/blocklist/blocklist.service.ts
+++ b/client/src/app/shared/blocklist/blocklist.service.ts
@@ -76,10 +76,14 @@ export class BlocklistService {
76 76
77 /*********************** Instance -> Account blocklist ***********************/ 77 /*********************** Instance -> Account blocklist ***********************/
78 78
79 getInstanceAccountBlocklist (pagination: RestPagination, sort: SortMeta) { 79 getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) {
80 const { pagination, sort, search } = options
81
80 let params = new HttpParams() 82 let params = new HttpParams()
81 params = this.restService.addRestGetParams(params, pagination, sort) 83 params = this.restService.addRestGetParams(params, pagination, sort)
82 84
85 if (search) params = params.append('search', search)
86
83 return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts', { params }) 87 return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts', { params })
84 .pipe( 88 .pipe(
85 map(res => this.restExtractor.convertResultListDateToHuman(res)), 89 map(res => this.restExtractor.convertResultListDateToHuman(res)),
@@ -104,10 +108,14 @@ export class BlocklistService {
104 108
105 /*********************** Instance -> Server blocklist ***********************/ 109 /*********************** Instance -> Server blocklist ***********************/
106 110
107 getInstanceServerBlocklist (pagination: RestPagination, sort: SortMeta) { 111 getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) {
112 const { pagination, sort, search } = options
113
108 let params = new HttpParams() 114 let params = new HttpParams()
109 params = this.restService.addRestGetParams(params, pagination, sort) 115 params = this.restService.addRestGetParams(params, pagination, sort)
110 116
117 if (search) params = params.append('search', search)
118
111 return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/servers', { params }) 119 return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/servers', { params })
112 .pipe( 120 .pipe(
113 map(res => this.restExtractor.convertResultListDateToHuman(res)), 121 map(res => this.restExtractor.convertResultListDateToHuman(res)),
diff --git a/client/src/app/shared/video-blacklist/video-blacklist.service.ts b/client/src/app/shared/video-blacklist/video-blacklist.service.ts
index 116177c4a..c0e13a651 100644
--- a/client/src/app/shared/video-blacklist/video-blacklist.service.ts
+++ b/client/src/app/shared/video-blacklist/video-blacklist.service.ts
@@ -19,13 +19,19 @@ export class VideoBlacklistService {
19 private restExtractor: RestExtractor 19 private restExtractor: RestExtractor
20 ) {} 20 ) {}
21 21
22 listBlacklist (pagination: RestPagination, sort: SortMeta, type?: VideoBlacklistType): Observable<ResultList<VideoBlacklist>> { 22 listBlacklist (options: {
23 pagination: RestPagination,
24 sort: SortMeta,
25 search?: string
26 type?: VideoBlacklistType
27 }): Observable<ResultList<VideoBlacklist>> {
28 const { pagination, sort, search, type } = options
29
23 let params = new HttpParams() 30 let params = new HttpParams()
24 params = this.restService.addRestGetParams(params, pagination, sort) 31 params = this.restService.addRestGetParams(params, pagination, sort)
25 32
26 if (type) { 33 if (search) params = params.append('search', search)
27 params = params.set('type', type.toString()) 34 if (type) params = params.append('type', type.toString())
28 }
29 35
30 return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params }) 36 return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params })
31 .pipe( 37 .pipe(
diff --git a/server/controllers/api/server/server-blocklist.ts b/server/controllers/api/server/server-blocklist.ts
index d165db191..ffb7814fa 100644
--- a/server/controllers/api/server/server-blocklist.ts
+++ b/server/controllers/api/server/server-blocklist.ts
@@ -82,7 +82,13 @@ export {
82async function listBlockedAccounts (req: express.Request, res: express.Response) { 82async function listBlockedAccounts (req: express.Request, res: express.Response) {
83 const serverActor = await getServerActor() 83 const serverActor = await getServerActor()
84 84
85 const resultList = await AccountBlocklistModel.listForApi(serverActor.Account.id, req.query.start, req.query.count, req.query.sort) 85 const resultList = await AccountBlocklistModel.listForApi({
86 start: req.query.start,
87 count: req.query.count,
88 sort: req.query.sort,
89 search: req.query.search,
90 accountId: serverActor.Account.id
91 })
86 92
87 return res.json(getFormattedObjects(resultList.data, resultList.total)) 93 return res.json(getFormattedObjects(resultList.data, resultList.total))
88} 94}
@@ -107,7 +113,13 @@ async function unblockAccount (req: express.Request, res: express.Response) {
107async function listBlockedServers (req: express.Request, res: express.Response) { 113async function listBlockedServers (req: express.Request, res: express.Response) {
108 const serverActor = await getServerActor() 114 const serverActor = await getServerActor()
109 115
110 const resultList = await ServerBlocklistModel.listForApi(serverActor.Account.id, req.query.start, req.query.count, req.query.sort) 116 const resultList = await ServerBlocklistModel.listForApi({
117 start: req.query.start,
118 count: req.query.count,
119 sort: req.query.sort,
120 search: req.query.search,
121 accountId: serverActor.Account.id
122 })
111 123
112 return res.json(getFormattedObjects(resultList.data, resultList.total)) 124 return res.json(getFormattedObjects(resultList.data, resultList.total))
113} 125}
diff --git a/server/controllers/api/users/my-blocklist.ts b/server/controllers/api/users/my-blocklist.ts
index 713c16022..3a44376f2 100644
--- a/server/controllers/api/users/my-blocklist.ts
+++ b/server/controllers/api/users/my-blocklist.ts
@@ -74,7 +74,13 @@ export {
74async function listBlockedAccounts (req: express.Request, res: express.Response) { 74async function listBlockedAccounts (req: express.Request, res: express.Response) {
75 const user = res.locals.oauth.token.User 75 const user = res.locals.oauth.token.User
76 76
77 const resultList = await AccountBlocklistModel.listForApi(user.Account.id, req.query.start, req.query.count, req.query.sort) 77 const resultList = await AccountBlocklistModel.listForApi({
78 start: req.query.start,
79 count: req.query.count,
80 sort: req.query.sort,
81 search: req.query.search,
82 accountId: user.Account.id
83 })
78 84
79 return res.json(getFormattedObjects(resultList.data, resultList.total)) 85 return res.json(getFormattedObjects(resultList.data, resultList.total))
80} 86}
@@ -99,7 +105,13 @@ async function unblockAccount (req: express.Request, res: express.Response) {
99async function listBlockedServers (req: express.Request, res: express.Response) { 105async function listBlockedServers (req: express.Request, res: express.Response) {
100 const user = res.locals.oauth.token.User 106 const user = res.locals.oauth.token.User
101 107
102 const resultList = await ServerBlocklistModel.listForApi(user.Account.id, req.query.start, req.query.count, req.query.sort) 108 const resultList = await ServerBlocklistModel.listForApi({
109 start: req.query.start,
110 count: req.query.count,
111 sort: req.query.sort,
112 search: req.query.search,
113 accountId: user.Account.id
114 })
103 115
104 return res.json(getFormattedObjects(resultList.data, resultList.total)) 116 return res.json(getFormattedObjects(resultList.data, resultList.total))
105} 117}
diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts
index 2a667480d..c4aa79cd2 100644
--- a/server/controllers/api/videos/blacklist.ts
+++ b/server/controllers/api/videos/blacklist.ts
@@ -102,7 +102,13 @@ async function updateVideoBlacklistController (req: express.Request, res: expres
102} 102}
103 103
104async function listBlacklist (req: express.Request, res: express.Response) { 104async function listBlacklist (req: express.Request, res: express.Response) {
105 const resultList = await VideoBlacklistModel.listForApi(req.query.start, req.query.count, req.query.sort, req.query.type) 105 const resultList = await VideoBlacklistModel.listForApi({
106 start: req.query.start,
107 count: req.query.count,
108 sort: req.query.sort,
109 search: req.query.search,
110 type: req.query.type
111 })
106 112
107 return res.json(getFormattedObjects(resultList.data, resultList.total)) 113 return res.json(getFormattedObjects(resultList.data, resultList.total))
108} 114}
diff --git a/server/middlewares/validators/videos/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts
index 5440e57e7..4bd6a8333 100644
--- a/server/middlewares/validators/videos/video-blacklist.ts
+++ b/server/middlewares/validators/videos/video-blacklist.ts
@@ -69,6 +69,10 @@ const videosBlacklistFiltersValidator = [
69 query('type') 69 query('type')
70 .optional() 70 .optional()
71 .custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'), 71 .custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'),
72 query('search')
73 .optional()
74 .not()
75 .isEmpty().withMessage('Should have a valid search'),
72 76
73 (req: express.Request, res: express.Response, next: express.NextFunction) => { 77 (req: express.Request, res: express.Response, next: express.NextFunction) => {
74 logger.debug('Checking videos blacklist filters query', { parameters: req.query }) 78 logger.debug('Checking videos blacklist filters query', { parameters: req.query })
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts
index e2f66d733..fe2d5d010 100644
--- a/server/models/account/account-blocklist.ts
+++ b/server/models/account/account-blocklist.ts
@@ -1,6 +1,6 @@
1import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 1import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
2import { AccountModel } from './account' 2import { AccountModel } from './account'
3import { getSort } from '../utils' 3import { getSort, searchAttribute } from '../utils'
4import { AccountBlock } from '../../../shared/models/blocklist' 4import { AccountBlock } from '../../../shared/models/blocklist'
5import { Op } from 'sequelize' 5import { Op } from 'sequelize'
6import * as Bluebird from 'bluebird' 6import * as Bluebird from 'bluebird'
@@ -111,16 +111,36 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
111 return AccountBlocklistModel.findOne(query) 111 return AccountBlocklistModel.findOne(query)
112 } 112 }
113 113
114 static listForApi (accountId: number, start: number, count: number, sort: string) { 114 static listForApi (parameters: {
115 start: number
116 count: number
117 sort: string
118 search?: string
119 accountId: number
120 }) {
121 const { start, count, sort, search, accountId } = parameters
122
115 const query = { 123 const query = {
116 offset: start, 124 offset: start,
117 limit: count, 125 limit: count,
118 order: getSort(sort), 126 order: getSort(sort)
119 where: { 127 }
120 accountId 128
121 } 129 const where = {
130 accountId
122 } 131 }
123 132
133 if (search) {
134 Object.assign(where, {
135 [Op.or]: [
136 { ...searchAttribute(search, '$BlockedAccount.name$') },
137 { ...searchAttribute(search, '$BlockedAccount.Actor.url$') }
138 ]
139 })
140 }
141
142 Object.assign(query, { where })
143
124 return AccountBlocklistModel 144 return AccountBlocklistModel
125 .scope([ ScopeNames.WITH_ACCOUNTS ]) 145 .scope([ ScopeNames.WITH_ACCOUNTS ])
126 .findAndCountAll<MAccountBlocklistAccounts>(query) 146 .findAndCountAll<MAccountBlocklistAccounts>(query)
diff --git a/server/models/server/server-blocklist.ts b/server/models/server/server-blocklist.ts
index 883ae47ab..764203d2c 100644
--- a/server/models/server/server-blocklist.ts
+++ b/server/models/server/server-blocklist.ts
@@ -2,7 +2,7 @@ import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, Updated
2import { AccountModel } from '../account/account' 2import { AccountModel } from '../account/account'
3import { ServerModel } from './server' 3import { ServerModel } from './server'
4import { ServerBlock } from '../../../shared/models/blocklist' 4import { ServerBlock } from '../../../shared/models/blocklist'
5import { getSort } from '../utils' 5import { getSort, searchAttribute } from '../utils'
6import * as Bluebird from 'bluebird' 6import * as Bluebird from 'bluebird'
7import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/typings/models' 7import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/typings/models'
8import { Op } from 'sequelize' 8import { Op } from 'sequelize'
@@ -120,16 +120,27 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
120 return ServerBlocklistModel.findOne(query) 120 return ServerBlocklistModel.findOne(query)
121 } 121 }
122 122
123 static listForApi (accountId: number, start: number, count: number, sort: string) { 123 static listForApi (parameters: {
124 start: number
125 count: number
126 sort: string
127 search?: string
128 accountId: number
129 }) {
130 const { start, count, sort, search, accountId } = parameters
131
124 const query = { 132 const query = {
125 offset: start, 133 offset: start,
126 limit: count, 134 limit: count,
127 order: getSort(sort), 135 order: getSort(sort),
128 where: { 136 where: {
129 accountId 137 accountId,
138 ...searchAttribute(search, '$BlockedServer.host$')
130 } 139 }
131 } 140 }
132 141
142 console.log(search)
143
133 return ServerBlocklistModel 144 return ServerBlocklistModel
134 .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_SERVER ]) 145 .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_SERVER ])
135 .findAndCountAll<MServerBlocklistAccountServer>(query) 146 .findAndCountAll<MServerBlocklistAccountServer>(query)
diff --git a/server/models/utils.ts b/server/models/utils.ts
index 06ff05864..7137419a2 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -1,7 +1,7 @@
1import { Model, Sequelize } from 'sequelize-typescript' 1import { Model, Sequelize } from 'sequelize-typescript'
2import validator from 'validator' 2import validator from 'validator'
3import { Col } from 'sequelize/types/lib/utils' 3import { Col } from 'sequelize/types/lib/utils'
4import { literal, OrderItem } from 'sequelize' 4import { literal, OrderItem, Op } from 'sequelize'
5 5
6type Primitive = string | Function | number | boolean | Symbol | undefined | null 6type Primitive = string | Function | number | boolean | Symbol | undefined | null
7type DeepOmitHelper<T, K extends keyof T> = { 7type DeepOmitHelper<T, K extends keyof T> = {
@@ -207,6 +207,16 @@ function buildDirectionAndField (value: string) {
207 return { direction, field } 207 return { direction, field }
208} 208}
209 209
210function searchAttribute (sourceField, targetField) {
211 return sourceField
212 ? {
213 [targetField]: {
214 [Op.iLike]: `%${sourceField}%`
215 }
216 }
217 : {}
218}
219
210// --------------------------------------------------------------------------- 220// ---------------------------------------------------------------------------
211 221
212export { 222export {
@@ -228,7 +238,8 @@ export {
228 parseAggregateResult, 238 parseAggregateResult,
229 getFollowsSort, 239 getFollowsSort,
230 buildDirectionAndField, 240 buildDirectionAndField,
231 createSafeIn 241 createSafeIn,
242 searchAttribute
232} 243}
233 244
234// --------------------------------------------------------------------------- 245// ---------------------------------------------------------------------------
diff --git a/server/models/video/video-abuse.ts b/server/models/video/video-abuse.ts
index d68608ca6..e8c3bd823 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 } from '../utils' 12import { buildBlockedAccountSQL, getSort, throwIfNotValid, searchAttribute } 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'
@@ -17,8 +17,8 @@ import { MUserAccountId, MVideoAbuse, MVideoAbuseFormattable, MVideoAbuseVideo }
17import * as Bluebird from 'bluebird' 17import * as Bluebird from 'bluebird'
18import { literal, Op } from 'sequelize' 18import { literal, Op } from 'sequelize'
19import { ThumbnailModel } from './thumbnail' 19import { ThumbnailModel } from './thumbnail'
20import { VideoChannelModel } from './video-channel'
21import { VideoBlacklistModel } from './video-blacklist' 20import { VideoBlacklistModel } from './video-blacklist'
21import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
22 22
23export enum ScopeNames { 23export enum ScopeNames {
24 FOR_API = 'FOR_API' 24 FOR_API = 'FOR_API'
@@ -33,12 +33,6 @@ export enum ScopeNames {
33 serverAccountId: number 33 serverAccountId: number
34 userAccountId: any 34 userAccountId: any
35 }) => { 35 }) => {
36 const search = (sourceField, targetField) => sourceField ? ({
37 [targetField]: {
38 [Op.iLike]: `%${sourceField}%`
39 }
40 }) : {}
41
42 let where = { 36 let where = {
43 reporterAccountId: { 37 reporterAccountId: {
44 [Op.notIn]: literal('(' + buildBlockedAccountSQL(options.serverAccountId, options.userAccountId) + ')') 38 [Op.notIn]: literal('(' + buildBlockedAccountSQL(options.serverAccountId, options.userAccountId) + ')')
@@ -148,19 +142,19 @@ export enum ScopeNames {
148 { 142 {
149 model: AccountModel, 143 model: AccountModel,
150 required: true, 144 required: true,
151 where: { ...search(options.searchReporter, 'name') } 145 where: { ...searchAttribute(options.searchReporter, 'name') }
152 }, 146 },
153 { 147 {
154 model: VideoModel, 148 model: VideoModel,
155 required: false, 149 required: false,
156 where: { ...search(options.searchVideo, 'name') }, 150 where: { ...searchAttribute(options.searchVideo, 'name') },
157 include: [ 151 include: [
158 { 152 {
159 model: ThumbnailModel 153 model: ThumbnailModel
160 }, 154 },
161 { 155 {
162 model: VideoChannelModel.scope([ 'WITH_ACTOR', 'WITH_ACCOUNT' ]), 156 model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),
163 where: { ...search(options.searchVideoChannel, 'name') } 157 where: { ...searchAttribute(options.searchVideoChannel, 'name') }
164 }, 158 },
165 { 159 {
166 attributes: [ 'id', 'reason', 'unfederated' ], 160 attributes: [ 'id', 'reason', 'unfederated' ],
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts
index 694983cb3..680eba471 100644
--- a/server/models/video/video-blacklist.ts
+++ b/server/models/video/video-blacklist.ts
@@ -1,5 +1,5 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { getBlacklistSort, SortType, throwIfNotValid } from '../utils' 2import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '../utils'
3import { VideoModel } from './video' 3import { VideoModel } from './video'
4import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel' 4import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
5import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' 5import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
@@ -54,7 +54,15 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
54 }) 54 })
55 Video: VideoModel 55 Video: VideoModel
56 56
57 static listForApi (start: number, count: number, sort: SortType, type?: VideoBlacklistType) { 57 static listForApi (parameters: {
58 start: number
59 count: number
60 sort: SortType
61 search?: string
62 type?: VideoBlacklistType
63 }) {
64 const { start, count, sort, search, type } = parameters
65
58 function buildBaseQuery (): FindOptions { 66 function buildBaseQuery (): FindOptions {
59 return { 67 return {
60 offset: start, 68 offset: start,
@@ -70,6 +78,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
70 { 78 {
71 model: VideoModel, 79 model: VideoModel,
72 required: true, 80 required: true,
81 where: { ...searchAttribute(search, 'name') },
73 include: [ 82 include: [
74 { 83 {
75 model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }), 84 model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),