init
This commit is contained in:
107
api/service/biz_auth_verify.js
Normal file
107
api/service/biz_auth_verify.js
Normal file
@@ -0,0 +1,107 @@
|
||||
const baseModel = require("../../middleware/baseModel");
|
||||
const tokenLogic = require("./biz_token_logic");
|
||||
const usageSvc = require("./biz_usage_service");
|
||||
|
||||
function featureAllowed(plan, feature) {
|
||||
if (!feature) return true;
|
||||
const feats = plan.enabled_features;
|
||||
if (feats == null) return true;
|
||||
if (Array.isArray(feats)) return feats.includes(feature);
|
||||
if (typeof feats === "object") {
|
||||
return feats[feature] === true || feats[feature] === 1 || feats[feature] === "1";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalizeUsageDelta(raw) {
|
||||
if (!raw || typeof raw !== "object") return {};
|
||||
return {
|
||||
msg: usageSvc.num(raw.msg ?? raw.msg_count),
|
||||
mass: usageSvc.num(raw.mass ?? raw.mass_count),
|
||||
friend: usageSvc.num(raw.friend ?? raw.friend_count),
|
||||
sns: usageSvc.num(raw.sns ?? raw.sns_count),
|
||||
active_user: usageSvc.num(raw.active_user ?? raw.active_user_count),
|
||||
};
|
||||
}
|
||||
|
||||
function hasPositiveDelta(delta) {
|
||||
return Object.values(delta).some((v) => usageSvc.num(v) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外鉴权:Token + 用户 + 有效订阅 + 功能点 + 可选用量上报与额度
|
||||
* body: { token, feature?, usage_delta?: { msg?, mass?, ... } }
|
||||
*/
|
||||
async function verifyRequest(body) {
|
||||
const { token, feature } = body || {};
|
||||
if (!token) {
|
||||
return { ok: false, error_code: "TOKEN_INVALID", message: "缺少 token" };
|
||||
}
|
||||
|
||||
const hash = tokenLogic.hashPlainToken(token);
|
||||
const row = await baseModel.biz_api_token.findOne({ where: { token_hash: hash } });
|
||||
if (!row) {
|
||||
return { ok: false, error_code: "TOKEN_INVALID", message: "Token 不存在" };
|
||||
}
|
||||
if (row.status === "revoked") {
|
||||
return { ok: false, error_code: "TOKEN_REVOKED", message: "Token 已吊销" };
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
if (new Date(row.expire_at) < now) {
|
||||
return { ok: false, error_code: "TOKEN_EXPIRED", message: "Token 已过期" };
|
||||
}
|
||||
|
||||
const user = await baseModel.biz_user.findByPk(row.user_id);
|
||||
if (!user || user.status !== "active") {
|
||||
return { ok: false, error_code: "SUBSCRIPTION_INACTIVE", message: "用户不可用" };
|
||||
}
|
||||
|
||||
const sub = await tokenLogic.findActiveSubscriptionForUser(row.user_id);
|
||||
if (!sub) {
|
||||
return { ok: false, error_code: "SUBSCRIPTION_INACTIVE", message: "无有效订阅" };
|
||||
}
|
||||
|
||||
const plan = await baseModel.biz_plan.findByPk(sub.plan_id);
|
||||
if (!plan || plan.status !== "active") {
|
||||
return { ok: false, error_code: "SUBSCRIPTION_INACTIVE", message: "套餐不可用" };
|
||||
}
|
||||
|
||||
if (feature && !featureAllowed(plan, feature)) {
|
||||
return { ok: false, error_code: "FEATURE_NOT_ALLOWED", message: "功能未在套餐内" };
|
||||
}
|
||||
|
||||
const statMonth = usageSvc.currentStatMonth();
|
||||
let usageRow = await usageSvc.getOrCreateUsage(row.user_id, sub.plan_id, statMonth);
|
||||
|
||||
const delta = normalizeUsageDelta(body.usage_delta || body.usage_report);
|
||||
if (hasPositiveDelta(delta)) {
|
||||
const q = usageSvc.checkQuotaAfterDelta(plan, usageRow, delta);
|
||||
if (!q.ok) {
|
||||
return { ok: false, error_code: q.error_code || "QUOTA_EXCEEDED", message: q.message || "额度不足" };
|
||||
}
|
||||
usageRow = await usageSvc.applyDelta(row.user_id, sub.plan_id, statMonth, delta);
|
||||
}
|
||||
|
||||
await row.update({ last_used_at: now });
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
context: {
|
||||
user_id: row.user_id,
|
||||
plan_id: sub.plan_id,
|
||||
subscription_id: sub.id,
|
||||
token_id: row.id,
|
||||
stat_month: statMonth,
|
||||
usage_snapshot: {
|
||||
msg_count: usageSvc.num(usageRow.msg_count),
|
||||
mass_count: usageSvc.num(usageRow.mass_count),
|
||||
friend_count: usageSvc.num(usageRow.friend_count),
|
||||
sns_count: usageSvc.num(usageRow.sns_count),
|
||||
active_user_count: usageSvc.num(usageRow.active_user_count),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { verifyRequest };
|
||||
Reference in New Issue
Block a user