64 lines
2.8 KiB
TypeScript
64 lines
2.8 KiB
TypeScript
import {
|
|
moderationConcernCategories,
|
|
moderationFindingOutcomes,
|
|
type ModerationCaseAssessment
|
|
} from '../../moderation.js';
|
|
import { AuthError } from '../auth/index.js';
|
|
import { db } from '../db/index.js';
|
|
import { textField } from './core.js';
|
|
|
|
type AssessmentDraft = Pick<ModerationCaseAssessment, 'summary' | 'rules' | 'findings'>;
|
|
|
|
export function assessmentDraft(input: Record<string, unknown>): AssessmentDraft {
|
|
const summary = textField(input.summary, 'Assessment summary', 2000);
|
|
if (!Array.isArray(input.rules) || input.rules.length > 20)
|
|
throw new AuthError('Choose up to 20 applicable rules.');
|
|
const rules = input.rules.map((rule) => textField(rule, 'Applicable rule', 160));
|
|
if (
|
|
!Array.isArray(input.findings) ||
|
|
!input.findings.length ||
|
|
input.findings.length > moderationConcernCategories.length
|
|
)
|
|
throw new AuthError('Record between 1 and 7 findings, one per concern category.');
|
|
const categories = new Set<string>();
|
|
const findings = input.findings.map((value): AssessmentDraft['findings'][number] => {
|
|
if (!value || typeof value !== 'object')
|
|
throw new AuthError('Choose a concern category and finding.');
|
|
const category = moderationConcernCategories.find(
|
|
(category) => category === value.category
|
|
);
|
|
const finding = moderationFindingOutcomes.find((finding) => finding === value.finding);
|
|
if (!category || !finding)
|
|
throw new AuthError('Choose a known concern category and finding.');
|
|
if (categories.has(category))
|
|
throw new AuthError('Record each concern category only once.');
|
|
categories.add(category);
|
|
return { category, finding, detail: textField(value.detail, 'Finding detail', 1000) };
|
|
});
|
|
return { summary, rules, findings };
|
|
}
|
|
|
|
export function caseAssessmentHistory(caseId: string): ModerationCaseAssessment[] {
|
|
return (
|
|
db()
|
|
.prepare(
|
|
`SELECT revision,data,actor,created_at AS createdAt
|
|
FROM moderation_case_assessments WHERE case_id=? ORDER BY revision DESC`
|
|
)
|
|
.all(caseId) as { revision: number; data: string; actor: string; createdAt: string }[]
|
|
).map(({ data, ...revision }) => ({ ...JSON.parse(data), ...revision }));
|
|
}
|
|
|
|
export function currentCaseAssessment(caseId: string): ModerationCaseAssessment | null {
|
|
const row = db()
|
|
.prepare(
|
|
`SELECT revision,data,actor,created_at AS createdAt
|
|
FROM moderation_case_assessments WHERE case_id=? ORDER BY revision DESC LIMIT 1`
|
|
)
|
|
.get(caseId) as
|
|
{ revision: number; data: string; actor: string; createdAt: string } | undefined;
|
|
if (!row) return null;
|
|
const { data, ...revision } = row;
|
|
return { ...JSON.parse(data), ...revision };
|
|
}
|