Link prior moderation actions to case decisions
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { db } from '../db/index.js';
|
||||
import { archivedEvidenceSnapshots } from './evidence.js';
|
||||
import { caseActionReference, recordedCaseAction, isCaseActionLinked } from './case-actions.js';
|
||||
import { AuthError } from '../auth/index.js';
|
||||
import { moderatorMaximumRestrictionMs, type AuthUser } from '../../auth.js';
|
||||
import {
|
||||
@@ -220,7 +221,13 @@ function revokeSanction(actor: AuthUser, input: Record<string, unknown>, now: st
|
||||
.run(now, id);
|
||||
advancePolicy();
|
||||
moderationEvent(actor, 'restriction.revoked', row, id, reason, now);
|
||||
if (row.case_id) touchCase(row.case_id, now);
|
||||
db()
|
||||
.prepare(
|
||||
`UPDATE moderation_cases SET updated_at=?,revision=revision+1
|
||||
WHERE id=? OR id IN (SELECT case_id FROM moderation_case_action_links
|
||||
WHERE action_type='restriction' AND action_id=?)`
|
||||
)
|
||||
.run(now, row.case_id, id);
|
||||
return { id };
|
||||
}
|
||||
function liveAction(actor: AuthUser, input: Record<string, unknown>, now: string) {
|
||||
@@ -465,6 +472,27 @@ export function mutateModeration(actorId: string, input: Record<string, unknown>
|
||||
if (input.op === 'action') return liveAction(actor, input, now);
|
||||
if (input.op === 'create-case') return createCase(actor, input, now);
|
||||
if (input.op === 'update-case') return updateCase(actor, input, now);
|
||||
if (input.op === 'link-case-action') {
|
||||
const row = caseRow(input.id);
|
||||
checkCaseRevision(row, input.revision);
|
||||
const reference = caseActionReference({ type: input.actionType, id: input.actionId });
|
||||
const reason = textField(input.reason, 'Link reason', 4000);
|
||||
recordedCaseAction(row, reference, now);
|
||||
if (isCaseActionLinked(row.id, reference)) return { id: row.id };
|
||||
db()
|
||||
.prepare('INSERT INTO moderation_case_action_links VALUES(?,?,?,?,?)')
|
||||
.run(row.id, reference.type, reference.id, actor.username, now);
|
||||
touchCase(row.id, now);
|
||||
moderationEvent(
|
||||
actor,
|
||||
'case.action_linked',
|
||||
row,
|
||||
row.id,
|
||||
JSON.stringify({ actionReference: reference, reason }),
|
||||
now
|
||||
);
|
||||
return { id: row.id };
|
||||
}
|
||||
if (input.op === 'case-note') {
|
||||
const row = caseRow(input.id);
|
||||
if (input.revision !== undefined) checkCaseRevision(row, input.revision);
|
||||
@@ -481,13 +509,43 @@ export function mutateModeration(actorId: string, input: Record<string, unknown>
|
||||
const outcome = moderationCaseOutcomes.find((status) => status === input.status);
|
||||
if (!outcome) throw new AuthError('Choose a case outcome.');
|
||||
const reason = textField(input.reason, 'Decision reason', 4000);
|
||||
const reference =
|
||||
input.actionReference === undefined || input.actionReference === null
|
||||
? null
|
||||
: caseActionReference(input.actionReference);
|
||||
if (reference) {
|
||||
const action = recordedCaseAction(row, reference, now);
|
||||
if (!isCaseActionLinked(row.id, reference))
|
||||
throw new AuthError(
|
||||
'Link the recorded action to this case before citing it.',
|
||||
409
|
||||
);
|
||||
if (
|
||||
outcome === 'warning_issued' &&
|
||||
(action.type !== 'action' ||
|
||||
action.kind !== 'warn' ||
|
||||
action.state !== 'confirmed')
|
||||
)
|
||||
throw new AuthError('Warning issued must reference a confirmed warning.');
|
||||
if (outcome === 'restriction_applied' && action.type !== 'restriction')
|
||||
throw new AuthError(
|
||||
'Restriction applied must reference a recorded restriction.'
|
||||
);
|
||||
}
|
||||
evidence(actor, row.id, reason, moderationCaseStatusLabels[outcome], null, now, true);
|
||||
db()
|
||||
.prepare(
|
||||
'UPDATE moderation_cases SET status=?,updated_at=?,revision=revision+1 WHERE id=?'
|
||||
)
|
||||
.run(outcome, now, row.id);
|
||||
moderationEvent(actor, `case.${outcome}`, row, row.id, reason, now);
|
||||
moderationEvent(
|
||||
actor,
|
||||
`case.${outcome}`,
|
||||
row,
|
||||
row.id,
|
||||
reference ? JSON.stringify({ reason, actionReference: reference }) : reason,
|
||||
now
|
||||
);
|
||||
return { id: row.id };
|
||||
}
|
||||
if (input.op === 'reopen-case') {
|
||||
|
||||
Reference in New Issue
Block a user