This commit is contained in:
2026-07-22 18:12:09 +08:00 Unverified
parent 56f1d7a273
commit 0b05dc2a09
12 changed files with 533 additions and 61 deletions
+12 -4
View File
@@ -13,6 +13,7 @@ import { createAuthRoutes } from './src/routes/auth.routes.mjs';
import { createPublicRoutes } from './src/routes/public.routes.mjs';
import { adminLevelNames, adminScopeLabel, createPermissionGuard, hasPermission, permissionsByLevel, profileInScope, registrationInScope } from './src/security/authorization.mjs';
import { createSessionManager } from './src/security/session.mjs';
import { createAuthStateStore } from './src/security/auth-state.mjs';
import { readBodyBuffer, readJson, sendError, sendJson, sendWorkbook } from './src/http/responses.mjs';
import { createBaseDatabase } from './src/data/base.mjs';
import { resolveRegion } from './src/data/region-service.mjs';
@@ -41,7 +42,6 @@ const publicSiteConfig = Object.freeze({
heroDescription: process.env.PUBLIC_SITE_HERO_DESCRIPTION || '使用学校下发的报名号登录,完成密码更新和个人信息核验后,即可办理所有考试事项。',
footerNotice: process.env.PUBLIC_SITE_FOOTER_NOTICE || ''
});
const sessions = new Map();
const staticFiles = new Set([
'/index.html',
'/styles.css',
@@ -105,6 +105,13 @@ const initializeDatabase = () => createBaseDatabase({
});
const persistentDatabase = await createDatabase({ root, seed: initializeDatabase });
const cache = await createRedisCache();
let authState;
try {
authState = await createAuthStateStore();
} catch (error) {
await Promise.allSettled([persistentDatabase.close(), cache.close()]);
throw error;
}
const resultCacheWriteMethods = new Set(['saveResult', 'saveResults', 'updateFeatureScore', 'updateFeatureScores', 'updateExam', 'archiveExam']);
const database = withCacheInvalidation(persistentDatabase, cache, (method, args) => {
const namespaces = ['public'];
@@ -121,7 +128,7 @@ const documentNumberDb = await readDb();
const missingNoticeNumbers = admissionRecords(documentNumberDb, 'placement').filter(item => item.status === 'final' && !item.payload?.noticeNumber);
if (missingNoticeNumbers.length) await database.saveAdmissionRecords(assignAdmissionNoticeNumbers(documentNumberDb, missingNoticeNumbers));
const { parseCookies, currentUser, safeUser, requireUser } = createSessionManager({ sessions, readDb, sendError });
const { parseCookies, currentUser, safeUser, requireUser } = createSessionManager({ authState, readDb, sendError });
const requirePermission = createPermissionGuard(sendError);
function adminsForStep(db, adminLevel, profile) {
@@ -966,7 +973,7 @@ const routeContext = {
randomBytes,
uid,
nowIso,
sessions,
authState,
buildWorkbook,
buildCenterMaterialsWorkbook,
hasExcelResource,
@@ -1020,12 +1027,13 @@ server.listen(port, host, () => {
console.log(`衡准考试信息管理系统:http://${host}:${port}`);
console.log(`数据库:${database.client}${database.location}`);
console.log(`Redis 缓存:${cache.status === 'ready' ? '已连接' : cache.status === 'disabled' ? '未配置' : '不可用,已回源数据库'}`);
console.log(`登录状态:${authState.status === 'ready' ? `Redis DB ${authState.database}` : '本机内存(Redis 未配置)'}`);
});
async function shutdown(signal) {
console.log(`收到 ${signal},正在关闭服务...`);
server.close(async () => {
await Promise.allSettled([database.close(), cache.close()]);
await Promise.allSettled([database.close(), cache.close(), authState.close()]);
process.exit(0);
});
}