Add user/instance block by users in the client
This commit is contained in:
parent
7ad9b9846c
commit
af5767ffae
|
@ -10,8 +10,13 @@
|
||||||
<div class="actor-name">{{ account.nameWithHost }}</div>
|
<div class="actor-name">{{ account.nameWithHost }}</div>
|
||||||
|
|
||||||
<span *ngIf="user?.blocked" [ngbTooltip]="user.blockedReason" class="badge badge-danger" i18n>Banned</span>
|
<span *ngIf="user?.blocked" [ngbTooltip]="user.blockedReason" class="badge badge-danger" i18n>Banned</span>
|
||||||
|
<span *ngIf="account.muted" class="badge badge-danger" i18n>Muted</span>
|
||||||
|
<span *ngIf="account.mutedServer" class="badge badge-danger" i18n>Instance muted</span>
|
||||||
|
|
||||||
<my-user-moderation-dropdown buttonSize="small" [user]="user" (userChanged)="onUserChanged()" (userDeleted)="onUserDeleted()">
|
<my-user-moderation-dropdown
|
||||||
|
buttonSize="small" [account]="account" [user]="user"
|
||||||
|
(userChanged)="onUserChanged()" (userDeleted)="onUserDeleted()"
|
||||||
|
>
|
||||||
</my-user-moderation-dropdown>
|
</my-user-moderation-dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div i18n class="actor-followers">{{ account.followersCount }} subscribers</div>
|
<div i18n class="actor-followers">{{ account.followersCount }} subscribers</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
|
<th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
|
||||||
<th i18n>Video</th>
|
<th i18n>Video</th>
|
||||||
<th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th>
|
<th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th>
|
||||||
<th style="width: 50px;"></th>
|
<th style="width: 120px;"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<th i18n pSortableColumn="name">Video name <p-sortIcon field="name"></p-sortIcon></th>
|
<th i18n pSortableColumn="name">Video name <p-sortIcon field="name"></p-sortIcon></th>
|
||||||
<th i18n>Sensitive</th>
|
<th i18n>Sensitive</th>
|
||||||
<th i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
|
<th i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
|
||||||
<th style="width: 50px;"></th>
|
<th style="width: 120px;"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,10 @@
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
<a i18n-title title="Go to the account page" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
|
||||||
{{ user.username }}
|
{{ user.username }}
|
||||||
<span *ngIf="user.blocked" class="banned-info">(banned)</span>
|
<span i18n *ngIf="user.blocked" class="banned-info">(banned)</span>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ user.email }}</td>
|
<td>{{ user.email }}</td>
|
||||||
<td>{{ user.videoQuotaUsed }} / {{ user.videoQuota }}</td>
|
<td>{{ user.videoQuotaUsed }} / {{ user.videoQuota }}</td>
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<div class="admin-sub-header">
|
||||||
|
<div i18n class="form-sub-title">Muted accounts</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p-table
|
||||||
|
[value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
|
||||||
|
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
|
||||||
|
>
|
||||||
|
|
||||||
|
<ng-template pTemplate="header">
|
||||||
|
<tr>
|
||||||
|
<th i18n>Account</th>
|
||||||
|
<th i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template pTemplate="body" let-accountBlock>
|
||||||
|
<tr>
|
||||||
|
<td>{{ accountBlock.blockedAccount.nameWithHost }}</td>
|
||||||
|
<td>{{ accountBlock.createdAt }}</td>
|
||||||
|
<td class="action-cell">
|
||||||
|
<button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
</p-table>
|
|
@ -0,0 +1,7 @@
|
||||||
|
@import '_variables';
|
||||||
|
@import '_mixins';
|
||||||
|
|
||||||
|
.unblock-button {
|
||||||
|
@include peertube-button;
|
||||||
|
@include grey-button;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { Component, OnInit } from '@angular/core'
|
||||||
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
import { RestPagination, RestTable } from '@app/shared'
|
||||||
|
import { SortMeta } from 'primeng/components/common/sortmeta'
|
||||||
|
import { BlocklistService, AccountBlock } from '@app/shared/blocklist'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-account-blocklist',
|
||||||
|
styleUrls: [ './my-account-blocklist.component.scss' ],
|
||||||
|
templateUrl: './my-account-blocklist.component.html'
|
||||||
|
})
|
||||||
|
export class MyAccountBlocklistComponent extends RestTable implements OnInit {
|
||||||
|
blockedAccounts: AccountBlock[] = []
|
||||||
|
totalRecords = 0
|
||||||
|
rowsPerPage = 10
|
||||||
|
sort: SortMeta = { field: 'createdAt', order: -1 }
|
||||||
|
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private notificationsService: NotificationsService,
|
||||||
|
private blocklistService: BlocklistService,
|
||||||
|
private i18n: I18n
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
this.initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
unblockAccount (accountBlock: AccountBlock) {
|
||||||
|
const blockedAccount = accountBlock.blockedAccount
|
||||||
|
|
||||||
|
this.blocklistService.unblockAccountByUser(blockedAccount)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected loadData () {
|
||||||
|
return this.blocklistService.getUserAccountBlocklist(this.pagination, this.sort)
|
||||||
|
.subscribe(
|
||||||
|
resultList => {
|
||||||
|
this.blockedAccounts = resultList.data
|
||||||
|
this.totalRecords = resultList.total
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<div class="admin-sub-header">
|
||||||
|
<div i18n class="form-sub-title">Muted instances</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p-table
|
||||||
|
[value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
|
||||||
|
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
|
||||||
|
>
|
||||||
|
|
||||||
|
<ng-template pTemplate="header">
|
||||||
|
<tr>
|
||||||
|
<th i18n>Instance</th>
|
||||||
|
<th i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template pTemplate="body" let-serverBlock>
|
||||||
|
<tr>
|
||||||
|
<td>{{ serverBlock.blockedServer.host }}</td>
|
||||||
|
<td>{{ serverBlock.createdAt }}</td>
|
||||||
|
<td class="action-cell">
|
||||||
|
<button class="unblock-button" (click)="unblockServer(serverBlock)" i18n>Unmute</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
</p-table>
|
|
@ -0,0 +1,7 @@
|
||||||
|
@import '_variables';
|
||||||
|
@import '_mixins';
|
||||||
|
|
||||||
|
.unblock-button {
|
||||||
|
@include peertube-button;
|
||||||
|
@include grey-button;
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { Component, OnInit } from '@angular/core'
|
||||||
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
import { RestPagination, RestTable } from '@app/shared'
|
||||||
|
import { SortMeta } from 'primeng/components/common/sortmeta'
|
||||||
|
import { ServerBlock } from '../../../../../shared'
|
||||||
|
import { BlocklistService } from '@app/shared/blocklist'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-account-server-blocklist',
|
||||||
|
styleUrls: [ './my-account-server-blocklist.component.scss' ],
|
||||||
|
templateUrl: './my-account-server-blocklist.component.html'
|
||||||
|
})
|
||||||
|
export class MyAccountServerBlocklistComponent extends RestTable implements OnInit {
|
||||||
|
blockedAccounts: ServerBlock[] = []
|
||||||
|
totalRecords = 0
|
||||||
|
rowsPerPage = 10
|
||||||
|
sort: SortMeta = { field: 'createdAt', order: -1 }
|
||||||
|
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private notificationsService: NotificationsService,
|
||||||
|
private blocklistService: BlocklistService,
|
||||||
|
private i18n: I18n
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
this.initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
unblockServer (serverBlock: ServerBlock) {
|
||||||
|
const host = serverBlock.blockedServer.host
|
||||||
|
|
||||||
|
this.blocklistService.unblockServerByUser(host)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('Instance {{host}} unmuted.', { host })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected loadData () {
|
||||||
|
return this.blocklistService.getUserServerBlocklist(this.pagination, this.sort)
|
||||||
|
.subscribe(
|
||||||
|
resultList => {
|
||||||
|
this.blockedAccounts = resultList.data
|
||||||
|
this.totalRecords = resultList.total
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ import { MyAccountVideoChannelUpdateComponent } from '@app/+my-account/my-accoun
|
||||||
import { MyAccountVideoImportsComponent } from '@app/+my-account/my-account-video-imports/my-account-video-imports.component'
|
import { MyAccountVideoImportsComponent } from '@app/+my-account/my-account-video-imports/my-account-video-imports.component'
|
||||||
import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-subscriptions/my-account-subscriptions.component'
|
import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-subscriptions/my-account-subscriptions.component'
|
||||||
import { MyAccountOwnershipComponent } from '@app/+my-account/my-account-ownership/my-account-ownership.component'
|
import { MyAccountOwnershipComponent } from '@app/+my-account/my-account-ownership/my-account-ownership.component'
|
||||||
|
import { MyAccountBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-blocklist.component'
|
||||||
|
import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-server-blocklist.component'
|
||||||
|
|
||||||
const myAccountRoutes: Routes = [
|
const myAccountRoutes: Routes = [
|
||||||
{
|
{
|
||||||
|
@ -94,6 +96,24 @@ const myAccountRoutes: Routes = [
|
||||||
title: 'Ownership changes'
|
title: 'Ownership changes'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'blocklist/accounts',
|
||||||
|
component: MyAccountBlocklistComponent,
|
||||||
|
data: {
|
||||||
|
meta: {
|
||||||
|
title: 'Accounts blocklist'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'blocklist/servers',
|
||||||
|
component: MyAccountServerBlocklistComponent,
|
||||||
|
data: {
|
||||||
|
meta: {
|
||||||
|
title: 'Instances blocklist'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a i18n routerLink="/my-account/ownership" routerLinkActive="active" class="title-page">Ownership changes</a>
|
<div ngbDropdown class="misc">
|
||||||
|
<span role="button" class="title-page" [ngClass]="{ active: miscLabel !== '' }" ngbDropdownToggle>
|
||||||
|
<ng-container i18n>Misc</ng-container>
|
||||||
|
<ng-container *ngIf="miscLabel"> - {{ miscLabel }}</ng-container>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div ngbDropdownMenu>
|
||||||
|
<a class="dropdown-item" i18n routerLink="/my-account/blocklist/accounts">Muted accounts</a>
|
||||||
|
|
||||||
|
<a class="dropdown-item" i18n routerLink="/my-account/blocklist/servers">Muted instances</a>
|
||||||
|
|
||||||
|
<a class="dropdown-item" i18n routerLink="/my-account/ownership">Ownership changes</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="margin-content">
|
<div class="margin-content">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.my-library {
|
.my-library, .misc {
|
||||||
span[role=button] {
|
span[role=button] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { Subscription } from 'rxjs'
|
||||||
export class MyAccountComponent implements OnInit, OnDestroy {
|
export class MyAccountComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
libraryLabel = ''
|
libraryLabel = ''
|
||||||
|
miscLabel = ''
|
||||||
|
|
||||||
private routeSub: Subscription
|
private routeSub: Subscription
|
||||||
|
|
||||||
|
@ -23,11 +24,11 @@ export class MyAccountComponent implements OnInit, OnDestroy {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.updateLibraryLabel(this.router.url)
|
this.updateLabels(this.router.url)
|
||||||
|
|
||||||
this.routeSub = this.router.events
|
this.routeSub = this.router.events
|
||||||
.pipe(filter(event => event instanceof NavigationStart))
|
.pipe(filter(event => event instanceof NavigationStart))
|
||||||
.subscribe((event: NavigationStart) => this.updateLibraryLabel(event.url))
|
.subscribe((event: NavigationStart) => this.updateLabels(event.url))
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
ngOnDestroy () {
|
||||||
|
@ -40,7 +41,7 @@ export class MyAccountComponent implements OnInit, OnDestroy {
|
||||||
return importConfig.http.enabled || importConfig.torrent.enabled
|
return importConfig.http.enabled || importConfig.torrent.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateLibraryLabel (url: string) {
|
private updateLabels (url: string) {
|
||||||
const [ path ] = url.split('?')
|
const [ path ] = url.split('?')
|
||||||
|
|
||||||
if (path.startsWith('/my-account/video-channels')) {
|
if (path.startsWith('/my-account/video-channels')) {
|
||||||
|
@ -54,5 +55,13 @@ export class MyAccountComponent implements OnInit, OnDestroy {
|
||||||
} else {
|
} else {
|
||||||
this.libraryLabel = ''
|
this.libraryLabel = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.startsWith('/my-account/blocklist/accounts')) {
|
||||||
|
this.miscLabel = this.i18n('Muted accounts')
|
||||||
|
} else if (path.startsWith('/my-account/blocklist/servers')) {
|
||||||
|
this.miscLabel = this.i18n('Muted instances')
|
||||||
|
} else {
|
||||||
|
this.miscLabel = ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import { ActorAvatarInfoComponent } from '@app/+my-account/shared/actor-avatar-i
|
||||||
import { MyAccountVideoImportsComponent } from '@app/+my-account/my-account-video-imports/my-account-video-imports.component'
|
import { MyAccountVideoImportsComponent } from '@app/+my-account/my-account-video-imports/my-account-video-imports.component'
|
||||||
import { MyAccountDangerZoneComponent } from '@app/+my-account/my-account-settings/my-account-danger-zone'
|
import { MyAccountDangerZoneComponent } from '@app/+my-account/my-account-settings/my-account-danger-zone'
|
||||||
import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-subscriptions/my-account-subscriptions.component'
|
import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-subscriptions/my-account-subscriptions.component'
|
||||||
|
import { MyAccountBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-blocklist.component'
|
||||||
|
import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-server-blocklist.component'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -45,7 +47,9 @@ import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-sub
|
||||||
ActorAvatarInfoComponent,
|
ActorAvatarInfoComponent,
|
||||||
MyAccountVideoImportsComponent,
|
MyAccountVideoImportsComponent,
|
||||||
MyAccountDangerZoneComponent,
|
MyAccountDangerZoneComponent,
|
||||||
MyAccountSubscriptionsComponent
|
MyAccountSubscriptionsComponent,
|
||||||
|
MyAccountBlocklistComponent,
|
||||||
|
MyAccountServerBlocklistComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
exports: [
|
exports: [
|
||||||
|
|
|
@ -5,6 +5,8 @@ export class Account extends Actor implements ServerAccount {
|
||||||
displayName: string
|
displayName: string
|
||||||
description: string
|
description: string
|
||||||
nameWithHost: string
|
nameWithHost: string
|
||||||
|
muted: boolean
|
||||||
|
mutedServer: boolean
|
||||||
|
|
||||||
userId?: number
|
userId?: number
|
||||||
|
|
||||||
|
@ -15,5 +17,8 @@ export class Account extends Actor implements ServerAccount {
|
||||||
this.description = hash.description
|
this.description = hash.description
|
||||||
this.userId = hash.userId
|
this.userId = hash.userId
|
||||||
this.nameWithHost = Actor.CREATE_BY_STRING(this.name, this.host)
|
this.nameWithHost = Actor.CREATE_BY_STRING(this.name, this.host)
|
||||||
|
|
||||||
|
this.muted = false
|
||||||
|
this.mutedServer = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { AccountBlock as AccountBlockServer } from '../../../../../shared'
|
||||||
|
import { Account } from '../account/account.model'
|
||||||
|
|
||||||
|
export class AccountBlock implements AccountBlockServer {
|
||||||
|
byAccount: Account
|
||||||
|
blockedAccount: Account
|
||||||
|
createdAt: Date | string
|
||||||
|
|
||||||
|
constructor (block: AccountBlockServer) {
|
||||||
|
this.byAccount = new Account(block.byAccount)
|
||||||
|
this.blockedAccount = new Account(block.blockedAccount)
|
||||||
|
this.createdAt = block.createdAt
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { environment } from '../../../environments/environment'
|
||||||
|
import { HttpClient, HttpParams } from '@angular/common/http'
|
||||||
|
import { RestExtractor, RestPagination, RestService } from '../rest'
|
||||||
|
import { SortMeta } from 'primeng/api'
|
||||||
|
import { catchError, map } from 'rxjs/operators'
|
||||||
|
import { AccountBlock as AccountBlockServer, ResultList, ServerBlock } from '../../../../../shared'
|
||||||
|
import { Account } from '@app/shared/account/account.model'
|
||||||
|
import { AccountBlock } from '@app/shared/blocklist/account-block.model'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BlocklistService {
|
||||||
|
static BASE_USER_BLOCKLIST_URL = environment.apiUrl + '/api/v1/users/me/blocklist'
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private authHttp: HttpClient,
|
||||||
|
private restExtractor: RestExtractor,
|
||||||
|
private restService: RestService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
/*********************** User -> Account blocklist ***********************/
|
||||||
|
|
||||||
|
getUserAccountBlocklist (pagination: RestPagination, sort: SortMeta) {
|
||||||
|
let params = new HttpParams()
|
||||||
|
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||||
|
|
||||||
|
return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts', { params })
|
||||||
|
.pipe(
|
||||||
|
map(res => this.restExtractor.convertResultListDateToHuman(res)),
|
||||||
|
map(res => this.restExtractor.applyToResultListData(res, this.formatAccountBlock.bind(this))),
|
||||||
|
catchError(err => this.restExtractor.handleError(err))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
blockAccountByUser (account: Account) {
|
||||||
|
const body = { accountName: account.nameWithHost }
|
||||||
|
|
||||||
|
return this.authHttp.post(BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts', body)
|
||||||
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
unblockAccountByUser (account: Account) {
|
||||||
|
const path = BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts/' + account.nameWithHost
|
||||||
|
|
||||||
|
return this.authHttp.delete(path)
|
||||||
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************** User -> Server blocklist ***********************/
|
||||||
|
|
||||||
|
getUserServerBlocklist (pagination: RestPagination, sort: SortMeta) {
|
||||||
|
let params = new HttpParams()
|
||||||
|
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||||
|
|
||||||
|
return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/servers', { params })
|
||||||
|
.pipe(
|
||||||
|
map(res => this.restExtractor.convertResultListDateToHuman(res)),
|
||||||
|
catchError(err => this.restExtractor.handleError(err))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
blockServerByUser (host: string) {
|
||||||
|
const body = { host }
|
||||||
|
|
||||||
|
return this.authHttp.post(BlocklistService.BASE_USER_BLOCKLIST_URL + '/servers', body)
|
||||||
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
unblockServerByUser (host: string) {
|
||||||
|
const path = BlocklistService.BASE_USER_BLOCKLIST_URL + '/servers/' + host
|
||||||
|
|
||||||
|
return this.authHttp.delete(path)
|
||||||
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatAccountBlock (accountBlock: AccountBlockServer) {
|
||||||
|
return new AccountBlock(accountBlock)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './blocklist.service'
|
||||||
|
export * from './account-block.model'
|
|
@ -9,13 +9,13 @@
|
||||||
|
|
||||||
<div ngbDropdownMenu class="dropdown-menu">
|
<div ngbDropdownMenu class="dropdown-menu">
|
||||||
<ng-container *ngFor="let action of actions">
|
<ng-container *ngFor="let action of actions">
|
||||||
<div class="dropdown-item" *ngIf="action.isDisplayed === undefined || action.isDisplayed(entry) === true">
|
<ng-container *ngIf="action.isDisplayed === undefined || action.isDisplayed(entry) === true">
|
||||||
<a *ngIf="action.linkBuilder" class="dropdown-item" [routerLink]="action.linkBuilder(entry)">{{ action.label }}</a>
|
<a *ngIf="action.linkBuilder" class="dropdown-item" [routerLink]="action.linkBuilder(entry)">{{ action.label }}</a>
|
||||||
|
|
||||||
<span *ngIf="!action.linkBuilder" class="custom-action" class="dropdown-item" (click)="action.handler(entry)" role="button">
|
<span *ngIf="!action.linkBuilder" class="custom-action dropdown-item" (click)="action.handler(entry)" role="button">
|
||||||
{{ action.label }}
|
{{ action.label }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -46,5 +46,10 @@
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #000 !important;
|
color: #000 !important;
|
||||||
|
|
||||||
|
a, span {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
<ng-container *ngIf="user && userActions.length !== 0">
|
<ng-container *ngIf="userActions.length !== 0">
|
||||||
<my-user-ban-modal #userBanModal (userBanned)="onUserBanned()"></my-user-ban-modal>
|
<my-user-ban-modal #userBanModal (userBanned)="onUserBanned()"></my-user-ban-modal>
|
||||||
|
|
||||||
<my-action-dropdown [actions]="userActions" [entry]="user" [buttonSize]="buttonSize" [placement]="placement"></my-action-dropdown>
|
<my-action-dropdown
|
||||||
|
[actions]="userActions" [entry]="{ user: user, account: account }"
|
||||||
|
[buttonSize]="buttonSize" [placement]="placement"
|
||||||
|
></my-action-dropdown>
|
||||||
</ng-container>
|
</ng-container>
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
|
import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
||||||
|
@ -6,16 +6,20 @@ import { UserBanModalComponent } from '@app/shared/moderation/user-ban-modal.com
|
||||||
import { UserService } from '@app/shared/users'
|
import { UserService } from '@app/shared/users'
|
||||||
import { AuthService, ConfirmService } from '@app/core'
|
import { AuthService, ConfirmService } from '@app/core'
|
||||||
import { User, UserRight } from '../../../../../shared/models/users'
|
import { User, UserRight } from '../../../../../shared/models/users'
|
||||||
|
import { Account } from '@app/shared/account/account.model'
|
||||||
|
import { BlocklistService } from '@app/shared/blocklist'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-user-moderation-dropdown',
|
selector: 'my-user-moderation-dropdown',
|
||||||
templateUrl: './user-moderation-dropdown.component.html',
|
templateUrl: './user-moderation-dropdown.component.html',
|
||||||
styleUrls: [ './user-moderation-dropdown.component.scss' ]
|
styleUrls: [ './user-moderation-dropdown.component.scss' ]
|
||||||
})
|
})
|
||||||
export class UserModerationDropdownComponent implements OnInit {
|
export class UserModerationDropdownComponent implements OnChanges {
|
||||||
@ViewChild('userBanModal') userBanModal: UserBanModalComponent
|
@ViewChild('userBanModal') userBanModal: UserBanModalComponent
|
||||||
|
|
||||||
@Input() user: User
|
@Input() user: User
|
||||||
|
@Input() account: Account
|
||||||
|
|
||||||
@Input() buttonSize: 'normal' | 'small' = 'normal'
|
@Input() buttonSize: 'normal' | 'small' = 'normal'
|
||||||
@Input() placement = 'left'
|
@Input() placement = 'left'
|
||||||
|
|
||||||
|
@ -29,10 +33,11 @@ export class UserModerationDropdownComponent implements OnInit {
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private confirmService: ConfirmService,
|
private confirmService: ConfirmService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
private blocklistService: BlocklistService,
|
||||||
private i18n: I18n
|
private i18n: I18n
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnChanges () {
|
||||||
this.buildActions()
|
this.buildActions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +97,74 @@ export class UserModerationDropdownComponent implements OnInit {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blockAccountByUser (account: Account) {
|
||||||
|
this.blocklistService.blockAccountByUser(account)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('Account {{nameWithHost}} muted.', { nameWithHost: account.nameWithHost })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.account.muted = true
|
||||||
|
this.userChanged.emit()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
unblockAccountByUser (account: Account) {
|
||||||
|
this.blocklistService.unblockAccountByUser(account)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: account.nameWithHost })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.account.muted = false
|
||||||
|
this.userChanged.emit()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
blockServerByUser (host: string) {
|
||||||
|
this.blocklistService.blockServerByUser(host)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('Instance {{host}} muted.', { host })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.account.mutedServer = true
|
||||||
|
this.userChanged.emit()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
unblockServerByUser (host: string) {
|
||||||
|
this.blocklistService.unblockServerByUser(host)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('Instance {{host}} unmuted.', { host })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.account.mutedServer = false
|
||||||
|
this.userChanged.emit()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
getRouterUserEditLink (user: User) {
|
getRouterUserEditLink (user: User) {
|
||||||
return [ '/admin', 'users', 'update', user.id ]
|
return [ '/admin', 'users', 'update', user.id ]
|
||||||
}
|
}
|
||||||
|
@ -102,25 +175,53 @@ export class UserModerationDropdownComponent implements OnInit {
|
||||||
if (this.authService.isLoggedIn()) {
|
if (this.authService.isLoggedIn()) {
|
||||||
const authUser = this.authService.getUser()
|
const authUser = this.authService.getUser()
|
||||||
|
|
||||||
if (authUser.hasRight(UserRight.MANAGE_USERS)) {
|
if (this.user && authUser.id === this.user.id) return
|
||||||
|
|
||||||
|
if (this.user && authUser.hasRight(UserRight.MANAGE_USERS)) {
|
||||||
this.userActions = this.userActions.concat([
|
this.userActions = this.userActions.concat([
|
||||||
{
|
{
|
||||||
label: this.i18n('Edit'),
|
label: this.i18n('Edit'),
|
||||||
linkBuilder: this.getRouterUserEditLink
|
linkBuilder: ({ user }) => this.getRouterUserEditLink(user)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.i18n('Delete'),
|
label: this.i18n('Delete'),
|
||||||
handler: user => this.removeUser(user)
|
handler: ({ user }) => this.removeUser(user)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.i18n('Ban'),
|
label: this.i18n('Ban'),
|
||||||
handler: user => this.openBanUserModal(user),
|
handler: ({ user }) => this.openBanUserModal(user),
|
||||||
isDisplayed: user => !user.blocked
|
isDisplayed: ({ user }) => !user.muted
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.i18n('Unban'),
|
label: this.i18n('Unban'),
|
||||||
handler: user => this.unbanUser(user),
|
handler: ({ user }) => this.unbanUser(user),
|
||||||
isDisplayed: user => user.blocked
|
isDisplayed: ({ user }) => user.muted
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
// User actions on accounts/servers
|
||||||
|
if (this.account) {
|
||||||
|
this.userActions = this.userActions.concat([
|
||||||
|
{
|
||||||
|
label: this.i18n('Mute this account'),
|
||||||
|
isDisplayed: ({ account }) => account.muted === false,
|
||||||
|
handler: ({ account }) => this.blockAccountByUser(account)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.i18n('Unmute this account'),
|
||||||
|
isDisplayed: ({ account }) => account.muted === true,
|
||||||
|
handler: ({ account }) => this.unblockAccountByUser(account)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.i18n('Mute the instance'),
|
||||||
|
isDisplayed: ({ account }) => !account.userId && account.mutedServer === false,
|
||||||
|
handler: ({ account }) => this.blockServerByUser(account.host)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.i18n('Unmute the instance'),
|
||||||
|
isDisplayed: ({ account }) => !account.userId && account.mutedServer === true,
|
||||||
|
handler: ({ account }) => this.unblockServerByUser(account.host)
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-fe
|
||||||
import { OverviewService } from '@app/shared/overview'
|
import { OverviewService } from '@app/shared/overview'
|
||||||
import { UserBanModalComponent } from '@app/shared/moderation'
|
import { UserBanModalComponent } from '@app/shared/moderation'
|
||||||
import { UserModerationDropdownComponent } from '@app/shared/moderation/user-moderation-dropdown.component'
|
import { UserModerationDropdownComponent } from '@app/shared/moderation/user-moderation-dropdown.component'
|
||||||
|
import { BlocklistService } from '@app/shared/blocklist'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -172,6 +173,7 @@ import { UserModerationDropdownComponent } from '@app/shared/moderation/user-mod
|
||||||
OverviewService,
|
OverviewService,
|
||||||
VideoChangeOwnershipValidatorsService,
|
VideoChangeOwnershipValidatorsService,
|
||||||
VideoAcceptOwnershipValidatorsService,
|
VideoAcceptOwnershipValidatorsService,
|
||||||
|
BlocklistService,
|
||||||
|
|
||||||
I18nPrimengCalendarService,
|
I18nPrimengCalendarService,
|
||||||
ScreenService,
|
ScreenService,
|
||||||
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
asyncRetryTransactionMiddleware,
|
asyncRetryTransactionMiddleware,
|
||||||
authenticate,
|
authenticate,
|
||||||
paginationValidator,
|
paginationValidator,
|
||||||
serverGetValidator,
|
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
setDefaultSort,
|
setDefaultSort,
|
||||||
unblockAccountByAccountValidator
|
unblockAccountByAccountValidator
|
||||||
|
@ -14,6 +13,7 @@ import {
|
||||||
import {
|
import {
|
||||||
accountsBlocklistSortValidator,
|
accountsBlocklistSortValidator,
|
||||||
blockAccountByAccountValidator,
|
blockAccountByAccountValidator,
|
||||||
|
blockServerByAccountValidator,
|
||||||
serversBlocklistSortValidator,
|
serversBlocklistSortValidator,
|
||||||
unblockServerByAccountValidator
|
unblockServerByAccountValidator
|
||||||
} from '../../../middlewares/validators'
|
} from '../../../middlewares/validators'
|
||||||
|
@ -58,7 +58,7 @@ myBlocklistRouter.get('/me/blocklist/servers',
|
||||||
|
|
||||||
myBlocklistRouter.post('/me/blocklist/servers',
|
myBlocklistRouter.post('/me/blocklist/servers',
|
||||||
authenticate,
|
authenticate,
|
||||||
asyncMiddleware(serverGetValidator),
|
asyncMiddleware(blockServerByAccountValidator),
|
||||||
asyncRetryTransactionMiddleware(blockServer)
|
asyncRetryTransactionMiddleware(blockServer)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ServerBlocklistModel } from '../models/server/server-blocklist'
|
||||||
|
|
||||||
function addAccountInBlocklist (byAccountId: number, targetAccountId: number) {
|
function addAccountInBlocklist (byAccountId: number, targetAccountId: number) {
|
||||||
return sequelizeTypescript.transaction(async t => {
|
return sequelizeTypescript.transaction(async t => {
|
||||||
return AccountBlocklistModel.create({
|
return AccountBlocklistModel.upsert({
|
||||||
accountId: byAccountId,
|
accountId: byAccountId,
|
||||||
targetAccountId: targetAccountId
|
targetAccountId: targetAccountId
|
||||||
}, { transaction: t })
|
}, { transaction: t })
|
||||||
|
@ -13,7 +13,7 @@ function addAccountInBlocklist (byAccountId: number, targetAccountId: number) {
|
||||||
|
|
||||||
function addServerInBlocklist (byAccountId: number, targetServerId: number) {
|
function addServerInBlocklist (byAccountId: number, targetServerId: number) {
|
||||||
return sequelizeTypescript.transaction(async t => {
|
return sequelizeTypescript.transaction(async t => {
|
||||||
return ServerBlocklistModel.create({
|
return ServerBlocklistModel.upsert({
|
||||||
accountId: byAccountId,
|
accountId: byAccountId,
|
||||||
targetServerId
|
targetServerId
|
||||||
}, { transaction: t })
|
}, { transaction: t })
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { param, body } from 'express-validator/check'
|
import { body, param } from 'express-validator/check'
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { logger } from '../../helpers/logger'
|
import { logger } from '../../helpers/logger'
|
||||||
import { areValidationErrors } from './utils'
|
import { areValidationErrors } from './utils'
|
||||||
|
@ -7,6 +7,8 @@ import { UserModel } from '../../models/account/user'
|
||||||
import { AccountBlocklistModel } from '../../models/account/account-blocklist'
|
import { AccountBlocklistModel } from '../../models/account/account-blocklist'
|
||||||
import { isHostValid } from '../../helpers/custom-validators/servers'
|
import { isHostValid } from '../../helpers/custom-validators/servers'
|
||||||
import { ServerBlocklistModel } from '../../models/server/server-blocklist'
|
import { ServerBlocklistModel } from '../../models/server/server-blocklist'
|
||||||
|
import { ServerModel } from '../../models/server/server'
|
||||||
|
import { CONFIG } from '../../initializers'
|
||||||
|
|
||||||
const blockAccountByAccountValidator = [
|
const blockAccountByAccountValidator = [
|
||||||
body('accountName').exists().withMessage('Should have an account name with host'),
|
body('accountName').exists().withMessage('Should have an account name with host'),
|
||||||
|
@ -17,6 +19,17 @@ const blockAccountByAccountValidator = [
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
if (!await isAccountNameWithHostExist(req.body.accountName, res)) return
|
if (!await isAccountNameWithHostExist(req.body.accountName, res)) return
|
||||||
|
|
||||||
|
const user = res.locals.oauth.token.User as UserModel
|
||||||
|
const accountToBlock = res.locals.account
|
||||||
|
|
||||||
|
if (user.Account.id === accountToBlock.id) {
|
||||||
|
res.status(409)
|
||||||
|
.send({ error: 'You cannot block yourself.' })
|
||||||
|
.end()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -38,6 +51,35 @@ const unblockAccountByAccountValidator = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const blockServerByAccountValidator = [
|
||||||
|
body('host').custom(isHostValid).withMessage('Should have a valid host'),
|
||||||
|
|
||||||
|
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
|
logger.debug('Checking serverGetValidator parameters', { parameters: req.body })
|
||||||
|
|
||||||
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
const host: string = req.body.host
|
||||||
|
|
||||||
|
if (host === CONFIG.WEBSERVER.HOST) {
|
||||||
|
return res.status(409)
|
||||||
|
.send({ error: 'You cannot block your own server.' })
|
||||||
|
.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = await ServerModel.loadByHost(host)
|
||||||
|
if (!server) {
|
||||||
|
return res.status(404)
|
||||||
|
.send({ error: 'Server host not found.' })
|
||||||
|
.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
res.locals.server = server
|
||||||
|
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const unblockServerByAccountValidator = [
|
const unblockServerByAccountValidator = [
|
||||||
param('host').custom(isHostValid).withMessage('Should have an account name with host'),
|
param('host').custom(isHostValid).withMessage('Should have an account name with host'),
|
||||||
|
|
||||||
|
@ -56,6 +98,7 @@ const unblockServerByAccountValidator = [
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
blockServerByAccountValidator,
|
||||||
blockAccountByAccountValidator,
|
blockAccountByAccountValidator,
|
||||||
unblockAccountByAccountValidator,
|
unblockAccountByAccountValidator,
|
||||||
unblockServerByAccountValidator
|
unblockServerByAccountValidator
|
||||||
|
|
|
@ -18,7 +18,7 @@ enum ScopeNames {
|
||||||
{
|
{
|
||||||
model: () => AccountModel,
|
model: () => AccountModel,
|
||||||
required: true,
|
required: true,
|
||||||
as: 'AccountBlocked'
|
as: 'BlockedAccount'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -67,10 +67,10 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
|
||||||
name: 'targetAccountId',
|
name: 'targetAccountId',
|
||||||
allowNull: false
|
allowNull: false
|
||||||
},
|
},
|
||||||
as: 'AccountBlocked',
|
as: 'BlockedAccount',
|
||||||
onDelete: 'CASCADE'
|
onDelete: 'CASCADE'
|
||||||
})
|
})
|
||||||
AccountBlocked: AccountModel
|
BlockedAccount: AccountModel
|
||||||
|
|
||||||
static loadByAccountAndTarget (accountId: number, targetAccountId: number) {
|
static loadByAccountAndTarget (accountId: number, targetAccountId: number) {
|
||||||
const query = {
|
const query = {
|
||||||
|
@ -104,7 +104,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
|
||||||
toFormattedJSON (): AccountBlock {
|
toFormattedJSON (): AccountBlock {
|
||||||
return {
|
return {
|
||||||
byAccount: this.ByAccount.toFormattedJSON(),
|
byAccount: this.ByAccount.toFormattedJSON(),
|
||||||
accountBlocked: this.AccountBlocked.toFormattedJSON(),
|
blockedAccount: this.BlockedAccount.toFormattedJSON(),
|
||||||
createdAt: this.createdAt
|
createdAt: this.createdAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
|
||||||
},
|
},
|
||||||
onDelete: 'CASCADE'
|
onDelete: 'CASCADE'
|
||||||
})
|
})
|
||||||
ServerBlocked: ServerModel
|
BlockedServer: ServerModel
|
||||||
|
|
||||||
static loadByAccountAndHost (accountId: number, host: string) {
|
static loadByAccountAndHost (accountId: number, host: string) {
|
||||||
const query = {
|
const query = {
|
||||||
|
@ -114,7 +114,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
|
||||||
toFormattedJSON (): ServerBlock {
|
toFormattedJSON (): ServerBlock {
|
||||||
return {
|
return {
|
||||||
byAccount: this.ByAccount.toFormattedJSON(),
|
byAccount: this.ByAccount.toFormattedJSON(),
|
||||||
serverBlocked: this.ServerBlocked.toFormattedJSON(),
|
blockedServer: this.BlockedServer.toFormattedJSON(),
|
||||||
createdAt: this.createdAt
|
createdAt: this.createdAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,16 @@ describe('Test blocklist API validators', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should fail to block ourselves', async function () {
|
||||||
|
await makePostBodyRequest({
|
||||||
|
url: server.url,
|
||||||
|
token: server.accessToken,
|
||||||
|
path,
|
||||||
|
fields: { accountName: 'root' },
|
||||||
|
statusCodeExpected: 409
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('Should succeed with the correct params', async function () {
|
it('Should succeed with the correct params', async function () {
|
||||||
await makePostBodyRequest({
|
await makePostBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
|
@ -170,6 +180,16 @@ describe('Test blocklist API validators', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should fail with our own server', async function () {
|
||||||
|
await makePostBodyRequest({
|
||||||
|
url: server.url,
|
||||||
|
token: server.accessToken,
|
||||||
|
path,
|
||||||
|
fields: { host: 'localhost:9001' },
|
||||||
|
statusCodeExpected: 409
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('Should succeed with the correct params', async function () {
|
it('Should succeed with the correct params', async function () {
|
||||||
await makePostBodyRequest({
|
await makePostBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
|
|
|
@ -183,9 +183,9 @@ describe('Test accounts blocklist', function () {
|
||||||
const block = blocks[0]
|
const block = blocks[0]
|
||||||
expect(block.byAccount.displayName).to.equal('root')
|
expect(block.byAccount.displayName).to.equal('root')
|
||||||
expect(block.byAccount.name).to.equal('root')
|
expect(block.byAccount.name).to.equal('root')
|
||||||
expect(block.accountBlocked.displayName).to.equal('user2')
|
expect(block.blockedAccount.displayName).to.equal('user2')
|
||||||
expect(block.accountBlocked.name).to.equal('user2')
|
expect(block.blockedAccount.name).to.equal('user2')
|
||||||
expect(block.accountBlocked.host).to.equal('localhost:9002')
|
expect(block.blockedAccount.host).to.equal('localhost:9002')
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -197,9 +197,9 @@ describe('Test accounts blocklist', function () {
|
||||||
const block = blocks[0]
|
const block = blocks[0]
|
||||||
expect(block.byAccount.displayName).to.equal('root')
|
expect(block.byAccount.displayName).to.equal('root')
|
||||||
expect(block.byAccount.name).to.equal('root')
|
expect(block.byAccount.name).to.equal('root')
|
||||||
expect(block.accountBlocked.displayName).to.equal('user1')
|
expect(block.blockedAccount.displayName).to.equal('user1')
|
||||||
expect(block.accountBlocked.name).to.equal('user1')
|
expect(block.blockedAccount.name).to.equal('user1')
|
||||||
expect(block.accountBlocked.host).to.equal('localhost:9001')
|
expect(block.blockedAccount.host).to.equal('localhost:9001')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ describe('Test accounts blocklist', function () {
|
||||||
const block = blocks[0]
|
const block = blocks[0]
|
||||||
expect(block.byAccount.displayName).to.equal('root')
|
expect(block.byAccount.displayName).to.equal('root')
|
||||||
expect(block.byAccount.name).to.equal('root')
|
expect(block.byAccount.name).to.equal('root')
|
||||||
expect(block.serverBlocked.host).to.equal('localhost:9002')
|
expect(block.blockedServer.host).to.equal('localhost:9002')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should unblock the remote server', async function () {
|
it('Should unblock the remote server', async function () {
|
||||||
|
|
|
@ -2,6 +2,6 @@ import { Account } from '../actors'
|
||||||
|
|
||||||
export interface AccountBlock {
|
export interface AccountBlock {
|
||||||
byAccount: Account
|
byAccount: Account
|
||||||
accountBlocked: Account
|
blockedAccount: Account
|
||||||
createdAt: Date | string
|
createdAt: Date | string
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Account } from '../actors'
|
||||||
|
|
||||||
export interface ServerBlock {
|
export interface ServerBlock {
|
||||||
byAccount: Account
|
byAccount: Account
|
||||||
serverBlocked: {
|
blockedServer: {
|
||||||
host: string
|
host: string
|
||||||
}
|
}
|
||||||
createdAt: Date | string
|
createdAt: Date | string
|
||||||
|
|
Loading…
Reference in New Issue