370 lines
8.1 KiB
JavaScript
370 lines
8.1 KiB
JavaScript
|
|
const common = require("../../common");
|
||
|
|
const dayjs = require("dayjs");
|
||
|
|
const caApi = require("./ca-api");
|
||
|
|
const { getConfig } = require("../utils/config");
|
||
|
|
let db = "";
|
||
|
|
|
||
|
|
const caState = {};
|
||
|
|
|
||
|
|
module.exports = async (item, mongodb) => {
|
||
|
|
db = mongodb;
|
||
|
|
switch (item.type) {
|
||
|
|
case "caAuth":
|
||
|
|
return await caAuth(item);
|
||
|
|
case "getSealImage":
|
||
|
|
return await getSealImage(item);
|
||
|
|
case "getCaUserInfo":
|
||
|
|
return await getCaUserInfo(item);
|
||
|
|
case "startAutoSign":
|
||
|
|
return await startAutoSign(item);
|
||
|
|
case "autoSign":
|
||
|
|
return await autoSign(item);
|
||
|
|
case "autoSignVerifyCA":
|
||
|
|
return await autoSignVerifyCA(item);
|
||
|
|
case "closeAutoSign":
|
||
|
|
return await closeAutoSign(item);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
// ca授权, 获取授权码 NORMAL-正常, LOCKED-冻结, DELETION-已删除
|
||
|
|
async function caAuth(item) {
|
||
|
|
const { uniqueId } = item;
|
||
|
|
// 查询用户信息
|
||
|
|
const { success, data, message } = await caApi.getUserInfo({ uniqueId });
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { status, userId } = data;
|
||
|
|
if (status === "NORMAL") {
|
||
|
|
// 获取授权码
|
||
|
|
const { success, data, message } = await caApi.getAuthCode({
|
||
|
|
userId,
|
||
|
|
});
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: data.authCode,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: "用户状态异常",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
async function getCaUserInfo({ uniqueId }) {
|
||
|
|
const { success, data, message } = await caApi.getUserInfo({ uniqueId });
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { status, userId } = data;
|
||
|
|
if (status === "NORMAL") {
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: {
|
||
|
|
status,
|
||
|
|
userId,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: "用户状态异常",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查询印章图片
|
||
|
|
async function getSealImage({ uniqueId }) {
|
||
|
|
const res = await caApi.getUserInfo({ uniqueId });
|
||
|
|
if (!res.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: res.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { userId } = res.data;
|
||
|
|
const { success, data, message } = await caApi.queryImage({ userId });
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: data.image,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
// 开启时效签
|
||
|
|
async function startAutoSign({ userId, corpId }) {
|
||
|
|
const { caTimeRegion } = await getConfig(corpId);
|
||
|
|
const { success, data, message } = await caApi.startAutoSign({
|
||
|
|
userId,
|
||
|
|
timeRegion: caTimeRegion,
|
||
|
|
});
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: data,
|
||
|
|
caTimeRegion,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
// 自动签名
|
||
|
|
async function autoSign({ userId, oriData }) {
|
||
|
|
// data 为base64编码过的数据
|
||
|
|
const base64Data = Buffer.from(oriData).toString("base64");
|
||
|
|
console.log("=========>base64Data", base64Data);
|
||
|
|
const { success, data, message } = await caApi.autoSign({
|
||
|
|
userId,
|
||
|
|
data: base64Data,
|
||
|
|
});
|
||
|
|
// 如果自动签时效, 采用手动签名
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
console.log("签名成功饭后", data);
|
||
|
|
const { signCert, signResult } = data;
|
||
|
|
// 产生时间戳
|
||
|
|
const tsResult = await caApi.createAndGetTssInfo({
|
||
|
|
oriData,
|
||
|
|
attachCert: true,
|
||
|
|
});
|
||
|
|
if (!tsResult.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: tsResult.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
console.log("产生时间戳", tsResult);
|
||
|
|
|
||
|
|
const { tsResp } = tsResult.data;
|
||
|
|
// 验证签名结果 和 时间戳
|
||
|
|
const verifyResult = await verifySignAndTS({
|
||
|
|
userId,
|
||
|
|
oriData,
|
||
|
|
signResult,
|
||
|
|
tsResp,
|
||
|
|
signCert,
|
||
|
|
base64Data,
|
||
|
|
});
|
||
|
|
if (!verifyResult.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: verifyResult.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
console.log("验证签名结果 和 时间戳", verifyResult);
|
||
|
|
// 保存签名结果到本地数据库
|
||
|
|
await saveSignResult({
|
||
|
|
oriData,
|
||
|
|
tsResp,
|
||
|
|
signCert,
|
||
|
|
signResult,
|
||
|
|
userId,
|
||
|
|
});
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: data,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
// 验证签名结果 和 时间戳 verifyTS 和 verifySign 使用 promse.all
|
||
|
|
async function verifySignAndTS({
|
||
|
|
userId,
|
||
|
|
oriData,
|
||
|
|
signResult,
|
||
|
|
tsResp,
|
||
|
|
signCert,
|
||
|
|
base64Data,
|
||
|
|
}) {
|
||
|
|
console.log("===========>验证签名结果 和 时间戳", {
|
||
|
|
userId,
|
||
|
|
oriData,
|
||
|
|
signResult,
|
||
|
|
tsResp,
|
||
|
|
signCert,
|
||
|
|
base64Data,
|
||
|
|
});
|
||
|
|
const [verifyTSResult, verifySignResult] = await Promise.all([
|
||
|
|
caApi.verifyTS({ userId, oriData, tsResp }),
|
||
|
|
caApi.verifySign({
|
||
|
|
plain: base64Data,
|
||
|
|
signValue: signResult,
|
||
|
|
cert: signCert,
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
if (!verifyTSResult.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: verifyTSResult.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
if (!verifySignResult.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: verifySignResult.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: {
|
||
|
|
tsData: verifyTSResult.data,
|
||
|
|
signData: verifySignResult.data,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 保存签名结果到本地数据库
|
||
|
|
* @param {Object} param
|
||
|
|
* @param {String} param.oriData 原始数据
|
||
|
|
* @param {String} param.tsResp 签名时间戳
|
||
|
|
* @param {String} param.signCert 签名证书
|
||
|
|
* @param {String} param.signResult 签名数据
|
||
|
|
* @param {String} param.userId 用户ID
|
||
|
|
* @returns
|
||
|
|
*/
|
||
|
|
async function saveSignResult({
|
||
|
|
oriData,
|
||
|
|
tsResp,
|
||
|
|
signCert,
|
||
|
|
signResult,
|
||
|
|
userId,
|
||
|
|
}) {
|
||
|
|
const result = await db.collection("ca-sign").insertOne({
|
||
|
|
userId,
|
||
|
|
oriData,
|
||
|
|
tsResp,
|
||
|
|
signCert,
|
||
|
|
signResult,
|
||
|
|
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||
|
|
});
|
||
|
|
console.log("保存签名结果到本地数据库", result);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 验证CA时效 通过 queryAutoSignRegion 接口
|
||
|
|
async function autoSignVerifyCA(item) {
|
||
|
|
const { code } = item;
|
||
|
|
const state = useCaState(code);
|
||
|
|
if (state) {
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
message: `时效签已开启,有效期至: ${state.endTime}`,
|
||
|
|
userId: state.userId,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const uerInfo = await caApi.getUserInfo({ uniqueId: code });
|
||
|
|
if (!uerInfo.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: uerInfo.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { status, userId } = uerInfo.data;
|
||
|
|
if (status != "NORMAL") {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: "用户状态异常",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { success, data } = await caApi.queryAutoSignRegion({
|
||
|
|
userId,
|
||
|
|
});
|
||
|
|
if (success && data.autoSignStatus === "STARTED") {
|
||
|
|
const state = {
|
||
|
|
userId,
|
||
|
|
endTime: data.endTime
|
||
|
|
}
|
||
|
|
keepCaState(code, state);
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
message: "时效签已开启",
|
||
|
|
userId,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
removeCaState(code);
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: "时效签未开启",
|
||
|
|
userId,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
async function closeAutoSign({ uniqueId }) {
|
||
|
|
const uerInfo = await caApi.getUserInfo({ uniqueId });
|
||
|
|
if (!uerInfo.success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: uerInfo.message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { status, userId } = uerInfo.data;
|
||
|
|
if (status != "NORMAL") {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: "用户状态异常",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
const { success, message } = await caApi.closeAutoSign({
|
||
|
|
userId,
|
||
|
|
});
|
||
|
|
if (!success) {
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
message: message,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
message: "关闭成功",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function keepCaState(uniqueId, { userId, endTime }) {
|
||
|
|
if (typeof userId === 'string' && userId.trim() && endTime && dayjs(endTime).isValid()) {
|
||
|
|
// ca当天有效, 如果有效期超过当天, 则将有效期设置为当天
|
||
|
|
const newEndTime = dayjs(endTime).isAfter(dayjs().endOf('day')) ? dayjs().endOf('day').format('YYYY-MM-DD HH:mm') : endTime;
|
||
|
|
caState[uniqueId] = { userId, endTime: newEndTime };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function removeCaState(uniqueId) {
|
||
|
|
caState[uniqueId] = undefined;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
function useCaState(uniqueId) {
|
||
|
|
const info = caState[uniqueId];
|
||
|
|
if (!info) return null;
|
||
|
|
const { userId, endTime } = info;
|
||
|
|
if (endTime && dayjs().isBefore(dayjs(endTime))) {
|
||
|
|
return { userId, endTime }
|
||
|
|
}
|
||
|
|
return null
|
||
|
|
}
|