Expand application functionality
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { admissionMixingScopes, buildAdmissionArrangement } from '../services/admission-arrangement.mjs';
|
||||
import { noticeForClient, noticePlainText, sanitizeNoticeContent } from '../security/notice-content.mjs';
|
||||
|
||||
export function createAdminRoutes(context) {
|
||||
const {
|
||||
@@ -1001,18 +1002,22 @@ export function createAdminRoutes(context) {
|
||||
}
|
||||
if (request.method === 'GET' && pathname === '/api/admin/notices') {
|
||||
if (!requirePermission(user, response, '*')) return true;
|
||||
return sendJson(response, 200, { ok: true, notices: db.notices.sort((a, b) => new Date(b.publishAt || b.createdAt) - new Date(a.publishAt || a.createdAt)) });
|
||||
const notices = db.notices
|
||||
.sort((a, b) => new Date(b.publishAt || b.createdAt) - new Date(a.publishAt || a.createdAt))
|
||||
.map(noticeForClient);
|
||||
return sendJson(response, 200, { ok: true, notices });
|
||||
}
|
||||
if (request.method === 'POST' && pathname === '/api/admin/notices') {
|
||||
if (!requirePermission(user, response, '*')) return true;
|
||||
const body = await readJson(request);
|
||||
const title = cleanText(body.title, 120);
|
||||
const content = cleanText(body.content, 5000);
|
||||
if (!title || !content) return sendError(response, 400, '通知标题和正文不能为空');
|
||||
const notice = { id: uid('notice'), title, summary: cleanText(body.summary, 260) || content.slice(0, 80), content, category: cleanText(body.category, 30) || '通知公告', pinned: Boolean(body.pinned), status: body.status === 'draft' ? 'draft' : 'published', publishAt: body.status === 'draft' ? null : nowIso(), createdAt: nowIso(), author: user.displayName };
|
||||
const content = sanitizeNoticeContent(body.content);
|
||||
const contentText = noticePlainText(content);
|
||||
if (!title || !contentText) return sendError(response, 400, '通知标题和正文不能为空');
|
||||
const notice = { id: uid('notice'), title, summary: cleanText(body.summary, 260) || contentText.slice(0, 80), content, category: cleanText(body.category, 30) || '通知公告', pinned: Boolean(body.pinned), status: body.status === 'draft' ? 'draft' : 'published', publishAt: body.status === 'draft' ? null : nowIso(), createdAt: nowIso(), author: user.displayName };
|
||||
const log = logAction(db, user, notice.status === 'published' ? '发布通知' : '保存通知草稿', notice.title);
|
||||
await database.createNotice(notice, log);
|
||||
return sendJson(response, 201, { ok: true, notice });
|
||||
return sendJson(response, 201, { ok: true, notice: noticeForClient(notice) });
|
||||
}
|
||||
const noticeMatch = pathname.match(/^\/api\/admin\/notices\/([^/]+)$/);
|
||||
if (request.method === 'PATCH' && noticeMatch) {
|
||||
@@ -1020,7 +1025,12 @@ export function createAdminRoutes(context) {
|
||||
const body = await readJson(request);
|
||||
const notice = db.notices.find(item => item.id === noticeMatch[1]);
|
||||
if (!notice) return sendError(response, 404, '通知不存在');
|
||||
['title', 'summary', 'content', 'category'].forEach(field => { if (body[field] != null) notice[field] = cleanText(body[field], field === 'content' ? 5000 : 260); });
|
||||
['title', 'summary', 'category'].forEach(field => { if (body[field] != null) notice[field] = cleanText(body[field], 260); });
|
||||
if (body.content != null) {
|
||||
const content = sanitizeNoticeContent(body.content);
|
||||
if (!noticePlainText(content)) return sendError(response, 400, '通知正文不能为空');
|
||||
notice.content = content;
|
||||
}
|
||||
if (body.pinned != null) notice.pinned = Boolean(body.pinned);
|
||||
if (body.status && ['draft', 'published'].includes(body.status)) {
|
||||
notice.status = body.status;
|
||||
@@ -1028,7 +1038,7 @@ export function createAdminRoutes(context) {
|
||||
}
|
||||
const log = logAction(db, user, '更新通知', `${notice.title} · ${notice.status}`);
|
||||
await database.updateNotice(notice, log);
|
||||
return sendJson(response, 200, { ok: true, notice });
|
||||
return sendJson(response, 200, { ok: true, notice: noticeForClient(notice) });
|
||||
}
|
||||
if (request.method === 'GET' && pathname === '/api/admin/results') {
|
||||
if (!requirePermission(user, response, 'results.read')) return true;
|
||||
|
||||
Reference in New Issue
Block a user