init
This commit is contained in:
90
api/service/biz_token_logic.js
Normal file
90
api/service/biz_token_logic.js
Normal file
@@ -0,0 +1,90 @@
|
||||
const crypto = require("crypto");
|
||||
const baseModel = require("../../middleware/baseModel");
|
||||
const { op } = baseModel;
|
||||
|
||||
const MAX_TOKENS_PER_USER = 5;
|
||||
|
||||
function hashPlainToken(plain) {
|
||||
return crypto.createHash("sha256").update(plain, "utf8").digest("hex");
|
||||
}
|
||||
|
||||
function generatePlainToken() {
|
||||
return `waw_${crypto.randomBytes(24).toString("hex")}`;
|
||||
}
|
||||
|
||||
/** 当前时间在 [start,end] 内且 status=active 的订阅 */
|
||||
async function findActiveSubscriptionForUser(userId) {
|
||||
const now = new Date();
|
||||
return baseModel.biz_subscription.findOne({
|
||||
where: {
|
||||
user_id: userId,
|
||||
status: "active",
|
||||
start_time: { [op.lte]: now },
|
||||
end_time: { [op.gte]: now },
|
||||
},
|
||||
order: [["id", "DESC"]],
|
||||
});
|
||||
}
|
||||
|
||||
async function createToken(body) {
|
||||
const { user_id, token_name, expire_at } = body;
|
||||
if (!user_id || !expire_at) throw new Error("缺少 user_id 或 expire_at");
|
||||
const u = await baseModel.biz_user.findByPk(user_id);
|
||||
if (!u) throw new Error("用户不存在");
|
||||
if (u.status !== "active") throw new Error("用户已禁用");
|
||||
|
||||
const activeCount = await baseModel.biz_api_token.count({
|
||||
where: { user_id, status: "active" },
|
||||
});
|
||||
if (activeCount >= MAX_TOKENS_PER_USER) {
|
||||
throw new Error(`单用户最多 ${MAX_TOKENS_PER_USER} 个有效 Token`);
|
||||
}
|
||||
|
||||
const sub = await findActiveSubscriptionForUser(user_id);
|
||||
const plan_id = sub ? sub.plan_id : null;
|
||||
|
||||
const plain = generatePlainToken();
|
||||
const token_hash = hashPlainToken(plain);
|
||||
|
||||
const row = await baseModel.biz_api_token.create({
|
||||
user_id,
|
||||
plan_id,
|
||||
token_name: token_name || "default",
|
||||
token_hash,
|
||||
status: "active",
|
||||
expire_at,
|
||||
});
|
||||
|
||||
return {
|
||||
row,
|
||||
plain_token: plain,
|
||||
warn: sub ? null : "当前无生效中的订阅,鉴权将失败",
|
||||
};
|
||||
}
|
||||
|
||||
async function revokeToken(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 不存在");
|
||||
await row.update({ status: "revoked" });
|
||||
return row;
|
||||
}
|
||||
|
||||
async function revokeAllForUser(userId) {
|
||||
if (userId == null) throw new Error("缺少 user_id");
|
||||
const [n] = await baseModel.biz_api_token.update(
|
||||
{ status: "revoked" },
|
||||
{ where: { user_id: userId, status: "active" } }
|
||||
);
|
||||
return n;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hashPlainToken,
|
||||
createToken,
|
||||
revokeToken,
|
||||
revokeAllForUser,
|
||||
findActiveSubscriptionForUser,
|
||||
MAX_TOKENS_PER_USER,
|
||||
};
|
||||
Reference in New Issue
Block a user