From 9ca504784aeebb6989403816684e541a1140cbfe Mon Sep 17 00:00:00 2001 From: Johann150 Date: Fri, 21 Jan 2022 18:37:22 +0100 Subject: [PATCH] keep URL of reported object separate Instead of putting the URL in the report text, it is stored separately so that users do not accidentally change or remove it. This way it can easily be used when forwarding reports to different instances to tell them what exactly was reported. --- .../backend/migration/1642698156335-reported-urls.js | 11 +++++++++++ .../backend/src/models/entities/abuse-user-report.ts | 5 +++++ .../src/models/repositories/abuse-user-report.ts | 1 + .../api/endpoints/admin/resolve-abuse-user-report.ts | 2 +- .../src/server/api/endpoints/users/report-abuse.ts | 9 +++++++++ packages/backend/src/server/api/stream/types.ts | 1 + .../client/src/components/abuse-report-window.vue | 5 +++-- packages/client/src/scripts/get-note-menu.ts | 4 ++-- 8 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 packages/backend/migration/1642698156335-reported-urls.js diff --git a/packages/backend/migration/1642698156335-reported-urls.js b/packages/backend/migration/1642698156335-reported-urls.js new file mode 100644 index 000000000..416b69dfb --- /dev/null +++ b/packages/backend/migration/1642698156335-reported-urls.js @@ -0,0 +1,11 @@ +export class reportedUrls1642698156335 { + name = 'reportedUrls1642698156335'; + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "urls" character varying (512) array NOT NULL DEFAULT '{}'::varchar[]`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "urls"`); + } +}; diff --git a/packages/backend/src/models/entities/abuse-user-report.ts b/packages/backend/src/models/entities/abuse-user-report.ts index 6ac563552..4f5126163 100644 --- a/packages/backend/src/models/entities/abuse-user-report.ts +++ b/packages/backend/src/models/entities/abuse-user-report.ts @@ -56,6 +56,11 @@ export class AbuseUserReport { }) public forwarded: boolean; + @Column('varchar', { + length: 512, array: true, default: '{}', + }) + public urls: string[]; + @Column('varchar', { length: 2048, }) diff --git a/packages/backend/src/models/repositories/abuse-user-report.ts b/packages/backend/src/models/repositories/abuse-user-report.ts index 36d7ab90c..d1adf3f30 100644 --- a/packages/backend/src/models/repositories/abuse-user-report.ts +++ b/packages/backend/src/models/repositories/abuse-user-report.ts @@ -27,6 +27,7 @@ export const AbuseUserReportRepository = db.getRepository(AbuseUserReport).exten detail: true, }) : null, forwarded: report.forwarded, + urls: report.urls, }); }, diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index 3edae4a85..23940ba05 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -33,7 +33,7 @@ export default define(meta, paramDef, async (ps, me) => { const actor = await getInstanceActor(); const targetUser = await Users.findOneByOrFail({ id: report.targetUserId }); - deliver(actor, renderActivity(renderFlag(actor, [targetUser.uri!], report.comment)), targetUser.inbox); + deliver(actor, renderActivity(renderFlag(actor, report.urls, report.comment)), targetUser.inbox); } await AbuseUserReports.update(report.id, { diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index a9987eafa..4ef0f0d2a 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -1,4 +1,5 @@ import * as sanitizeHtml from 'sanitize-html'; +import config from '@/config/index.js'; import { publishAdminStream } from '@/services/stream.js'; import { AbuseUserReports, Users } from '@/models/index.js'; import { genId } from '@/misc/gen-id.js'; @@ -40,6 +41,7 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, + urls: { type: 'array', items: { type: 'string' }, nullable: true, uniqueItems: true }, comment: { type: 'string', minLength: 1, maxLength: 2048 }, }, required: ['userId', 'comment'], @@ -61,6 +63,11 @@ export default define(meta, paramDef, async (ps, me) => { throw new ApiError(meta.errors.cannotReportAdmin); } + const uri = user.host == null ? `${config.url}/users/${user.id}` : user.uri; + if (!ps.urls.includes(uri)) { + ps.urls.push(uri); + } + const report = await AbuseUserReports.insert({ id: genId(), createdAt: new Date(), @@ -69,6 +76,7 @@ export default define(meta, paramDef, async (ps, me) => { reporterId: me.id, reporterHost: null, comment: ps.comment, + urls: ps.urls, }).then(x => AbuseUserReports.findOneByOrFail(x.identifiers[0])); // Publish event to moderators @@ -87,6 +95,7 @@ export default define(meta, paramDef, async (ps, me) => { targetUserId: report.targetUserId, reporterId: report.reporterId, comment: report.comment, + urls: report.urls, }); } diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index 4aa655e5b..5fdc6dfcf 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -173,6 +173,7 @@ export interface AdminStreamTypes { targetUserId: User['id'], reporterId: User['id'], comment: string; + urls: string[]; }; } //#endregion diff --git a/packages/client/src/components/abuse-report-window.vue b/packages/client/src/components/abuse-report-window.vue index 82960fa97..45c9dca8e 100644 --- a/packages/client/src/components/abuse-report-window.vue +++ b/packages/client/src/components/abuse-report-window.vue @@ -33,7 +33,7 @@ import { i18n } from '@/i18n'; const props = defineProps<{ user: Misskey.entities.User; - initialComment?: string; + urls?: string[]; }>(); const emit = defineEmits<{ @@ -41,11 +41,12 @@ const emit = defineEmits<{ }>(); const uiWindow = ref>(); -const comment = ref(props.initialComment || ''); +const comment = ref(''); function send() { os.apiWithDialog('users/report-abuse', { userId: props.user.id, + urls: props.urls || [], comment: comment.value, }).then(res => { os.alert({ diff --git a/packages/client/src/scripts/get-note-menu.ts b/packages/client/src/scripts/get-note-menu.ts index 632143f51..8f0ecbdea 100644 --- a/packages/client/src/scripts/get-note-menu.ts +++ b/packages/client/src/scripts/get-note-menu.ts @@ -291,9 +291,9 @@ export function getNoteMenu(props: { const u = appearNote.url || appearNote.uri || `${url}/notes/${appearNote.id}`; os.popup(defineAsyncComponent(() => import('@/components/abuse-report-window.vue')), { user: appearNote.user, - initialComment: `Note: ${u}\n-----\n`, + urls: [u] }, {}, 'closed'); - }, + } }] : [] ),