Link prior moderation actions to case decisions
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import { db } from '../db/index.js';
|
||||
import { AuthError } from '../auth/index.js';
|
||||
import { textField } from './core.js';
|
||||
import type { ModerationCaseAction, ModerationGame } from '../../moderation.js';
|
||||
|
||||
type Subject = { game: ModerationGame; guid: string };
|
||||
export type CaseActionReference = Pick<ModerationCaseAction, 'type' | 'id'>;
|
||||
|
||||
export function caseActionReference(value: unknown): CaseActionReference {
|
||||
if (!value || typeof value !== 'object') throw new AuthError('Choose a recorded action.');
|
||||
const reference = value as Record<string, unknown>;
|
||||
if (reference.type !== 'action' && reference.type !== 'restriction')
|
||||
throw new AuthError('Choose a recorded warning, action, or restriction.');
|
||||
return { type: reference.type, id: textField(reference.id, 'Action ID', 128) };
|
||||
}
|
||||
|
||||
const restrictionColumns = `id,'restriction' AS type,kind,reason,actor,
|
||||
created_at AS createdAt,expires_at AS expiresAt,
|
||||
CASE WHEN revoked_at IS NOT NULL THEN 'revoked'
|
||||
WHEN expires_at IS NOT NULL AND expires_at<=? THEN 'expired' ELSE 'active' END AS state`;
|
||||
const actionColumns = `id,'action' AS type,kind,reason,actor,
|
||||
created_at AS createdAt,expires_at AS expiresAt,state`;
|
||||
|
||||
/** Only actual records for this account can become case evidence. */
|
||||
export function recordedCaseAction(
|
||||
subject: Subject,
|
||||
reference: CaseActionReference,
|
||||
now: string
|
||||
): ModerationCaseAction {
|
||||
const handle = db();
|
||||
const action =
|
||||
reference.type === 'restriction'
|
||||
? handle
|
||||
.prepare(
|
||||
`SELECT ${restrictionColumns} FROM moderation_sanctions
|
||||
WHERE id=? AND guid=? AND (game=? OR scope='fleet')`
|
||||
)
|
||||
.get(now, reference.id, subject.guid, subject.game)
|
||||
: handle
|
||||
.prepare(
|
||||
`SELECT ${actionColumns} FROM moderation_actions
|
||||
WHERE id=? AND guid=? AND game=?`
|
||||
)
|
||||
.get(reference.id, subject.guid, subject.game);
|
||||
if (!action)
|
||||
throw new AuthError('The recorded action is unavailable for this case’s player.', 404);
|
||||
return action as ModerationCaseAction;
|
||||
}
|
||||
|
||||
export function isCaseActionLinked(caseId: string, reference: CaseActionReference): boolean {
|
||||
return Boolean(
|
||||
db()
|
||||
.prepare(
|
||||
`SELECT 1 FROM moderation_case_action_links
|
||||
WHERE case_id=? AND action_type=? AND action_id=?
|
||||
UNION ALL SELECT 1 FROM moderation_sanctions
|
||||
WHERE ?='restriction' AND id=? AND case_id=? LIMIT 1`
|
||||
)
|
||||
.get(caseId, reference.type, reference.id, reference.type, reference.id, caseId)
|
||||
);
|
||||
}
|
||||
|
||||
export function caseActionLists(caseId: string, subject: Subject, now: string) {
|
||||
const handle = db();
|
||||
const records = handle
|
||||
.prepare(
|
||||
`SELECT ${restrictionColumns},
|
||||
(case_id=? OR EXISTS (SELECT 1 FROM moderation_case_action_links l
|
||||
WHERE l.case_id=? AND l.action_type='restriction' AND l.action_id=moderation_sanctions.id)) AS linked
|
||||
FROM moderation_sanctions WHERE guid=? AND (game=? OR scope='fleet')
|
||||
UNION ALL SELECT ${actionColumns},
|
||||
EXISTS (SELECT 1 FROM moderation_case_action_links l
|
||||
WHERE l.case_id=? AND l.action_type='action' AND l.action_id=moderation_actions.id) AS linked
|
||||
FROM moderation_actions WHERE guid=? AND game=?
|
||||
ORDER BY createdAt DESC,id`
|
||||
)
|
||||
.all(
|
||||
now,
|
||||
caseId,
|
||||
caseId,
|
||||
subject.guid,
|
||||
subject.game,
|
||||
caseId,
|
||||
subject.guid,
|
||||
subject.game
|
||||
) as Array<ModerationCaseAction & { linked: number | null }>;
|
||||
const linkedActions: ModerationCaseAction[] = [];
|
||||
const availableActions: ModerationCaseAction[] = [];
|
||||
for (const { linked, ...record } of records)
|
||||
(linked ? linkedActions : availableActions).push(record);
|
||||
return { linkedActions, availableActions };
|
||||
}
|
||||
Reference in New Issue
Block a user