server/laf-cloud/functions/cloudRise/admin.ts
2026-09-24 17:59:52 +08:00

65 lines
4.2 KiB
TypeScript

import * as ConfigStore from "@/activityConfig/store";
import cloud from "@lafjs/cloud";
import * as Activity from "@/cloudRise/index";
const mongo: any = cloud.mongo.db;
/** Operator-only setup; no default password and no implicit production opening. */
export default async function (ctx: FunctionContext) {
const body = ctx.body || {};
const expected = (globalThis as any).process?.env?.ADMIN_TOKEN;
if (!expected || body.adminToken !== expected) return { code: 0, msg: "unauthorized" };
if (body.action === "read") {
const version = body.periodId ? await ConfigStore.records().findOne({
activityId: "cloudRise", recordType: "version",
"config.periodId": body.periodId
}, { sort: { publishedAt: -1, _id: 1 } }) : null;
const config = body.periodId ? version ? { ...version.config, configVersion: version.configVersion, enabled: version.enabled !== false } : null
: await (Activity as any).findOpenPeriod(Date.now());
return { code: 1, data: config };
}
if (body.action === "migrate_config") return { code: 0, msg: "请按 activityConfig/MIGRATION.md 迁移到公共配置集合" };
if (body.action === "compact_archives") {
const limit = body.limit === undefined ? 100 : Number(body.limit);
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 500
|| body.afterId !== undefined && typeof body.afterId !== "string") return { code: 0, msg: "归档分页参数无效" };
try { return { code: 1, data: await (Activity as any).compactArchives(limit, body.afterId || "") }; }
catch (error) { return { code: 0, msg: error instanceof Error ? error.message : "归档精简失败,可重试" }; }
}
if (body.action === "setup_indexes") {
await mongo.collection("users").createIndex({ taskTime: 1 });
await mongo.collection("users").createIndex({ onlyId: 1 }, { unique: true, partialFilterExpression: { onlyId: { $type: "number" } } });
await ConfigStore.setupIndexes();
await mongo.collection("cloudRiseSamples").createIndex({ "samples.stage": 1, "samples.start_level": 1, "samples.success_num": 1 });
await mongo.collection("cloudRiseSamples").createIndex({ uid: 1, periodId: 1 }, {
unique: true, partialFilterExpression: { schemaVersion: 2 }, name: "cloudRiseSamples_uid_period",
});
await mongo.collection("cloudRiseRuns").createIndex({ uid: 1, periodId: 1 });
return { code: 1, msg: "索引已准备" };
}
if (body.action !== "save") return { code: 0, msg: "无效操作" };
const enabled = body.enabled === undefined ? true : body.enabled;
if (typeof enabled !== "boolean") return { code: 0, msg: "enabled 必须为布尔值" };
let config = body.config;
try { if (typeof config === "string") config = JSON.parse(config); }
catch { return { code: 0, msg: "配置 JSON 无效" }; }
const error = (Activity as any).validatePeriod(config);
if (error) return { code: 0, msg: error };
const saved = {
periodId: config.periodId, durationHours: (Activity as any).periodDurationHours(config),
startsAt: config.startsAt, endsAt: config.endsAt, unlockLevel: config.unlockLevel, pools: (Activity as any).periodPools(config)
};
try {
const previous = await ConfigStore.records().findOne({ activityId: "cloudRise", recordType: "version", "config.periodId": saved.periodId });
if (previous && (previous.config.startsAt !== saved.startsAt || previous.config.endsAt !== saved.endsAt))
return { code: 0, msg: "同一期的报名时间不可改动;请创建新期配置" };
// A period already opened may not be republished to change its enrollment or rewards.
const opened = await ConfigStore.records().findOne({
activityId: "cloudRise", recordType: "version",
"config.periodId": saved.periodId, "config.startsAt": { $lte: Date.now() }
});
if (opened) return { code: 0, msg: "该期已经开启,不可修改;请创建新期配置" };
const version = await ConfigStore.publish("cloudRise", body.configVersion || config.configVersion, saved.startsAt, saved, enabled);
return { code: 1, data: { ...saved, configVersion: version.configVersion, enabled: version.enabled !== false }, msg: "配置版本已发布,活动开启后固定" };
} catch (error) { return { code: 0, msg: error instanceof Error ? error.message : "配置发布失败" }; }
}