merge: Add option to reject reports from an instance (Resolves #579, #715, #716) (!662)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/662

Closes #579, #715, and #716

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
Marie 2024-10-06 19:39:38 +00:00
commit 28bfd87537
10 changed files with 125 additions and 2 deletions

View file

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class AddRejectReports1728177700920 {
name = 'AddRejectReports1728177700920'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "instance" ADD "rejectReports" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "rejectReports"`);
}
}

View file

@ -5,6 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm';
import * as Bull from 'bullmq';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
@ -29,6 +30,7 @@ import { bindThis } from '@/decorators.js';
import type { MiRemoteUser } from '@/models/User.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { AbuseReportService } from '@/core/AbuseReportService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
import { ApNoteService } from './models/ApNoteService.js';
import { ApLoggerService } from './ApLoggerService.js';
@ -83,6 +85,7 @@ export class ApInboxService {
private apQuestionService: ApQuestionService,
private queueService: QueueService,
private globalEventService: GlobalEventService,
private federatedInstanceService: FederatedInstanceService,
) {
this.logger = this.apLoggerService.logger;
}
@ -530,6 +533,12 @@ export class ApInboxService {
@bindThis
private async flag(actor: MiRemoteUser, activity: IFlag): Promise<string> {
// Make sure the source instance is allowed to send reports.
const instance = await this.federatedInstanceService.fetch(actor.host);
if (instance.rejectReports) {
throw new Bull.UnrecoverableError(`Rejecting report from instance: ${actor.host}`);
}
// objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので
// 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する
const uris = getApIds(activity.object);

View file

@ -158,7 +158,12 @@ export class MiInstance {
default: false,
})
public isNSFW: boolean;
@Column('boolean', {
default: false,
})
public rejectReports: boolean;
@Column('varchar', {
length: 16384, default: '',
})

View file

@ -25,6 +25,7 @@ export const paramDef = {
host: { type: 'string' },
isSuspended: { type: 'boolean' },
isNSFW: { type: 'boolean' },
rejectReports: { type: 'boolean' },
moderationNote: { type: 'string' },
},
required: ['host'],
@ -57,6 +58,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
await this.federatedInstanceService.update(instance.id, {
suspensionState,
isNSFW: ps.isNSFW,
rejectReports: ps.rejectReports,
moderationNote: ps.moderationNote,
});
@ -74,6 +76,22 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}
if (ps.isNSFW != null && instance.isNSFW !== ps.isNSFW) {
const message = ps.rejectReports ? 'setRemoteInstanceNSFW' : 'unsetRemoteInstanceNSFW';
this.moderationLogService.log(me, message, {
id: instance.id,
host: instance.host,
});
}
if (ps.rejectReports != null && instance.rejectReports !== ps.rejectReports) {
const message = ps.rejectReports ? 'rejectRemoteInstanceReports' : 'acceptRemoteInstanceReports';
this.moderationLogService.log(me, message, {
id: instance.id,
host: instance.host,
});
}
if (ps.moderationNote != null && instance.moderationNote !== ps.moderationNote) {
this.moderationLogService.log(me, 'updateRemoteInstanceNote', {
id: instance.id,

View file

@ -77,8 +77,12 @@ export const moderationLogTypes = [
'deleteGlobalAnnouncement',
'deleteUserAnnouncement',
'resetPassword',
'setRemoteInstanceNSFW',
'unsetRemoteInstanceNSFW',
'suspendRemoteInstance',
'unsuspendRemoteInstance',
'rejectRemoteInstanceReports',
'acceptRemoteInstanceReports',
'updateRemoteInstanceNote',
'markSensitiveDriveFile',
'unmarkSensitiveDriveFile',
@ -227,6 +231,14 @@ export type ModerationLogPayloads = {
userUsername: string;
userHost: string | null;
};
setRemoteInstanceNSFW: {
id: string;
host: string;
};
unsetRemoteInstanceNSFW: {
id: string;
host: string;
};
suspendRemoteInstance: {
id: string;
host: string;
@ -235,6 +247,14 @@ export type ModerationLogPayloads = {
id: string;
host: string;
};
rejectRemoteInstanceReports: {
id: string;
host: string;
};
acceptRemoteInstanceReports: {
id: string;
host: string;
};
updateRemoteInstanceNote: {
id: string;
host: string;