1
This commit is contained in:
@@ -55,6 +55,27 @@ module.exports = {
|
||||
});
|
||||
ctx.success({ id: row.id, status: row.status });
|
||||
},
|
||||
"POST /biz_token/regenerate": async (ctx) => {
|
||||
const body = ctx.getBody();
|
||||
const result = await tokenLogic.regenerateToken(body);
|
||||
await audit.logAudit({
|
||||
admin_user_id: audit.pickAdminId(ctx),
|
||||
biz_user_id: result.row.user_id,
|
||||
action: "biz_token.regenerate",
|
||||
resource_type: "biz_api_token",
|
||||
resource_id: result.row.id,
|
||||
detail: { token_name: result.row.token_name },
|
||||
});
|
||||
ctx.success({
|
||||
id: result.row.id,
|
||||
user_id: result.row.user_id,
|
||||
plan_id: result.row.plan_id,
|
||||
token_name: result.row.token_name,
|
||||
expire_at: result.row.expire_at,
|
||||
plain_token: result.plain_token,
|
||||
warn: result.warn,
|
||||
});
|
||||
},
|
||||
"POST /biz_token/export": async (ctx) => {
|
||||
const body = ctx.getBody();
|
||||
const param = body.param || body;
|
||||
|
||||
@@ -46,7 +46,40 @@ module.exports = {
|
||||
resource_id: row.id,
|
||||
detail: { name: row.name },
|
||||
});
|
||||
ctx.success(row);
|
||||
|
||||
const out = row.get({ plain: true });
|
||||
let plain_token = null;
|
||||
let token_warn = null;
|
||||
let token_error = null;
|
||||
const auto_token = body.auto_create_token !== false;
|
||||
if (auto_token && row.status === "active") {
|
||||
try {
|
||||
const result = await tokenLogic.createToken({
|
||||
user_id: row.id,
|
||||
token_name: body.initial_token_name || "default",
|
||||
expire_at: body.initial_token_expire_at || tokenLogic.defaultTokenExpireAt(),
|
||||
});
|
||||
await audit.logAudit({
|
||||
admin_user_id: audit.pickAdminId(ctx),
|
||||
biz_user_id: row.id,
|
||||
action: "biz_token.create",
|
||||
resource_type: "biz_api_token",
|
||||
resource_id: result.row.id,
|
||||
detail: { token_name: result.row.token_name, via: "biz_user.add" },
|
||||
});
|
||||
plain_token = result.plain_token;
|
||||
token_warn = result.warn;
|
||||
} catch (e) {
|
||||
token_error = e.message || String(e);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.success({
|
||||
...out,
|
||||
plain_token,
|
||||
token_warn,
|
||||
token_error,
|
||||
});
|
||||
},
|
||||
"POST /biz_user/edit": async (ctx) => {
|
||||
const body = ctx.getBody();
|
||||
|
||||
@@ -13,6 +13,13 @@ function generatePlainToken() {
|
||||
return `waw_${crypto.randomBytes(24).toString("hex")}`;
|
||||
}
|
||||
|
||||
/** 默认 Token 过期时间:一年后当日 23:59:59 */
|
||||
function defaultTokenExpireAt() {
|
||||
const d = new Date();
|
||||
d.setFullYear(d.getFullYear() + 1);
|
||||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")} 23:59:59`;
|
||||
}
|
||||
|
||||
/** 当前时间在 [start,end] 内且 status=active 的订阅 */
|
||||
async function findActiveSubscriptionForUser(userId) {
|
||||
const now = new Date();
|
||||
@@ -72,6 +79,39 @@ async function revokeToken(body) {
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保留同一条 Token 记录,仅更换密钥(旧明文立即失效)
|
||||
*/
|
||||
async function regenerateToken(body) {
|
||||
const id = body.id;
|
||||
if (id == null) throw new Error("缺少 id");
|
||||
const row = await baseModel.biz_api_token.findByPk(id);
|
||||
if (!row) throw new Error("Token 不存在");
|
||||
if (row.status !== "active") throw new Error("仅可对状态为 active 的 Token 重新生成密钥");
|
||||
|
||||
const u = await baseModel.biz_user.findByPk(row.user_id);
|
||||
if (!u) throw new Error("用户不存在");
|
||||
if (u.status !== "active") throw new Error("用户已禁用,无法轮换密钥");
|
||||
|
||||
const sub = await findActiveSubscriptionForUser(row.user_id);
|
||||
const plan_id = sub ? sub.plan_id : null;
|
||||
|
||||
const plain = generatePlainToken();
|
||||
const token_hash = hashPlainToken(plain);
|
||||
|
||||
await row.update({
|
||||
token_hash,
|
||||
plan_id,
|
||||
});
|
||||
await row.reload();
|
||||
|
||||
return {
|
||||
row,
|
||||
plain_token: plain,
|
||||
warn: sub ? null : "当前无生效中的订阅,鉴权将失败",
|
||||
};
|
||||
}
|
||||
|
||||
async function revokeAllForUser(userId) {
|
||||
if (userId == null) throw new Error("缺少 user_id");
|
||||
const [n] = await baseModel.biz_api_token.update(
|
||||
@@ -84,8 +124,10 @@ async function revokeAllForUser(userId) {
|
||||
module.exports = {
|
||||
hashPlainToken,
|
||||
createToken,
|
||||
regenerateToken,
|
||||
revokeToken,
|
||||
revokeAllForUser,
|
||||
findActiveSubscriptionForUser,
|
||||
defaultTokenExpireAt,
|
||||
MAX_TOKENS_PER_USER,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user