From: Rigel Kent Date: Tue, 2 Jun 2020 18:50:42 +0000 (+0200) Subject: rename blacklist to block/blocklist, merge block and auto-block views X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=5baee5fca418487e72ddcd6419d31bca8659b668;p=oweals%2Fpeertube.git rename blacklist to block/blocklist, merge block and auto-block views - also replace whitelist with allowlist - add advanced filters for video-block-list view - move icons in video-block-list and video-abuse-list to left side for visibility - add robot icon to depict automated nature of a block in video-block-list resolves #2790 --- diff --git a/client/src/app/+admin/admin.component.ts b/client/src/app/+admin/admin.component.ts index 9662522dc..4cf3da0e8 100644 --- a/client/src/app/+admin/admin.component.ts +++ b/client/src/app/+admin/admin.component.ts @@ -18,7 +18,7 @@ export class AdminComponent implements OnInit { ngOnInit () { if (this.hasUsersRight()) this.items.push({ label: this.i18n('Users'), routerLink: '/admin/users' }) if (this.hasServerFollowRight()) this.items.push({ label: this.i18n('Follows & redundancies'), routerLink: '/admin/follows' }) - if (this.hasVideoAbusesRight() || this.hasVideoBlacklistRight()) this.items.push({ label: this.i18n('Moderation'), routerLink: '/admin/moderation' }) + if (this.hasVideoAbusesRight() || this.hasVideoBlocklistRight()) this.items.push({ label: this.i18n('Moderation'), routerLink: '/admin/moderation' }) if (this.hasConfigRight()) this.items.push({ label: this.i18n('Configuration'), routerLink: '/admin/config' }) if (this.hasPluginsRight()) this.items.push({ label: this.i18n('Plugins/Themes'), routerLink: '/admin/plugins' }) if (this.hasJobsRight() || this.hasLogsRight() || this.hasDebugRight()) this.items.push({ label: this.i18n('System'), routerLink: '/admin/system' }) @@ -36,8 +36,8 @@ export class AdminComponent implements OnInit { return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES) } - hasVideoBlacklistRight () { - return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) + hasVideoBlocklistRight () { + return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLOCKS) } hasConfigRight () { diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts index d04313c0a..eb073f709 100644 --- a/client/src/app/+admin/admin.module.ts +++ b/client/src/app/+admin/admin.module.ts @@ -11,8 +11,7 @@ import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersCom import { ModerationCommentModalComponent, VideoAbuseListComponent, - VideoAutoBlacklistListComponent, - VideoBlacklistListComponent + VideoBlockListComponent } from './moderation' import { ModerationComponent } from '@app/+admin/moderation/moderation.component' import { RedundancyCheckboxComponent } from '@app/+admin/follows/shared/redundancy-checkbox.component' @@ -59,10 +58,9 @@ import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video- UserListComponent, ModerationComponent, - VideoBlacklistListComponent, + VideoBlockListComponent, VideoAbuseListComponent, VideoAbuseDetailsComponent, - VideoAutoBlacklistListComponent, ModerationCommentModalComponent, InstanceServerBlocklistComponent, InstanceAccountBlocklistComponent, diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html index 981b6685f..52c759fb7 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html @@ -430,7 +430,7 @@
Unless a user is marked as trusted, their videos will stay private until a moderator reviews them. @@ -671,16 +671,16 @@
- Instance whitelisted by Twitter + Instance allowed by Twitter - If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.
- If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.

+ If your instance is explicitly allowed by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.
+ If the instance is not, we use an image link card that will redirect on your PeerTube instance.

Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on https://cards-dev.twitter.com/validator - to see if you instance is whitelisted. + to see if you instance is allowed.
diff --git a/client/src/app/+admin/moderation/index.ts b/client/src/app/+admin/moderation/index.ts index 3c683a28c..e99244b74 100644 --- a/client/src/app/+admin/moderation/index.ts +++ b/client/src/app/+admin/moderation/index.ts @@ -1,5 +1,4 @@ export * from './video-abuse-list' -export * from './video-auto-blacklist-list' -export * from './video-blacklist-list' +export * from './video-block-list' export * from './moderation.component' export * from './moderation.routes' diff --git a/client/src/app/+admin/moderation/moderation.component.html b/client/src/app/+admin/moderation/moderation.component.html index b70027957..09f149c0e 100644 --- a/client/src/app/+admin/moderation/moderation.component.html +++ b/client/src/app/+admin/moderation/moderation.component.html @@ -2,11 +2,9 @@
Moderation
- Video abuses + Video reports - {{ autoBlacklistVideosEnabled ? 'Manually blacklisted videos' : 'Blacklisted videos' }} - - Auto-blacklisted videos + Video blocks Muted accounts diff --git a/client/src/app/+admin/moderation/moderation.component.ts b/client/src/app/+admin/moderation/moderation.component.ts index 7744deb06..d48305eed 100644 --- a/client/src/app/+admin/moderation/moderation.component.ts +++ b/client/src/app/+admin/moderation/moderation.component.ts @@ -7,7 +7,7 @@ import { AuthService, ServerService } from '@app/core' styleUrls: [ './moderation.component.scss' ] }) export class ModerationComponent implements OnInit { - autoBlacklistVideosEnabled = false + autoBlockVideosEnabled = false constructor ( private auth: AuthService, @@ -16,7 +16,7 @@ export class ModerationComponent implements OnInit { ngOnInit (): void { this.serverService.getConfig() - .subscribe(config => this.autoBlacklistVideosEnabled = config.autoBlacklist.videos.ofUsers.enabled) + .subscribe(config => this.autoBlockVideosEnabled = config.autoBlacklist.videos.ofUsers.enabled) } @@ -24,8 +24,8 @@ export class ModerationComponent implements OnInit { return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES) } - hasVideoBlacklistRight () { - return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) + hasVideoBlocklistRight () { + return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLOCKS) } hasAccountsBlocklistRight () { diff --git a/client/src/app/+admin/moderation/moderation.routes.ts b/client/src/app/+admin/moderation/moderation.routes.ts index a024f2bee..aeb555c4a 100644 --- a/client/src/app/+admin/moderation/moderation.routes.ts +++ b/client/src/app/+admin/moderation/moderation.routes.ts @@ -2,8 +2,7 @@ import { Routes } from '@angular/router' import { UserRight } from '../../../../../shared' import { UserRightGuard } from '@app/core' import { VideoAbuseListComponent } from '@app/+admin/moderation/video-abuse-list' -import { VideoBlacklistListComponent } from '@app/+admin/moderation/video-blacklist-list' -import { VideoAutoBlacklistListComponent } from '@app/+admin/moderation/video-auto-blacklist-list' +import { VideoBlockListComponent } from '@app/+admin/moderation/video-block-list' import { ModerationComponent } from '@app/+admin/moderation/moderation.component' import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from '@app/+admin/moderation/instance-blocklist' @@ -22,16 +21,6 @@ export const ModerationRoutes: Routes = [ redirectTo: 'video-abuses/list', pathMatch: 'full' }, - { - path: 'video-blacklist', - redirectTo: 'video-blacklist/list', - pathMatch: 'full' - }, - { - path: 'video-auto-blacklist', - redirectTo: 'video-auto-blacklist/list', - pathMatch: 'full' - }, { path: 'video-abuses/list', component: VideoAbuseListComponent, @@ -39,29 +28,38 @@ export const ModerationRoutes: Routes = [ data: { userRight: UserRight.MANAGE_VIDEO_ABUSES, meta: { - title: 'Video abuses list' + title: 'Video reports' } } }, + { + path: 'video-blacklist', + redirectTo: 'video-blocks/list', + pathMatch: 'full' + }, + { + path: 'video-auto-blacklist', + redirectTo: 'video-blocks/list', + pathMatch: 'full' + }, { path: 'video-auto-blacklist/list', - component: VideoAutoBlacklistListComponent, - canActivate: [ UserRightGuard ], - data: { - userRight: UserRight.MANAGE_VIDEO_BLACKLIST, - meta: { - title: 'Auto-blacklisted videos' - } - } + redirectTo: 'video-blocks/list', + pathMatch: 'full' + }, + { + path: 'video-blacklist', + redirectTo: 'video-blocks/list', + pathMatch: 'full' }, { - path: 'video-blacklist/list', - component: VideoBlacklistListComponent, + path: 'video-blocks/list', + component: VideoBlockListComponent, canActivate: [ UserRightGuard ], data: { - userRight: UserRight.MANAGE_VIDEO_BLACKLIST, + userRight: UserRight.MANAGE_VIDEO_BLOCKS, meta: { - title: 'Blacklisted videos' + title: 'Videos blocked' } } }, diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html index 2abcc0669..453a282d1 100644 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html @@ -69,7 +69,7 @@
The video was deleted - The video was blacklisted + The video was blocked
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html index d30475794..df15999ec 100644 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html @@ -19,7 +19,7 @@ Unsolved reports Accepted reports Refused reports - Reports with blacklisted videos + Reports with blocked videos Reports with deleted videos
@@ -84,9 +84,9 @@
- {{ videoAbuse.video.name }} - + + {{ videoAbuse.video.name }}
by {{ videoAbuse.video.channel?.displayName }} on {{ videoAbuse.video.channel?.host }}
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts index 39f619cc3..ca37bccf3 100644 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts @@ -3,7 +3,7 @@ import { Account } from '@app/shared/account/account.model' import { Notifier } from '@app/core' import { SortMeta } from 'primeng/api' import { VideoAbuse, VideoAbuseState } from '../../../../../../shared' -import { RestPagination, RestTable, VideoAbuseService, VideoBlacklistService } from '../../../shared' +import { RestPagination, RestTable, VideoAbuseService, VideoBlockService } from '../../../shared' import { I18n } from '@ngx-translate/i18n-polyfill' import { DropdownAction } from '../../../shared/buttons/action-dropdown.component' import { ConfirmService } from '../../../core/index' @@ -53,7 +53,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV private videoAbuseService: VideoAbuseService, private blocklistService: BlocklistService, private videoService: VideoService, - private videoBlacklistService: VideoBlacklistService, + private videoBlocklistService: VideoBlockService, private confirmService: ConfirmService, private i18n: I18n, private markdownRenderer: MarkdownService, @@ -101,13 +101,13 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV isDisplayed: videoAbuse => !videoAbuse.video.deleted }, { - label: this.i18n('Blacklist video'), + label: this.i18n('Block video'), isDisplayed: videoAbuse => !videoAbuse.video.deleted && !videoAbuse.video.blacklisted, handler: videoAbuse => { - this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true) + this.videoBlocklistService.blockVideo(videoAbuse.video.id, undefined, true) .subscribe( () => { - this.notifier.success(this.i18n('Video blacklisted.')) + this.notifier.success(this.i18n('Video blocklisted.')) this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) }, @@ -117,13 +117,13 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV } }, { - label: this.i18n('Unblacklist video'), + label: this.i18n('Unblock video'), isDisplayed: videoAbuse => !videoAbuse.video.deleted && videoAbuse.video.blacklisted, handler: videoAbuse => { - this.videoBlacklistService.removeVideoFromBlacklist(videoAbuse.video.id) + this.videoBlocklistService.unblockVideo(videoAbuse.video.id) .subscribe( () => { - this.notifier.success(this.i18n('Video unblacklisted.')) + this.notifier.success(this.i18n('Video unblocklisted.')) this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) }, @@ -292,7 +292,6 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV err => this.notifier.error(err.message) ) - } protected loadData () { diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/index.ts b/client/src/app/+admin/moderation/video-auto-blacklist-list/index.ts deleted file mode 100644 index e3522f68c..000000000 --- a/client/src/app/+admin/moderation/video-auto-blacklist-list/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './video-auto-blacklist-list.component' diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.html b/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.html deleted file mode 100644 index e2193b630..000000000 --- a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Unblacklist - - - - - - - - diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.scss b/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.scss deleted file mode 100644 index 85ebc6041..000000000 --- a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -.action-button-unblacklist-selection { - display: inline-block; - - @include peertube-button; - @include orange-button; - @include button-with-icon(21px); - - my-global-icon { - @include apply-svg-color(#fff); - } -} diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.ts b/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.ts deleted file mode 100644 index fb2962b47..000000000 --- a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Component } from '@angular/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { ActivatedRoute, Router } from '@angular/router' -import { ComponentPagination } from '@app/shared/rest/component-pagination.model' -import { AuthService, Notifier, ServerService } from '@app/core' -import { VideoBlacklistService } from '@app/shared' -import { immutableAssign } from '@app/shared/misc/utils' -import { ScreenService } from '@app/shared/misc/screen.service' -import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component' -import { SelectionType } from '@app/shared/video/videos-selection.component' -import { Video } from '@app/shared/video/video.model' - -@Component({ - selector: 'my-video-auto-blacklist-list', - templateUrl: './video-auto-blacklist-list.component.html', - styleUrls: [ './video-auto-blacklist-list.component.scss' ] -}) -export class VideoAutoBlacklistListComponent { - titlePage: string - selection: SelectionType = {} - miniatureDisplayOptions: MiniatureDisplayOptions = { - date: true, - views: false, - by: true, - privacyLabel: false, - privacyText: true, - state: false, - blacklistInfo: false, - nsfw: true - } - pagination: ComponentPagination = { - currentPage: 1, - itemsPerPage: 5, - totalItems: null - } - videos: Video[] = [] - getVideosObservableFunction = this.getVideosObservable.bind(this) - - constructor ( - protected router: Router, - protected route: ActivatedRoute, - protected notifier: Notifier, - protected authService: AuthService, - protected screenService: ScreenService, - protected serverService: ServerService, - private i18n: I18n, - private videoBlacklistService: VideoBlacklistService - ) { - this.titlePage = this.i18n('Auto-blacklisted videos') - } - - getVideosObservable (page: number) { - const newPagination = immutableAssign(this.pagination, { currentPage: page }) - - return this.videoBlacklistService.getAutoBlacklistedAsVideoList(newPagination) - } - - removeVideoFromBlacklist (entry: Video) { - this.videoBlacklistService.removeVideoFromBlacklist(entry.id).subscribe( - () => { - this.notifier.success(this.i18n('Video {{name}} removed from blacklist.', { name: entry.name })) - - this.videos = this.videos.filter(v => v.id !== entry.id) - }, - - error => this.notifier.error(error.message) - ) - } - - removeSelectedVideosFromBlacklist () { - const toReleaseVideosIds = Object.keys(this.selection) - .filter(k => this.selection[ k ] === true) - .map(k => parseInt(k, 10)) - - this.videoBlacklistService.removeVideoFromBlacklist(toReleaseVideosIds).subscribe( - () => { - this.notifier.success(this.i18n('{{num}} videos removed from blacklist.', { num: toReleaseVideosIds.length })) - - this.selection = {} - this.videos = this.videos.filter(v => toReleaseVideosIds.includes(v.id) === false) - }, - - error => this.notifier.error(error.message) - ) - } -} diff --git a/client/src/app/+admin/moderation/video-blacklist-list/index.ts b/client/src/app/+admin/moderation/video-blacklist-list/index.ts deleted file mode 100644 index 4daf64187..000000000 --- a/client/src/app/+admin/moderation/video-blacklist-list/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './video-blacklist-list.component' 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 deleted file mode 100644 index cfa04514f..000000000 --- a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html +++ /dev/null @@ -1,100 +0,0 @@ - - -
-
- - - Clear filters -
-
-
- - - - - Video - Sensitive - Unfederated - Date - - - - - - - - - - - - - - - -
-
- -
-
-
- {{ videoBlacklist.video.name }} - -
-
by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }}
-
-
-
- - - - {{ booleanToText(videoBlacklist.video.nsfw) }} - {{ booleanToText(videoBlacklist.unfederated) }} - {{ videoBlacklist.createdAt | date: 'short' }} - - - {{ booleanToText(videoBlacklist.video.nsfw) }} - {{ booleanToText(videoBlacklist.unfederated) }} - {{ videoBlacklist.createdAt | date: 'short' }} - - - - - - -
- - - - -
- Blacklist reason: - -
- - -
- - - - -
- No blacklisted video found matching current filters. - No blacklisted video found. -
- - -
-
- 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 deleted file mode 100644 index 63ecdeb9f..000000000 --- a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Component, OnInit } from '@angular/core' -import { SortMeta } from 'primeng/api' -import { Notifier, ServerService } from '@app/core' -import { ConfirmService } from '../../../core' -import { RestPagination, RestTable, VideoBlacklistService } from '../../../shared' -import { VideoBlacklist, VideoBlacklistType } from '../../../../../../shared' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { DropdownAction } from '../../../shared/buttons/action-dropdown.component' -import { Video } from '../../../shared/video/video.model' -import { MarkdownService } from '@app/shared/renderer' - -@Component({ - selector: 'my-video-blacklist-list', - templateUrl: './video-blacklist-list.component.html', - styleUrls: [ '../moderation.component.scss' ] -}) -export class VideoBlacklistListComponent extends RestTable implements OnInit { - blacklist: (VideoBlacklist & { reasonHtml?: string })[] = [] - totalRecords = 0 - sort: SortMeta = { field: 'createdAt', order: -1 } - pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - listBlacklistTypeFilter: VideoBlacklistType = undefined - - videoBlacklistActions: DropdownAction[] = [] - - constructor ( - private notifier: Notifier, - private serverService: ServerService, - private confirmService: ConfirmService, - private videoBlacklistService: VideoBlacklistService, - private markdownRenderer: MarkdownService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.serverService.getConfig() - .subscribe(config => { - // 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 - } - }) - - this.initialize() - - this.videoBlacklistActions = [ - { - label: this.i18n('Unblacklist'), - handler: videoBlacklist => this.removeVideoFromBlacklist(videoBlacklist) - } - ] - } - - getIdentifier () { - return 'VideoBlacklistListComponent' - } - - getVideoUrl (videoBlacklist: VideoBlacklist) { - return Video.buildClientUrl(videoBlacklist.video.uuid) - } - - booleanToText (value: boolean) { - if (value === true) return this.i18n('yes') - - return this.i18n('no') - } - - toHtml (text: string) { - return this.markdownRenderer.textMarkdownToHTML(text) - } - - async removeVideoFromBlacklist (entry: VideoBlacklist) { - const confirmMessage = this.i18n( - 'Do you really want to remove this video from the blacklist? It will be available again in the videos list.' - ) - - const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblacklist')) - if (res === false) return - - this.videoBlacklistService.removeVideoFromBlacklist(entry.video.id).subscribe( - () => { - this.notifier.success(this.i18n('Video {{name}} removed from the blacklist.', { name: entry.video.name })) - this.loadData() - }, - - err => this.notifier.error(err.message) - ) - } - - protected loadData () { - this.videoBlacklistService.listBlacklist({ - pagination: this.pagination, - sort: this.sort, - search: this.search, - type: this.listBlacklistTypeFilter - }) - .subscribe( - async resultList => { - this.totalRecords = resultList.total - - this.blacklist = resultList.data - - for (const element of this.blacklist) { - Object.assign(element, { reasonHtml: await this.toHtml(element.reason) }) - } - }, - - err => this.notifier.error(err.message) - ) - } -} diff --git a/client/src/app/+admin/moderation/video-block-list/index.ts b/client/src/app/+admin/moderation/video-block-list/index.ts new file mode 100644 index 000000000..ec4de8f62 --- /dev/null +++ b/client/src/app/+admin/moderation/video-block-list/index.ts @@ -0,0 +1 @@ +export * from './video-block-list.component' diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html new file mode 100644 index 000000000..f3ec37314 --- /dev/null +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html @@ -0,0 +1,113 @@ + + +
+
+
+
+
+ +
+ +
+ + Automatic blocks + Manual blocks +
+
+ + + Clear filters +
+
+
+
+ + + + + Video + Sensitive + Unfederated + Date + + + + + + + + + + + + + + + +
+
+ +
+
+
+ + {{ videoBlock.video.name }} +
+
by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }}
+
+
+
+ + + + {{ booleanToText(videoBlock.video.nsfw) }} + {{ booleanToText(videoBlock.unfederated) }} + {{ videoBlock.createdAt | date: 'short' }} + + + {{ booleanToText(videoBlock.video.nsfw) }} + {{ booleanToText(videoBlock.unfederated) }} + {{ videoBlock.createdAt | date: 'short' }} + + + + + + +
+ + + + +
+ Block reason: + +
+ + +
+ + + + +
+ No blocked video found matching current filters. + No blocked video found. +
+ + +
+
+ diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss new file mode 100644 index 000000000..43a365608 --- /dev/null +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss @@ -0,0 +1,18 @@ +@import 'mixins'; + +my-global-icon { + @include apply-svg-color(#7d7d7d); + + width: 12px; + height: 12px; + position: relative; + top: -1px; +} + +.input-group { + @include peertube-input-group(300px); + + .dropdown-toggle::after { + margin-left: 0; + } +} diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts new file mode 100644 index 000000000..e72ab5348 --- /dev/null +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts @@ -0,0 +1,196 @@ +import { Component, OnInit } from '@angular/core' +import { SortMeta } from 'primeng/api' +import { Notifier, ServerService } from '@app/core' +import { ConfirmService } from '../../../core' +import { RestPagination, RestTable, VideoBlockService } from '../../../shared' +import { VideoBlocklist, VideoBlockType } from '../../../../../../shared' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { DropdownAction } from '../../../shared/buttons/action-dropdown.component' +import { Video } from '../../../shared/video/video.model' +import { MarkdownService } from '@app/shared/renderer' +import { Params, ActivatedRoute, Router } from '@angular/router' +import { filter, switchMap } from 'rxjs/operators' +import { VideoService } from '@app/shared/video/video.service' + +@Component({ + selector: 'my-video-block-list', + templateUrl: './video-block-list.component.html', + styleUrls: [ '../moderation.component.scss', './video-block-list.component.scss' ] +}) +export class VideoBlockListComponent extends RestTable implements OnInit { + blocklist: (VideoBlocklist & { reasonHtml?: string })[] = [] + totalRecords = 0 + sort: SortMeta = { field: 'createdAt', order: -1 } + pagination: RestPagination = { count: this.rowsPerPage, start: 0 } + listBlockTypeFilter: VideoBlockType = undefined + + videoBlocklistActions: DropdownAction[][] = [] + + constructor ( + private notifier: Notifier, + private serverService: ServerService, + private confirmService: ConfirmService, + private videoBlocklistService: VideoBlockService, + private markdownRenderer: MarkdownService, + private videoService: VideoService, + private route: ActivatedRoute, + private router: Router, + private i18n: I18n + ) { + super() + + this.videoBlocklistActions = [ + [ + { + label: this.i18n('Internal actions'), + isHeader: true + }, + { + label: this.i18n('Switch video block to manual'), + handler: videoBlock => { + this.videoBlocklistService.unblockVideo(videoBlock.video.id).pipe( + switchMap(_ => this.videoBlocklistService.blockVideo(videoBlock.video.id, undefined, true)) + ).subscribe( + () => { + this.notifier.success(this.i18n('Video {{name}} switched to manual block.', { name: videoBlock.video.name })) + this.loadData() + }, + + err => this.notifier.error(err.message) + ) + } + } + ], + [ + { + label: this.i18n('Actions for the video'), + isHeader: true, + }, + { + label: this.i18n('Unblock video'), + handler: videoBlock => this.unblockVideo(videoBlock) + }, + + { + label: this.i18n('Delete video'), + handler: async videoBlock => { + const res = await this.confirmService.confirm( + this.i18n('Do you really want to delete this video?'), + this.i18n('Delete') + ) + if (res === false) return + + this.videoService.removeVideo(videoBlock.video.id) + .subscribe( + () => { + this.notifier.success(this.i18n('Video deleted.')) + }, + + err => this.notifier.error(err.message) + ) + } + } + ] + ] + } + + ngOnInit () { + this.serverService.getConfig() + .subscribe(config => { + // don't filter if auto-blacklist is not enabled as this will be the only list + if (config.autoBlacklist.videos.ofUsers.enabled) { + this.listBlockTypeFilter = VideoBlockType.MANUAL + } + }) + + this.initialize() + + this.route.queryParams + .pipe(filter(params => params.search !== undefined && params.search !== null)) + .subscribe(params => { + this.search = params.search + this.setTableFilter(params.search) + this.loadData() + }) + } + + ngAfterViewInit () { + if (this.search) this.setTableFilter(this.search) + } + + /* Table filter functions */ + onBlockSearch (event: Event) { + this.onSearch(event) + this.setQueryParams((event.target as HTMLInputElement).value) + } + + setQueryParams (search: string) { + const queryParams: Params = {} + if (search) Object.assign(queryParams, { search }) + this.router.navigate([ '/admin/moderation/video-blocks/list' ], { queryParams }) + } + + resetTableFilter () { + this.setTableFilter('') + this.setQueryParams('') + this.resetSearch() + } + /* END Table filter functions */ + + getIdentifier () { + return 'VideoBlockListComponent' + } + + getVideoUrl (videoBlock: VideoBlocklist) { + return Video.buildClientUrl(videoBlock.video.uuid) + } + + booleanToText (value: boolean) { + if (value === true) return this.i18n('yes') + + return this.i18n('no') + } + + toHtml (text: string) { + return this.markdownRenderer.textMarkdownToHTML(text) + } + + async unblockVideo (entry: VideoBlocklist) { + const confirmMessage = this.i18n( + 'Do you really want to unblock this video? It will be available again in the videos list.' + ) + + const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock')) + if (res === false) return + + this.videoBlocklistService.unblockVideo(entry.video.id).subscribe( + () => { + this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: entry.video.name })) + this.loadData() + }, + + err => this.notifier.error(err.message) + ) + } + + protected loadData () { + this.videoBlocklistService.listBlocks({ + pagination: this.pagination, + sort: this.sort, + search: this.search, + }) + .subscribe( + async resultList => { + this.totalRecords = resultList.total + + this.blocklist = resultList.data + + for (const element of this.blocklist) { + Object.assign(element, { reasonHtml: await this.toHtml(element.reason) }) + } + }, + + err => this.notifier.error(err.message) + ) + } +} diff --git a/client/src/app/+admin/users/user-edit/user-edit.ts b/client/src/app/+admin/users/user-edit/user-edit.ts index 6e2952c44..98249bcc1 100644 --- a/client/src/app/+admin/users/user-edit/user-edit.ts +++ b/client/src/app/+admin/users/user-edit/user-edit.ts @@ -88,7 +88,7 @@ export abstract class UserEdit extends FormReactive implements OnInit { } protected buildAdminFlags (formValue: any) { - return formValue.byPassAutoBlacklist ? UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST : UserAdminFlag.NONE + return formValue.byPassAutoBlacklist ? UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK : UserAdminFlag.NONE } protected buildQuotaOptions () { diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts index e0e1fbddf..f2bd8c8ec 100644 --- a/client/src/app/+admin/users/user-edit/user-update.component.ts +++ b/client/src/app/+admin/users/user-edit/user-update.component.ts @@ -125,7 +125,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy { role: userJson.role.toString(), videoQuota: userJson.videoQuota, videoQuotaDaily: userJson.videoQuotaDaily, - byPassAutoBlacklist: userJson.adminFlags & UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST + byPassAutoBlacklist: userJson.adminFlags & UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK }) } } diff --git a/client/src/app/+my-account/my-account-history/my-account-history.component.html b/client/src/app/+my-account/my-account-history/my-account-history.component.html index d3a329e8f..817b929fe 100644 --- a/client/src/app/+my-account/my-account-history/my-account-history.component.html +++ b/client/src/app/+my-account/my-account-history/my-account-history.component.html @@ -17,6 +17,6 @@
+ (videoRemoved)="removeVideoFromArray(video)" (videoBlocked)="removeVideoFromArray(video)">
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts index 6ba1a1020..72e26ac28 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts @@ -35,8 +35,8 @@ export class MyAccountNotificationPreferencesComponent implements OnInit { newVideoFromSubscription: this.i18n('New video from your subscriptions'), newCommentOnMyVideo: this.i18n('New comment on your video'), videoAbuseAsModerator: this.i18n('New video abuse'), - videoAutoBlacklistAsModerator: this.i18n('Video auto-blacklisted waiting review'), - blacklistOnMyVideo: this.i18n('One of your video is blacklisted/unblacklisted'), + videoAutoBlacklistAsModerator: this.i18n('Video blocked automatically waiting review'), + blacklistOnMyVideo: this.i18n('One of your video is blocked/unblocked'), myVideoPublished: this.i18n('Video published (after transcoding/scheduled update)'), myVideoImportFinished: this.i18n('Video import finished'), newUserRegistration: this.i18n('A new user registered on your instance'), @@ -49,7 +49,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit { this.rightNotifications = { videoAbuseAsModerator: UserRight.MANAGE_VIDEO_ABUSES, - videoAutoBlacklistAsModerator: UserRight.MANAGE_VIDEO_BLACKLIST, + videoAutoBlacklistAsModerator: UserRight.MANAGE_VIDEO_BLOCKS, newUserRegistration: UserRight.MANAGE_USERS, newInstanceFollower: UserRight.MANAGE_SERVER_FOLLOW, autoInstanceFollowing: UserRight.MANAGE_CONFIGURATION diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index 015c14bce..79bf29e9c 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts @@ -33,7 +33,7 @@ export class MenuComponent implements OnInit { [UserRight.MANAGE_USERS]: '/admin/users', [UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends', [UserRight.MANAGE_VIDEO_ABUSES]: '/admin/moderation/video-abuses', - [UserRight.MANAGE_VIDEO_BLACKLIST]: '/admin/moderation/video-blacklist', + [UserRight.MANAGE_VIDEO_BLOCKS]: '/admin/moderation/video-blocks', [UserRight.MANAGE_JOBS]: '/admin/jobs', [UserRight.MANAGE_CONFIGURATION]: '/admin/config' } @@ -131,7 +131,7 @@ export class MenuComponent implements OnInit { UserRight.MANAGE_USERS, UserRight.MANAGE_SERVER_FOLLOW, UserRight.MANAGE_VIDEO_ABUSES, - UserRight.MANAGE_VIDEO_BLACKLIST, + UserRight.MANAGE_VIDEO_BLOCKS, UserRight.MANAGE_JOBS, UserRight.MANAGE_CONFIGURATION ] diff --git a/client/src/app/search/search.component.html b/client/src/app/search/search.component.html index 3cafc676d..d723606db 100644 --- a/client/src/app/search/search.component.html +++ b/client/src/app/search/search.component.html @@ -55,7 +55,7 @@ diff --git a/client/src/app/shared/forms/form-validators/index.ts b/client/src/app/shared/forms/form-validators/index.ts index e3de3ae13..4a01b1622 100644 --- a/client/src/app/shared/forms/form-validators/index.ts +++ b/client/src/app/shared/forms/form-validators/index.ts @@ -6,7 +6,7 @@ export * from './login-validators.service' export * from './reset-password-validators.service' export * from './user-validators.service' export * from './video-abuse-validators.service' -export * from './video-blacklist-validators.service' +export * from './video-block-validators.service' export * from './video-channel-validators.service' export * from './video-comment-validators.service' export * from './video-validators.service' diff --git a/client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts b/client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts deleted file mode 100644 index 07d1f264a..000000000 --- a/client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { I18n } from '@ngx-translate/i18n-polyfill' -import { Validators } from '@angular/forms' -import { Injectable } from '@angular/core' -import { BuildFormValidator } from '@app/shared' - -@Injectable() -export class VideoBlacklistValidatorsService { - readonly VIDEO_BLACKLIST_REASON: BuildFormValidator - - constructor (private i18n: I18n) { - this.VIDEO_BLACKLIST_REASON = { - VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ], - MESSAGES: { - 'minlength': this.i18n('Blacklist reason must be at least 2 characters long.'), - 'maxlength': this.i18n('Blacklist reason cannot be more than 300 characters long.') - } - } - } -} diff --git a/client/src/app/shared/forms/form-validators/video-block-validators.service.ts b/client/src/app/shared/forms/form-validators/video-block-validators.service.ts new file mode 100644 index 000000000..dc8257761 --- /dev/null +++ b/client/src/app/shared/forms/form-validators/video-block-validators.service.ts @@ -0,0 +1,19 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from '@app/shared' + +@Injectable() +export class VideoBlockValidatorsService { + readonly VIDEO_BLOCK_REASON: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_BLOCK_REASON = { + VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ], + MESSAGES: { + 'minlength': this.i18n('Block reason must be at least 2 characters long.'), + 'maxlength': this.i18n('Block reason cannot be more than 300 characters long.') + } + } + } +} diff --git a/client/src/app/shared/images/global-icon.component.ts b/client/src/app/shared/images/global-icon.component.ts index d2700f6c3..169882685 100644 --- a/client/src/app/shared/images/global-icon.component.ts +++ b/client/src/app/shared/images/global-icon.component.ts @@ -56,7 +56,8 @@ const icons = { 'refresh': require('!!raw-loader?!../../../assets/images/global/refresh.svg').default, 'npm': require('!!raw-loader?!../../../assets/images/global/npm.svg').default, 'fullscreen': require('!!raw-loader?!../../../assets/images/global/fullscreen.svg').default, - 'exit-fullscreen': require('!!raw-loader?!../../../assets/images/global/exit-fullscreen.svg').default + 'exit-fullscreen': require('!!raw-loader?!../../../assets/images/global/exit-fullscreen.svg').default, + 'robot': require('!!raw-loader?!../../../assets/images/global/robot.svg').default } export type GlobalIconName = keyof typeof icons diff --git a/client/src/app/shared/index.ts b/client/src/app/shared/index.ts index 136730c91..8be578d9f 100644 --- a/client/src/app/shared/index.ts +++ b/client/src/app/shared/index.ts @@ -3,5 +3,5 @@ export * from './forms' export * from './rest' export * from './users' export * from './video-abuse' -export * from './video-blacklist' +export * from './video-block' export * from './shared.module' diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 813f76672..2035097d7 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -35,7 +35,7 @@ import { UserValidatorsService, VideoAbuseValidatorsService, VideoAcceptOwnershipValidatorsService, - VideoBlacklistValidatorsService, + VideoBlockValidatorsService, VideoChangeOwnershipValidatorsService, VideoChannelValidatorsService, VideoCommentValidatorsService, @@ -78,7 +78,7 @@ import { VideoPlaylistElementMiniatureComponent } from '@app/shared/video-playli import { VideoPlaylistMiniatureComponent } from '@app/shared/video-playlist/video-playlist-miniature.component' import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' -import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component' +import { VideoBlockComponent } from '@app/shared/video/modals/video-block.component' import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.component' import { VideoReportComponent } from '@app/shared/video/modals/video-report.component' import { RedundancyService } from '@app/shared/video/redundancy.service' @@ -102,7 +102,7 @@ import { LoaderComponent } from './misc/loader.component' import { RestExtractor, RestService } from './rest' import { UserService } from './users' import { VideoAbuseService } from './video-abuse' -import { VideoBlacklistService } from './video-blacklist' +import { VideoBlockService } from './video-block' import { VideoOwnershipService } from './video-ownership' import { FeedComponent } from './video/feed.component' import { VideoMiniatureComponent } from './video/video-miniature.component' @@ -147,7 +147,7 @@ import { VideoService } from './video/video.service' VideoDownloadComponent, VideoReportComponent, - VideoBlacklistComponent, + VideoBlockComponent, FeedComponent, @@ -230,7 +230,7 @@ import { VideoService } from './video/video.service' VideoDownloadComponent, VideoReportComponent, - VideoBlacklistComponent, + VideoBlockComponent, FeedComponent, @@ -282,7 +282,7 @@ import { VideoService } from './video/video.service' RestExtractor, RestService, VideoAbuseService, - VideoBlacklistService, + VideoBlockService, VideoOwnershipService, UserService, VideoService, @@ -305,7 +305,7 @@ import { VideoService } from './video/video.service' VideoCommentValidatorsService, VideoValidatorsService, VideoCaptionsValidatorsService, - VideoBlacklistValidatorsService, + VideoBlockValidatorsService, OverviewService, VideoChangeOwnershipValidatorsService, VideoAcceptOwnershipValidatorsService, diff --git a/client/src/app/shared/users/user-notification.model.ts b/client/src/app/shared/users/user-notification.model.ts index 7b8368d87..bc1861c64 100644 --- a/client/src/app/shared/users/user-notification.model.ts +++ b/client/src/app/shared/users/user-notification.model.ts @@ -96,7 +96,7 @@ export class UserNotification implements UserNotificationServer { this.videoUrl = this.buildVideoUrl(this.video) break - case UserNotificationType.UNBLACKLIST_ON_MY_VIDEO: + case UserNotificationType.UNBLOCK_ON_MY_VIDEO: this.videoUrl = this.buildVideoUrl(this.video) break @@ -112,7 +112,7 @@ export class UserNotification implements UserNotificationServer { this.videoUrl = this.buildVideoUrl(this.videoAbuse.video) break - case UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS: + case UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS: this.videoAutoBlacklistUrl = '/admin/moderation/video-auto-blacklist/list' // Backward compatibility where we did not assign videoBlacklist to this type of notification before if (!this.videoBlacklist) this.videoBlacklist = { id: null, video: this.video } @@ -120,7 +120,7 @@ export class UserNotification implements UserNotificationServer { this.videoUrl = this.buildVideoUrl(this.videoBlacklist.video) break - case UserNotificationType.BLACKLIST_ON_MY_VIDEO: + case UserNotificationType.BLOCK_ON_MY_VIDEO: this.videoUrl = this.buildVideoUrl(this.videoBlacklist.video) break diff --git a/client/src/app/shared/users/user-notifications.component.html b/client/src/app/shared/users/user-notifications.component.html index 8dbe6e329..5a102995a 100644 --- a/client/src/app/shared/users/user-notifications.component.html +++ b/client/src/app/shared/users/user-notifications.component.html @@ -26,19 +26,19 @@ - +
- Your video {{ notification.video.name }} has been unblacklisted + Your video {{ notification.video.name }} has been unblocked
- +
- Your video {{ notification.videoBlacklist.video.name }} has been blacklisted + Your video {{ notification.videoBlacklist.video.name }} has been blocked
@@ -50,11 +50,11 @@
- + diff --git a/client/src/app/shared/video-blacklist/index.ts b/client/src/app/shared/video-blacklist/index.ts deleted file mode 100644 index bfb026441..000000000 --- a/client/src/app/shared/video-blacklist/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './video-blacklist.service' diff --git a/client/src/app/shared/video-blacklist/video-blacklist.service.ts b/client/src/app/shared/video-blacklist/video-blacklist.service.ts deleted file mode 100644 index c0e13a651..000000000 --- a/client/src/app/shared/video-blacklist/video-blacklist.service.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { catchError, map, concatMap, toArray } from 'rxjs/operators' -import { HttpClient, HttpParams } from '@angular/common/http' -import { Injectable } from '@angular/core' -import { SortMeta } from 'primeng/api' -import { from as observableFrom, Observable } from 'rxjs' -import { VideoBlacklist, VideoBlacklistType, ResultList } from '../../../../../shared' -import { Video } from '../video/video.model' -import { environment } from '../../../environments/environment' -import { RestExtractor, RestPagination, RestService } from '../rest' -import { ComponentPaginationLight } from '../rest/component-pagination.model' - -@Injectable() -export class VideoBlacklistService { - private static BASE_VIDEOS_URL = environment.apiUrl + '/api/v1/videos/' - - constructor ( - private authHttp: HttpClient, - private restService: RestService, - private restExtractor: RestExtractor - ) {} - - listBlacklist (options: { - pagination: RestPagination, - sort: SortMeta, - search?: string - type?: VideoBlacklistType - }): Observable> { - const { pagination, sort, search, type } = options - - let params = new HttpParams() - params = this.restService.addRestGetParams(params, pagination, sort) - - if (search) params = params.append('search', search) - if (type) params = params.append('type', type.toString()) - - return this.authHttp.get>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params }) - .pipe( - map(res => this.restExtractor.convertResultListDateToHuman(res)), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - getAutoBlacklistedAsVideoList (videoPagination: ComponentPaginationLight): Observable> { - const pagination = this.restService.componentPaginationToRestPagination(videoPagination) - - // prioritize first created since waiting longest - const AUTO_BLACKLIST_SORT = 'createdAt' - - let params = new HttpParams() - params = this.restService.addRestGetParams(params, pagination, AUTO_BLACKLIST_SORT) - - params = params.set('type', VideoBlacklistType.AUTO_BEFORE_PUBLISHED.toString()) - - return this.authHttp.get>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params }) - .pipe( - map(res => { - return { - total: res.total, - data: res.data.map(videoBlacklist => new Video(videoBlacklist.video)) - } - }), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - removeVideoFromBlacklist (videoIdArgs: number | number[]) { - const videoIds = Array.isArray(videoIdArgs) ? videoIdArgs : [ videoIdArgs ] - - return observableFrom(videoIds) - .pipe( - concatMap(id => this.authHttp.delete(VideoBlacklistService.BASE_VIDEOS_URL + id + '/blacklist')), - toArray(), - catchError(err => this.restExtractor.handleError(err)) - ) - } - - blacklistVideo (videoId: number, reason: string, unfederate: boolean) { - const body = { - unfederate, - reason - } - - return this.authHttp.post(VideoBlacklistService.BASE_VIDEOS_URL + videoId + '/blacklist', body) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(res => this.restExtractor.handleError(res)) - ) - } -} diff --git a/client/src/app/shared/video-block/index.ts b/client/src/app/shared/video-block/index.ts new file mode 100644 index 000000000..a99551a38 --- /dev/null +++ b/client/src/app/shared/video-block/index.ts @@ -0,0 +1 @@ +export * from './video-block.service' diff --git a/client/src/app/shared/video-block/video-block.service.ts b/client/src/app/shared/video-block/video-block.service.ts new file mode 100644 index 000000000..67ca1d85b --- /dev/null +++ b/client/src/app/shared/video-block/video-block.service.ts @@ -0,0 +1,77 @@ +import { catchError, map, concatMap, toArray } from 'rxjs/operators' +import { HttpClient, HttpParams } from '@angular/common/http' +import { Injectable } from '@angular/core' +import { SortMeta } from 'primeng/api' +import { from as observableFrom, Observable } from 'rxjs' +import { VideoBlocklist, VideoBlockType, ResultList } from '../../../../../shared' +import { environment } from '../../../environments/environment' +import { RestExtractor, RestPagination, RestService } from '../rest' + +@Injectable() +export class VideoBlockService { + private static BASE_VIDEOS_URL = environment.apiUrl + '/api/v1/videos/' + + constructor ( + private authHttp: HttpClient, + private restService: RestService, + private restExtractor: RestExtractor + ) {} + + listBlocks (options: { + pagination: RestPagination + sort: SortMeta + search?: string + type?: VideoBlockType + }): Observable> { + const { pagination, sort, search, type } = options + + let params = new HttpParams() + params = this.restService.addRestGetParams(params, pagination, sort) + + if (search) { + const filters = this.restService.parseQueryStringFilter(search, { + type: { + prefix: 'type:', + handler: v => { + if (v === 'manual') return VideoBlockType.MANUAL + if (v === 'auto') return VideoBlockType.AUTO_BEFORE_PUBLISHED + + return undefined + } + } + }) + + params = this.restService.addObjectParams(params, filters) + } + + return this.authHttp.get>(VideoBlockService.BASE_VIDEOS_URL + 'blacklist', { params }) + .pipe( + map(res => this.restExtractor.convertResultListDateToHuman(res)), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + unblockVideo (videoIdArgs: number | number[]) { + const videoIds = Array.isArray(videoIdArgs) ? videoIdArgs : [ videoIdArgs ] + + return observableFrom(videoIds) + .pipe( + concatMap(id => this.authHttp.delete(VideoBlockService.BASE_VIDEOS_URL + id + '/blacklist')), + toArray(), + catchError(err => this.restExtractor.handleError(err)) + ) + } + + blockVideo (videoId: number, reason: string, unfederate: boolean) { + const body = { + unfederate, + reason + } + + return this.authHttp.post(VideoBlockService.BASE_VIDEOS_URL + videoId + '/blacklist', body) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } +} diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html index cd8a5b840..8ce3b25b0 100644 --- a/client/src/app/shared/video/abstract-video-list.html +++ b/client/src/app/shared/video/abstract-video-list.html @@ -39,7 +39,7 @@ [fitWidth]="true" [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType" [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions" - (videoBlacklisted)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)" + (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)" > diff --git a/client/src/app/shared/video/modals/video-blacklist.component.html b/client/src/app/shared/video/modals/video-blacklist.component.html deleted file mode 100644 index 8f06a6b02..000000000 --- a/client/src/app/shared/video/modals/video-blacklist.component.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/client/src/app/shared/video/modals/video-blacklist.component.scss b/client/src/app/shared/video/modals/video-blacklist.component.scss deleted file mode 100644 index afcdb9a16..000000000 --- a/client/src/app/shared/video/modals/video-blacklist.component.scss +++ /dev/null @@ -1,6 +0,0 @@ -@import 'variables'; -@import 'mixins'; - -textarea { - @include peertube-textarea(100%, 100px); -} diff --git a/client/src/app/shared/video/modals/video-blacklist.component.ts b/client/src/app/shared/video/modals/video-blacklist.component.ts deleted file mode 100644 index 6ef9c250b..000000000 --- a/client/src/app/shared/video/modals/video-blacklist.component.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' -import { Notifier, RedirectService } from '@app/core' -import { VideoBlacklistService } from '../../../shared/video-blacklist' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' -import { NgbModal } from '@ng-bootstrap/ng-bootstrap' -import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' -import { FormReactive, VideoBlacklistValidatorsService } from '@app/shared/forms' -import { Video } from '@app/shared/video/video.model' - -@Component({ - selector: 'my-video-blacklist', - templateUrl: './video-blacklist.component.html', - styleUrls: [ './video-blacklist.component.scss' ] -}) -export class VideoBlacklistComponent extends FormReactive implements OnInit { - @Input() video: Video = null - - @ViewChild('modal', { static: true }) modal: NgbModal - - @Output() videoBlacklisted = new EventEmitter() - - error: string = null - - private openedModal: NgbModalRef - - constructor ( - protected formValidatorService: FormValidatorService, - private modalService: NgbModal, - private videoBlacklistValidatorsService: VideoBlacklistValidatorsService, - private videoBlacklistService: VideoBlacklistService, - private notifier: Notifier, - private redirectService: RedirectService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - const defaultValues = { unfederate: 'true' } - - this.buildForm({ - reason: this.videoBlacklistValidatorsService.VIDEO_BLACKLIST_REASON, - unfederate: null - }, defaultValues) - } - - show () { - this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) - } - - hide () { - this.openedModal.close() - this.openedModal = null - } - - blacklist () { - const reason = this.form.value[ 'reason' ] || undefined - const unfederate = this.video.isLocal ? this.form.value[ 'unfederate' ] : undefined - - this.videoBlacklistService.blacklistVideo(this.video.id, reason, unfederate) - .subscribe( - () => { - this.notifier.success(this.i18n('Video blacklisted.')) - this.hide() - - this.video.blacklisted = true - this.video.blacklistedReason = reason - - this.videoBlacklisted.emit() - }, - - err => this.notifier.error(err.message) - ) - } -} diff --git a/client/src/app/shared/video/modals/video-block.component.html b/client/src/app/shared/video/modals/video-block.component.html new file mode 100644 index 000000000..a8dd30b5e --- /dev/null +++ b/client/src/app/shared/video/modals/video-block.component.html @@ -0,0 +1,45 @@ + + + + + diff --git a/client/src/app/shared/video/modals/video-block.component.scss b/client/src/app/shared/video/modals/video-block.component.scss new file mode 100644 index 000000000..afcdb9a16 --- /dev/null +++ b/client/src/app/shared/video/modals/video-block.component.scss @@ -0,0 +1,6 @@ +@import 'variables'; +@import 'mixins'; + +textarea { + @include peertube-textarea(100%, 100px); +} diff --git a/client/src/app/shared/video/modals/video-block.component.ts b/client/src/app/shared/video/modals/video-block.component.ts new file mode 100644 index 000000000..1a25e0578 --- /dev/null +++ b/client/src/app/shared/video/modals/video-block.component.ts @@ -0,0 +1,75 @@ +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' +import { Notifier, RedirectService } from '@app/core' +import { VideoBlockService } from '../../video-block' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' +import { NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' +import { FormReactive, VideoBlockValidatorsService } from '@app/shared/forms' +import { Video } from '@app/shared/video/video.model' + +@Component({ + selector: 'my-video-block', + templateUrl: './video-block.component.html', + styleUrls: [ './video-block.component.scss' ] +}) +export class VideoBlockComponent extends FormReactive implements OnInit { + @Input() video: Video = null + + @ViewChild('modal', { static: true }) modal: NgbModal + + @Output() videoBlocked = new EventEmitter() + + error: string = null + + private openedModal: NgbModalRef + + constructor ( + protected formValidatorService: FormValidatorService, + private modalService: NgbModal, + private videoBlockValidatorsService: VideoBlockValidatorsService, + private videoBlocklistService: VideoBlockService, + private notifier: Notifier, + private i18n: I18n + ) { + super() + } + + ngOnInit () { + const defaultValues = { unfederate: 'true' } + + this.buildForm({ + reason: this.videoBlockValidatorsService.VIDEO_BLOCK_REASON, + unfederate: null + }, defaultValues) + } + + show () { + this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) + } + + hide () { + this.openedModal.close() + this.openedModal = null + } + + block () { + const reason = this.form.value[ 'reason' ] || undefined + const unfederate = this.video.isLocal ? this.form.value[ 'unfederate' ] : undefined + + this.videoBlocklistService.blockVideo(this.video.id, reason, unfederate) + .subscribe( + () => { + this.notifier.success(this.i18n('Video blocked.')) + this.hide() + + this.video.blacklisted = true + this.video.blockedReason = reason + + this.videoBlocked.emit() + }, + + err => this.notifier.error(err.message) + ) + } +} diff --git a/client/src/app/shared/video/video-actions-dropdown.component.html b/client/src/app/shared/video/video-actions-dropdown.component.html index ec03fa55d..3c8271b65 100644 --- a/client/src/app/shared/video/video-actions-dropdown.component.html +++ b/client/src/app/shared/video/video-actions-dropdown.component.html @@ -17,5 +17,5 @@ - +
diff --git a/client/src/app/shared/video/video-actions-dropdown.component.ts b/client/src/app/shared/video/video-actions-dropdown.component.ts index 4e5fc6476..1f5763610 100644 --- a/client/src/app/shared/video/video-actions-dropdown.component.ts +++ b/client/src/app/shared/video/video-actions-dropdown.component.ts @@ -9,8 +9,8 @@ import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' import { VideoAddToPlaylistComponent } from '@app/shared/video-playlist/video-add-to-playlist.component' import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.component' import { VideoReportComponent } from '@app/shared/video/modals/video-report.component' -import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component' -import { VideoBlacklistService } from '@app/shared/video-blacklist' +import { VideoBlockComponent } from '@app/shared/video/modals/video-block.component' +import { VideoBlockService } from '@app/shared/video-block' import { ScreenService } from '@app/shared/misc/screen.service' import { VideoCaption } from '@shared/models' import { RedundancyService } from '@app/shared/video/redundancy.service' @@ -36,7 +36,7 @@ export class VideoActionsDropdownComponent implements OnChanges { @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent @ViewChild('videoReportModal') videoReportModal: VideoReportComponent - @ViewChild('videoBlacklistModal') videoBlacklistModal: VideoBlacklistComponent + @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent @Input() video: Video | VideoDetails @Input() videoCaptions: VideoCaption[] = [] @@ -59,8 +59,8 @@ export class VideoActionsDropdownComponent implements OnChanges { @Input() buttonDirection: DropdownDirection = 'vertical' @Output() videoRemoved = new EventEmitter() - @Output() videoUnblacklisted = new EventEmitter() - @Output() videoBlacklisted = new EventEmitter() + @Output() videoUnblocked = new EventEmitter() + @Output() videoBlocked = new EventEmitter() @Output() modalOpened = new EventEmitter() videoActions: DropdownAction<{ video: Video }>[][] = [] @@ -71,7 +71,7 @@ export class VideoActionsDropdownComponent implements OnChanges { private authService: AuthService, private notifier: Notifier, private confirmService: ConfirmService, - private videoBlacklistService: VideoBlacklistService, + private videoBlocklistService: VideoBlockService, private screenService: ScreenService, private videoService: VideoService, private redundancyService: RedundancyService, @@ -117,10 +117,10 @@ export class VideoActionsDropdownComponent implements OnChanges { this.videoReportModal.show() } - showBlacklistModal () { + showBlockModal () { this.modalOpened.emit() - this.videoBlacklistModal.show() + this.videoBlockModal.show() } /* Actions checker */ @@ -133,12 +133,12 @@ export class VideoActionsDropdownComponent implements OnChanges { return this.video.isRemovableBy(this.user) } - isVideoBlacklistable () { - return this.video.isBlackistableBy(this.user) + isVideoBlockable () { + return this.video.isBlockableBy(this.user) } - isVideoUnblacklistable () { - return this.video.isUnblacklistableBy(this.user) + isVideoUnblockable () { + return this.video.isUnblockableBy(this.user) } isVideoDownloadable () { @@ -151,22 +151,22 @@ export class VideoActionsDropdownComponent implements OnChanges { /* Action handlers */ - async unblacklistVideo () { + async unblockVideo () { const confirmMessage = this.i18n( - 'Do you really want to remove this video from the blacklist? It will be available again in the videos list.' + 'Do you really want to unblock this video? It will be available again in the videos list.' ) - const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblacklist')) + const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock')) if (res === false) return - this.videoBlacklistService.removeVideoFromBlacklist(this.video.id).subscribe( + this.videoBlocklistService.unblockVideo(this.video.id).subscribe( () => { - this.notifier.success(this.i18n('Video {{name}} removed from the blacklist.', { name: this.video.name })) + this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name })) this.video.blacklisted = false - this.video.blacklistedReason = null + this.video.blockedReason = null - this.videoUnblacklisted.emit() + this.videoUnblocked.emit() }, err => this.notifier.error(err.message) @@ -203,8 +203,8 @@ export class VideoActionsDropdownComponent implements OnChanges { ) } - onVideoBlacklisted () { - this.videoBlacklisted.emit() + onVideoBlocked () { + this.videoBlocked.emit() } getPlaylistDropdownPlacement () { @@ -239,16 +239,16 @@ export class VideoActionsDropdownComponent implements OnChanges { isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable() }, { - label: this.i18n('Blacklist'), - handler: () => this.showBlacklistModal(), + label: this.i18n('Block'), + handler: () => this.showBlockModal(), iconName: 'no', - isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlacklistable() + isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlockable() }, { - label: this.i18n('Unblacklist'), - handler: () => this.unblacklistVideo(), + label: this.i18n('Unblock'), + handler: () => this.unblockVideo(), iconName: 'undo', - isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblacklistable() + isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblockable() }, { label: this.i18n('Mirror'), diff --git a/client/src/app/shared/video/video-miniature.component.html b/client/src/app/shared/video/video-miniature.component.html index 3e23cf18c..575505f63 100644 --- a/client/src/app/shared/video/video-miniature.component.html +++ b/client/src/app/shared/video/video-miniature.component.html @@ -43,9 +43,9 @@ -
- Blacklisted - {{ video.blacklistedReason }} +
+ Blocked + {{ video.blockedReason }}
@@ -57,7 +57,7 @@
diff --git a/client/src/app/shared/video/video-miniature.component.scss b/client/src/app/shared/video/video-miniature.component.scss index 849bd54bb..34f34f228 100644 --- a/client/src/app/shared/video/video-miniature.component.scss +++ b/client/src/app/shared/video/video-miniature.component.scss @@ -45,15 +45,15 @@ $more-margin-right: 15px; } .video-info-privacy, - .video-info-blacklisted .blacklisted-label, + .video-info-blocked .blocked-label, .video-info-nsfw { font-weight: $font-semibold; } - .video-info-blacklisted { + .video-info-blocked { color: red; - .blacklisted-reason::before { + .blocked-reason::before { content: ' - '; } } @@ -160,7 +160,7 @@ $more-margin-right: 15px; margin-top: 5px; } - .video-info-blacklisted { + .video-info-blocked { margin-top: 3px; } } diff --git a/client/src/app/shared/video/video-miniature.component.ts b/client/src/app/shared/video/video-miniature.component.ts index aa1726ca7..f0b0992e2 100644 --- a/client/src/app/shared/video/video-miniature.component.ts +++ b/client/src/app/shared/video/video-miniature.component.ts @@ -59,8 +59,8 @@ export class VideoMiniatureComponent implements OnInit { @Input() useLazyLoadUrl = false - @Output() videoBlacklisted = new EventEmitter() - @Output() videoUnblacklisted = new EventEmitter() + @Output() videoBlocked = new EventEmitter() + @Output() videoUnblocked = new EventEmitter() @Output() videoRemoved = new EventEmitter() videoActionsDisplayOptions: VideoActionsDisplayType = { @@ -184,12 +184,12 @@ export class VideoMiniatureComponent implements OnInit { this.loadWatchLater() } - onVideoBlacklisted () { - this.videoBlacklisted.emit() + onVideoBlocked () { + this.videoBlocked.emit() } - onVideoUnblacklisted () { - this.videoUnblacklisted.emit() + onVideoUnblocked () { + this.videoUnblocked.emit() } onVideoRemoved () { diff --git a/client/src/app/shared/video/video.model.ts b/client/src/app/shared/video/video.model.ts index 97759f9c1..2b3d915ef 100644 --- a/client/src/app/shared/video/video.model.ts +++ b/client/src/app/shared/video/video.model.ts @@ -54,7 +54,7 @@ export class Video implements VideoServerModel { state?: VideoConstant scheduledUpdate?: VideoScheduleUpdate blacklisted?: boolean - blacklistedReason?: string + blockedReason?: string account: { id: number @@ -140,7 +140,7 @@ export class Video implements VideoServerModel { if (this.state) this.state.label = peertubeTranslate(this.state.label, translations) this.blacklisted = hash.blacklisted - this.blacklistedReason = hash.blacklistedReason + this.blockedReason = hash.blacklistedReason this.userHistory = hash.userHistory @@ -163,12 +163,12 @@ export class Video implements VideoServerModel { return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO)) } - isBlackistableBy (user: AuthUser) { - return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true + isBlockableBy (user: AuthUser) { + return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) === true } - isUnblacklistableBy (user: AuthUser) { - return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true + isUnblockableBy (user: AuthUser) { + return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) === true } isUpdatableBy (user: AuthUser) { diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 433543a7b..63103e2e7 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html @@ -29,8 +29,8 @@
-
This video is blacklisted.
- {{ video.blacklistedReason }} +
This video is blocked.
+ {{ video.blockedReason }}
diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss index 8be0bab1d..e0d41117a 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss @@ -45,7 +45,7 @@ $video-info-margin-left: 44px; } } -.blacklisted-label { +.blocked-label { font-weight: $font-semibold; } diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 3790c7f6a..9f726cf35 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -335,7 +335,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.videoCaptionService.listCaptions(videoId) ]) .pipe( - // If 401, the video is private or blacklisted so redirect to 404 + // If 401, the video is private or blocklisted so redirect to 404 catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ])) ) .subscribe(([ video, captionsResult ]) => { @@ -364,7 +364,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.playlistService.getVideoPlaylist(playlistId) .pipe( - // If 401, the video is private or blacklisted so redirect to 404 + // If 401, the video is private or blocklisted so redirect to 404 catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ])) ) .subscribe(playlist => { diff --git a/client/src/app/videos/recommendations/recommended-videos.component.html b/client/src/app/videos/recommendations/recommended-videos.component.html index c6bdfee46..e4568c309 100644 --- a/client/src/app/videos/recommendations/recommended-videos.component.html +++ b/client/src/app/videos/recommendations/recommended-videos.component.html @@ -13,7 +13,7 @@
- +
diff --git a/client/src/assets/images/global/robot.svg b/client/src/assets/images/global/robot.svg new file mode 100644 index 000000000..46db9baef --- /dev/null +++ b/client/src/assets/images/global/robot.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts index 3b25ceea2..2c6948923 100644 --- a/server/controllers/api/videos/blacklist.ts +++ b/server/controllers/api/videos/blacklist.ts @@ -23,14 +23,14 @@ const blacklistRouter = express.Router() blacklistRouter.post('/:videoId/blacklist', authenticate, - ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS), asyncMiddleware(videosBlacklistAddValidator), asyncMiddleware(addVideoToBlacklistController) ) blacklistRouter.get('/blacklist', authenticate, - ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS), paginationValidator, blacklistSortValidator, setBlacklistSort, @@ -41,14 +41,14 @@ blacklistRouter.get('/blacklist', blacklistRouter.put('/:videoId/blacklist', authenticate, - ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS), asyncMiddleware(videosBlacklistUpdateValidator), asyncMiddleware(updateVideoBlacklistController) ) blacklistRouter.delete('/:videoId/blacklist', authenticate, - ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), + ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS), asyncMiddleware(videosBlacklistRemoveValidator), asyncMiddleware(removeVideoFromBlacklistController) ) diff --git a/server/helpers/custom-validators/video-blacklist.ts b/server/helpers/custom-validators/video-blacklist.ts index 17cb3b00b..de6726b8f 100644 --- a/server/helpers/custom-validators/video-blacklist.ts +++ b/server/helpers/custom-validators/video-blacklist.ts @@ -1,7 +1,7 @@ import validator from 'validator' import { exists } from './misc' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' -import { VideoBlacklistType } from '../../../shared/models/videos' +import { VideoBlockType } from '../../../shared/models/videos' const VIDEO_BLACKLIST_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_BLACKLIST @@ -10,7 +10,7 @@ function isVideoBlacklistReasonValid (value: string) { } function isVideoBlacklistTypeValid (value: any) { - return exists(value) && validator.isInt('' + value) && VideoBlacklistType[value] !== undefined + return exists(value) && validator.isInt('' + value) && VideoBlockType[value] !== undefined } // --------------------------------------------------------------------------- diff --git a/server/initializers/migrations/0350-video-blacklist-type.ts b/server/initializers/migrations/0350-video-blacklist-type.ts index f79ae5ec7..22c82e431 100644 --- a/server/initializers/migrations/0350-video-blacklist-type.ts +++ b/server/initializers/migrations/0350-video-blacklist-type.ts @@ -1,5 +1,5 @@ import * as Sequelize from 'sequelize' -import { VideoBlacklistType } from '../../../shared/models/videos' +import { VideoBlockType } from '../../../shared/models/videos' async function up (utils: { transaction: Sequelize.Transaction @@ -18,7 +18,7 @@ async function up (utils: { } { - const query = 'UPDATE "videoBlacklist" SET "type" = ' + VideoBlacklistType.MANUAL + const query = 'UPDATE "videoBlacklist" SET "type" = ' + VideoBlockType.MANUAL await utils.sequelize.query(query) } diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts index 89f91e031..3e90bb57e 100644 --- a/server/lib/notifier.ts +++ b/server/lib/notifier.ts @@ -387,7 +387,7 @@ class Notifier { } private async notifyModeratorsOfVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo) { - const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLACKLIST) + const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLOCKS) if (moderators.length === 0) return logger.info('Notifying %s moderators of video auto-blacklist %s.', moderators.length, videoBlacklist.Video.url) @@ -398,7 +398,7 @@ class Notifier { async function notificationCreator (user: MUserWithNotificationSetting) { const notification = await UserNotificationModel.create({ - type: UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS, + type: UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS, userId: user.id, videoBlacklistId: videoBlacklist.id }) @@ -426,7 +426,7 @@ class Notifier { async function notificationCreator (user: MUserWithNotificationSetting) { const notification = await UserNotificationModel.create({ - type: UserNotificationType.BLACKLIST_ON_MY_VIDEO, + type: UserNotificationType.BLOCK_ON_MY_VIDEO, userId: user.id, videoBlacklistId: videoBlacklist.id }) @@ -454,7 +454,7 @@ class Notifier { async function notificationCreator (user: MUserWithNotificationSetting) { const notification = await UserNotificationModel.create({ - type: UserNotificationType.UNBLACKLIST_ON_MY_VIDEO, + type: UserNotificationType.UNBLOCK_ON_MY_VIDEO, userId: user.id, videoId: video.id }) diff --git a/server/lib/video-blacklist.ts b/server/lib/video-blacklist.ts index bd60c6201..f1657e8f1 100644 --- a/server/lib/video-blacklist.ts +++ b/server/lib/video-blacklist.ts @@ -8,7 +8,7 @@ import { MVideoFullLight, MVideoWithBlacklistLight } from '@server/typings/models' -import { UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../shared/models' +import { UserRight, VideoBlacklistCreate, VideoBlockType } from '../../shared/models' import { UserAdminFlag } from '../../shared/models/users/user-flag.model' import { logger } from '../helpers/logger' import { CONFIG } from '../initializers/config' @@ -39,7 +39,7 @@ async function autoBlacklistVideoIfNeeded (parameters: { videoId: video.id, unfederated: true, reason: 'Auto-blacklisted. Moderator review required.', - type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED + type: VideoBlockType.AUTO_BEFORE_PUBLISHED } const [ videoBlacklist ] = await VideoBlacklistModel.findOrCreate({ where: { @@ -64,7 +64,7 @@ async function blacklistVideo (videoInstance: MVideoAccountLight, options: Video videoId: videoInstance.id, unfederated: options.unfederate === true, reason: options.reason, - type: VideoBlacklistType.MANUAL + type: VideoBlockType.MANUAL } ) blacklist.Video = videoInstance @@ -94,7 +94,7 @@ async function unblacklistVideo (videoBlacklist: MVideoBlacklist, video: MVideoF Notifier.Instance.notifyOnVideoUnblacklist(video) - if (videoBlacklistType === VideoBlacklistType.AUTO_BEFORE_PUBLISHED) { + if (videoBlacklistType === VideoBlockType.AUTO_BEFORE_PUBLISHED) { Notifier.Instance.notifyOnVideoPublishedAfterRemovedFromAutoBlacklist(video) // Delete on object so new video notifications will send @@ -126,7 +126,7 @@ function autoBlacklistNeeded (parameters: { if (!CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED || !user) return false if (isRemote || isNew === false) return false - if (user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) || user.hasAdminFlag(UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST)) return false + if (user.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) || user.hasAdminFlag(UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK)) return false return true } diff --git a/server/models/account/user.ts b/server/models/account/user.ts index fbd3080c6..4ea175583 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts @@ -739,11 +739,11 @@ export class UserModel extends Model { const videoUserId = video.VideoChannel.Account.userId if (video.isBlacklisted()) { - return videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) + return videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) } if (video.privacy === VideoPrivacy.PRIVATE) { - return video.VideoChannel && videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) + return video.VideoChannel && videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) } if (video.privacy === VideoPrivacy.INTERNAL) return true diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index 8cbfe362e..70a6ecb03 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts @@ -3,7 +3,7 @@ import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '.. import { VideoModel } from './video' import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel' import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' -import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' +import { VideoBlocklist, VideoBlockType } from '../../../shared/models/videos' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' import { FindOptions } from 'sequelize' import { ThumbnailModel } from './thumbnail' @@ -34,7 +34,7 @@ export class VideoBlacklistModel extends Model { @Default(null) @Is('VideoBlacklistType', value => throwIfNotValid(value, isVideoBlacklistTypeValid, 'type')) @Column - type: VideoBlacklistType + type: VideoBlockType @CreatedAt createdAt: Date @@ -59,7 +59,7 @@ export class VideoBlacklistModel extends Model { count: number sort: SortType search?: string - type?: VideoBlacklistType + type?: VideoBlockType }) { const { start, count, sort, search, type } = parameters @@ -119,7 +119,7 @@ export class VideoBlacklistModel extends Model { return VideoBlacklistModel.findOne(query) } - toFormattedJSON (this: MVideoBlacklistFormattable): VideoBlacklist { + toFormattedJSON (this: MVideoBlacklistFormattable): VideoBlocklist { return { id: this.id, createdAt: this.createdAt, diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index 6e737af15..94d47408a 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts @@ -188,7 +188,7 @@ describe('Test users API validators', function () { videoQuota: -1, videoQuotaDaily: -1, role: UserRole.USER, - adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST + adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK } it('Should fail with a too small username', async function () { diff --git a/server/tests/api/check-params/video-blacklist.ts b/server/tests/api/check-params/video-blacklist.ts index 145f43980..b96c26989 100644 --- a/server/tests/api/check-params/video-blacklist.ts +++ b/server/tests/api/check-params/video-blacklist.ts @@ -24,7 +24,7 @@ import { checkBadSortPagination, checkBadStartPagination } from '../../../../shared/extra-utils/requests/check-api-params' -import { VideoBlacklistType, VideoDetails } from '../../../../shared/models/videos' +import { VideoBlockType, VideoDetails } from '../../../../shared/models/videos' import { expect } from 'chai' describe('Test video blacklist API validators', function () { @@ -243,7 +243,7 @@ describe('Test video blacklist API validators', function () { }) it('Should succeed with the correct parameters', async function () { - await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, type: VideoBlacklistType.MANUAL }) + await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, type: VideoBlockType.MANUAL }) }) }) diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index c0cbce360..af5a5fd25 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts @@ -265,7 +265,7 @@ describe('Test users', function () { username: user.username, password: user.password, videoQuota: 2 * 1024 * 1024, - adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST + adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK }) }) @@ -292,7 +292,7 @@ describe('Test users', function () { } expect(userMe.adminFlags).to.be.undefined - expect(userGet.adminFlags).to.equal(UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST) + expect(userGet.adminFlags).to.equal(UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK) expect(userMe.specialPlaylists).to.have.lengthOf(1) expect(userMe.specialPlaylists[0].type).to.equal(VideoPlaylistType.WATCH_LATER) diff --git a/server/tests/api/videos/video-blacklist.ts b/server/tests/api/videos/video-blacklist.ts index 67bc0114c..6e15893f3 100644 --- a/server/tests/api/videos/video-blacklist.ts +++ b/server/tests/api/videos/video-blacklist.ts @@ -25,7 +25,7 @@ import { } from '../../../../shared/extra-utils/index' import { doubleFollow } from '../../../../shared/extra-utils/server/follows' import { waitJobs } from '../../../../shared/extra-utils/server/jobs' -import { VideoBlacklist, VideoBlacklistType } from '../../../../shared/models/videos' +import { VideoBlocklist, VideoBlockType } from '../../../../shared/models/videos' import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' import { User, UserRole } from '../../../../shared/models/users' import { getMagnetURI, getYoutubeVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports' @@ -127,7 +127,7 @@ describe('Test video blacklist', function () { const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, - type: VideoBlacklistType.MANUAL + type: VideoBlockType.MANUAL }) expect(res.body.total).to.equal(2) @@ -141,7 +141,7 @@ describe('Test video blacklist', function () { const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, - type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED + type: VideoBlockType.AUTO_BEFORE_PUBLISHED }) expect(res.body.total).to.equal(0) @@ -219,7 +219,7 @@ describe('Test video blacklist', function () { }) describe('When removing a blacklisted video', function () { - let videoToRemove: VideoBlacklist + let videoToRemove: VideoBlocklist let blacklist = [] it('Should not have any video in videos list on server 1', async function () { @@ -328,7 +328,7 @@ describe('Test video blacklist', function () { it('Should have the correct video blacklist unfederate attribute', async function () { const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: 'createdAt' }) - const blacklistedVideos: VideoBlacklist[] = res.body.data + const blacklistedVideos: VideoBlocklist[] = res.body.data const video3Blacklisted = blacklistedVideos.find(b => b.video.uuid === video3UUID) const video4Blacklisted = blacklistedVideos.find(b => b.video.uuid === video4UUID) @@ -396,7 +396,7 @@ describe('Test video blacklist', function () { url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, - adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST, + adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK, password: user.password, role: UserRole.USER }) @@ -413,7 +413,7 @@ describe('Test video blacklist', function () { const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, - type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED + type: VideoBlockType.AUTO_BEFORE_PUBLISHED }) expect(res.body.total).to.equal(1) @@ -434,7 +434,7 @@ describe('Test video blacklist', function () { url: servers[0].url, token: servers[0].accessToken, sort: 'createdAt', - type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED + type: VideoBlockType.AUTO_BEFORE_PUBLISHED }) expect(res.body.total).to.equal(2) @@ -453,7 +453,7 @@ describe('Test video blacklist', function () { url: servers[0].url, token: servers[0].accessToken, sort: 'createdAt', - type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED + type: VideoBlockType.AUTO_BEFORE_PUBLISHED }) expect(res.body.total).to.equal(3) @@ -466,7 +466,7 @@ describe('Test video blacklist', function () { const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, - type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED + type: VideoBlockType.AUTO_BEFORE_PUBLISHED }) expect(res.body.total).to.equal(3) diff --git a/shared/extra-utils/users/user-notifications.ts b/shared/extra-utils/users/user-notifications.ts index bd00894c4..6f85bd450 100644 --- a/shared/extra-utils/users/user-notifications.ts +++ b/shared/extra-utils/users/user-notifications.ts @@ -455,7 +455,7 @@ async function checkNewVideoAbuseForModerators (base: CheckerBaseParams, videoUU } async function checkVideoAutoBlacklistForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) { - const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS + const notificationType = UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS function notificationChecker (notification: UserNotification, type: CheckerType) { if (type === 'presence') { @@ -486,8 +486,8 @@ async function checkNewBlacklistOnMyVideo ( blacklistType: 'blacklist' | 'unblacklist' ) { const notificationType = blacklistType === 'blacklist' - ? UserNotificationType.BLACKLIST_ON_MY_VIDEO - : UserNotificationType.UNBLACKLIST_ON_MY_VIDEO + ? UserNotificationType.BLOCK_ON_MY_VIDEO + : UserNotificationType.UNBLOCK_ON_MY_VIDEO function notificationChecker (notification: UserNotification) { expect(notification).to.not.be.undefined diff --git a/shared/extra-utils/videos/video-blacklist.ts b/shared/extra-utils/videos/video-blacklist.ts index ba139ef95..c06b2aa5d 100644 --- a/shared/extra-utils/videos/video-blacklist.ts +++ b/shared/extra-utils/videos/video-blacklist.ts @@ -1,5 +1,5 @@ import * as request from 'supertest' -import { VideoBlacklistType } from '../../models/videos' +import { VideoBlockType } from '../../models/videos' import { makeGetRequest } from '..' function addVideoToBlacklist ( @@ -45,7 +45,7 @@ function getBlacklistedVideosList (parameters: { url: string token: string sort?: string - type?: VideoBlacklistType + type?: VideoBlockType specialStatus?: number }) { const { url, token, sort, type, specialStatus = 200 } = parameters diff --git a/shared/models/users/user-flag.model.ts b/shared/models/users/user-flag.model.ts index f5759f18f..e8b5a5c50 100644 --- a/shared/models/users/user-flag.model.ts +++ b/shared/models/users/user-flag.model.ts @@ -1,4 +1,4 @@ export enum UserAdminFlag { NONE = 0, - BY_PASS_VIDEO_AUTO_BLACKLIST = 1 << 0 + BYPASS_VIDEO_AUTO_BLOCK = 1 << 0 } diff --git a/shared/models/users/user-notification.model.ts b/shared/models/users/user-notification.model.ts index e9be1ca7f..2329503a8 100644 --- a/shared/models/users/user-notification.model.ts +++ b/shared/models/users/user-notification.model.ts @@ -5,8 +5,8 @@ export enum UserNotificationType { NEW_COMMENT_ON_MY_VIDEO = 2, NEW_VIDEO_ABUSE_FOR_MODERATORS = 3, - BLACKLIST_ON_MY_VIDEO = 4, - UNBLACKLIST_ON_MY_VIDEO = 5, + BLOCK_ON_MY_VIDEO = 4, + UNBLOCK_ON_MY_VIDEO = 5, MY_VIDEO_PUBLISHED = 6, @@ -17,7 +17,7 @@ export enum UserNotificationType { NEW_FOLLOW = 10, COMMENT_MENTION = 11, - VIDEO_AUTO_BLACKLIST_FOR_MODERATORS = 12, + VIDEO_AUTO_BLOCK_FOR_MODERATORS = 12, NEW_INSTANCE_FOLLOWER = 13, diff --git a/shared/models/users/user-right.enum.ts b/shared/models/users/user-right.enum.ts index 2f88a65de..3fb760709 100644 --- a/shared/models/users/user-right.enum.ts +++ b/shared/models/users/user-right.enum.ts @@ -20,7 +20,7 @@ export enum UserRight { MANAGE_ACCOUNTS_BLOCKLIST, MANAGE_SERVERS_BLOCKLIST, - MANAGE_VIDEO_BLACKLIST, + MANAGE_VIDEO_BLOCKS, REMOVE_ANY_VIDEO, REMOVE_ANY_VIDEO_CHANNEL, diff --git a/shared/models/users/user-role.ts b/shared/models/users/user-role.ts index 2b08b5850..30ec5edce 100644 --- a/shared/models/users/user-role.ts +++ b/shared/models/users/user-role.ts @@ -19,7 +19,7 @@ const userRoleRights: { [ id in UserRole ]: UserRight[] } = { ], [UserRole.MODERATOR]: [ - UserRight.MANAGE_VIDEO_BLACKLIST, + UserRight.MANAGE_VIDEO_BLOCKS, UserRight.MANAGE_VIDEO_ABUSES, UserRight.REMOVE_ANY_VIDEO, UserRight.REMOVE_ANY_VIDEO_CHANNEL, diff --git a/shared/models/videos/blacklist/video-blacklist.model.ts b/shared/models/videos/blacklist/video-blacklist.model.ts index a6e0ef175..e6090b1e9 100644 --- a/shared/models/videos/blacklist/video-blacklist.model.ts +++ b/shared/models/videos/blacklist/video-blacklist.model.ts @@ -1,15 +1,15 @@ import { Video } from '../video.model' -export enum VideoBlacklistType { +export enum VideoBlockType { MANUAL = 1, AUTO_BEFORE_PUBLISHED = 2 } -export interface VideoBlacklist { +export interface VideoBlocklist { id: number unfederated: boolean reason?: string - type: VideoBlacklistType + type: VideoBlockType video: Video