hn-hlw-service/auth/index.js
2026-07-27 11:28:33 +08:00

369 lines
8.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const jwtUtils = require("../utils/jwt-utils");
const logger = require("../utils/logger");
/**
* 认证模块
* 处理用户登录、token 刷新等功能
*/
/**
* 用户登录
* @param {Object} params - 登录参数 { username, password, corpId }
* @param {Object} db - 数据库实例
* @returns {Object} 登录结果
*/
async function login(params, db) {
const { username, password, corpId } = params;
if (!username || !password) {
return {
success: false,
message: "用户名和密码不能为空",
};
}
// 查询用户信息
const user = await db.collection("corp-member").findOne(
{ corpId, mobile: username } // 查询条件
);
if (!user) {
logger.warn(`登录失败: 用户不存在 - ${username}`);
return {
success: false,
message: "用户名或密码错误",
};
}
// 验证密码(这里假设密码已加密,实际应该使用 bcrypt 等加密算法)
if (user.password !== password) {
logger.warn(`登录失败: 密码错误 - ${username}`);
return {
success: false,
message: "用户名或密码错误",
};
}
// 检查用户状态
if (user.status === "disabled") {
return {
success: false,
message: "账号已被禁用",
};
}
// 生成 token
const tokens = jwtUtils.generateTokens({
userId: user._id.toString(),
username: user.username,
corpId: user.corpId,
role: user.role || "user",
});
// 更新最后登录时间
await usersCollection.updateOne(
{ _id: user._id },
{
$set: {
lastLoginTime: new Date(),
lastLoginIp: params.ip || "",
},
}
);
logger.info(`用户登录成功: ${username}`);
return {
success: true,
message: "登录成功",
data: {
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
expiresIn: tokens.expiresIn,
tokenType: "Bearer",
userInfo: {
userId: user._id.toString(),
username: user.username,
corpId: user.corpId,
role: user.role || "user",
nickname: user.nickname || user.username,
},
},
};
}
/**
* 刷新 token
* @param {Object} params - 刷新参数 { refreshToken }
* @returns {Object} 刷新结果
*/
async function refreshToken(params) {
const { refreshToken } = params;
if (!refreshToken) {
return {
success: false,
message: "刷新令牌不能为空",
};
}
// 验证并生成新的访问令牌
const result = jwtUtils.refreshAccessToken(refreshToken);
logger.info("Token 刷新成功");
return {
success: true,
message: "Token 刷新成功",
data: {
accessToken: result.accessToken,
expiresIn: result.expiresIn,
tokenType: "Bearer",
},
};
}
/**
* 退出登录
* @param {Object} params - 参数
* @param {Object} user - 当前用户信息(来自 JWT
* @returns {Object} 退出结果
*/
async function logout(params, user) {
// 可以在这里实现 token 黑名单机制
// 将当前 token 加入黑名单,使其失效
logger.info(`用户退出登录: ${user.username}`);
return {
success: true,
message: "退出成功",
};
}
/**
* 小程序授权登录(支付宝/微信)
* @param {Object} params - 登录参数 { authCode, platform, corpId }
* @param {Object} db - 数据库实例
* @returns {Object} 登录结果
*/
async function miniProgramLogin(params, db) {
const { authCode, platform = "alipay", corpId } = params;
if (!authCode) {
return {
success: false,
message: "授权码不能为空",
};
}
try {
// 这里需要调用支付宝/微信的接口获取用户信息
// 由于没有具体的获取用户信息的逻辑,我们假设通过 authCode 可以获取到 userId
// 实际项目中,应该调用对应平台的 API 来验证 authCode 并获取用户信息
// 临时方案:使用 authCode 作为用户标识
// 在实际应用中,需要调用支付宝 API: alipay.system.oauth.token
const userId = authCode; // 这里应该是从支付宝返回的真实 userId
// 查询或创建小程序用户
const usersCollection = db.collection("miniapp_users");
let user = await usersCollection.findOne({
userId,
platform,
...(corpId && { corpId }),
});
if (!user) {
// 首次登录,创建用户记录
const newUser = {
userId,
platform,
corpId: corpId || "",
role: "customer",
status: "active",
createTime: new Date(),
lastLoginTime: new Date(),
lastLoginIp: params.ip || "",
};
const result = await usersCollection.insertOne(newUser);
user = { _id: result.insertedId, ...newUser };
logger.info(`小程序新用户注册: ${userId}`);
} else {
// 更新最后登录时间
await usersCollection.updateOne(
{ _id: user._id },
{
$set: {
lastLoginTime: new Date(),
lastLoginIp: params.ip || "",
},
}
);
logger.info(`小程序用户登录: ${userId}`);
}
// 检查用户状态
if (user.status === "disabled") {
return {
success: false,
message: "账号已被禁用",
};
}
// 生成 JWT token
const tokens = jwtUtils.generateTokens({
userId: user._id.toString(),
miniappUserId: user.userId,
platform: user.platform,
corpId: user.corpId,
role: user.role || "customer",
});
return {
success: true,
message: "登录成功",
data: {
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
expiresIn: tokens.expiresIn,
tokenType: "Bearer",
userInfo: {
userId: user._id.toString(),
miniappUserId: user.userId,
platform: user.platform,
corpId: user.corpId,
role: user.role || "customer",
},
},
};
} catch (error) {
logger.error("小程序登录失败:", error);
return {
success: false,
message: "登录失败: " + error.message,
};
}
}
/**
* 获取当前用户信息
* @param {Object} user - 当前用户信息(来自 JWT
* @param {Object} db - 数据库实例
* @returns {Object} 用户信息
*/
async function getCurrentUser(user, db) {
// 判断是小程序用户还是普通用户
if (user.miniappUserId) {
// 小程序用户
const usersCollection = db.collection("miniapp_users");
const userInfo = await usersCollection.findOne({
_id: require("mongodb").ObjectId.createFromHexString(user.userId),
});
if (!userInfo) {
return {
success: false,
message: "用户不存在",
};
}
return {
success: true,
data: {
userId: userInfo._id.toString(),
miniappUserId: userInfo.userId,
platform: userInfo.platform,
corpId: userInfo.corpId,
role: userInfo.role || "customer",
status: userInfo.status,
createTime: userInfo.createTime,
lastLoginTime: userInfo.lastLoginTime,
},
};
} else {
// 普通用户
const usersCollection = db.collection("users");
const userInfo = await usersCollection.findOne(
{ _id: require("mongodb").ObjectId.createFromHexString(user.userId) },
{ projection: { password: 0 } } // 不返回密码
);
if (!userInfo) {
return {
success: false,
message: "用户不存在",
};
}
return {
success: true,
data: {
userId: userInfo._id.toString(),
username: userInfo.username,
corpId: userInfo.corpId,
role: userInfo.role || "user",
nickname: userInfo.nickname || userInfo.username,
email: userInfo.email,
phone: userInfo.phone,
avatar: userInfo.avatar,
status: userInfo.status,
createTime: userInfo.createTime,
lastLoginTime: userInfo.lastLoginTime,
},
};
}
}
/**
* 主路由处理函数
* @param {Object} params - 请求参数
* @param {Object} db - 数据库实例
* @param {Object} user - 当前用户信息(可选)
* @returns {Object} 处理结果
*/
async function main(params, db, user) {
const { type } = params;
switch (type) {
case "login":
return await login(params, db);
case "miniProgramLogin":
return await miniProgramLogin(params, db);
case "refreshToken":
return await refreshToken(params);
case "logout":
if (!user) {
return { success: false, message: "未登录" };
}
return await logout(params, user);
case "getCurrentUser":
if (!user) {
return { success: false, message: "未登录" };
}
return await getCurrentUser(user, db);
default:
return {
success: false,
message: "未知的操作类型",
};
}
}
module.exports = {
main,
login,
miniProgramLogin,
refreshToken,
logout,
getCurrentUser,
};