diff --git a/api/controller_admin/invite_register.js b/api/controller_admin/invite_register.js index 04f825b..a383c12 100644 --- a/api/controller_admin/invite_register.js +++ b/api/controller_admin/invite_register.js @@ -67,17 +67,20 @@ module.exports = { return ctx.fail('密码长度不能少于6位'); } + // 统一邮箱地址为小写 + const email_normalized = email.toLowerCase().trim(); + // 验证验证码 - const emailVerifyResult = await verifyEmailCode(email, email_code); + const emailVerifyResult = await verifyEmailCode(email_normalized, email_code); if (!emailVerifyResult.success) { return ctx.fail(emailVerifyResult.message || '验证码错误或已过期'); } const { pla_account } = await Framework.getModels(); - // 检查邮箱是否已注册 + // 检查邮箱是否已注册(使用统一的小写邮箱) const existingUser = await pla_account.findOne({ - where: { login_name: email } + where: { login_name: email_normalized } }); if (existingUser) { @@ -87,7 +90,7 @@ module.exports = { // 验证邀请码(如果提供了邀请码) let inviter = null; let inviter_id = null; - + if (invite_code) { // 解析邀请码,获取邀请人ID // 邀请码格式:INV{user_id}_{timestamp} @@ -111,13 +114,13 @@ module.exports = { // 生成设备SN码(基于邮箱和时间戳) const sn_code = `SN${Date.now()}${Math.random().toString(36).substr(2, 6).toUpperCase()}`; - // 创建新用户 + // 创建新用户(使用统一的小写邮箱) const newUser = await pla_account.create({ - name: email.split('@')[0], // 默认使用邮箱用户名作为名称 + name: email_normalized.split('@')[0], // 默认使用邮箱用户名作为名称 sn_code: sn_code, device_id: '', // 设备ID由客户端登录时提供 platform_type: 'boss', // 默认平台类型 - login_name: email, + login_name: email_normalized, pwd: password, keyword: '', is_enabled: 1, @@ -173,9 +176,9 @@ module.exports = { is_delete: 0 }); - console.log(`[邀请注册] 用户 ${email} 通过邀请码 ${invite_code} 注册成功,邀请人 ${inviter.sn_code} 获得3天试用期`); + console.log(`[邀请注册] 用户 ${email_normalized} 通过邀请码 ${invite_code} 注册成功,邀请人 ${inviter.sn_code} 获得3天试用期`); } else { - console.log(`[邀请注册] 用户 ${email} 注册成功(无邀请码)`); + console.log(`[邀请注册] 用户 ${email_normalized} 注册成功(无邀请码)`); } return ctx.success({ @@ -231,8 +234,11 @@ module.exports = { return ctx.fail('邮箱格式不正确'); } + // 统一邮箱地址为小写 + const email_normalized = email.toLowerCase().trim(); + // 发送验证码 - const emailResult = await sendEmailCode(email); + const emailResult = await sendEmailCode(email_normalized); if (!emailResult.success) { return ctx.fail(emailResult.message || '发送验证码失败'); } @@ -255,35 +261,57 @@ module.exports = { */ async function sendEmailCode(email) { try { + + // 获取框架的 Redis 服务 + const redis_service = Framework.getServices().redisService; + + + // 统一邮箱地址为小写,避免大小写不一致导致的问题 + const email_lower = email.toLowerCase().trim(); + // 生成6位随机验证码 const code = Math.floor(100000 + Math.random() * 900000).toString(); - - // 将验证码存储到缓存中(可以使用Redis或内存缓存) - // 格式:email_code:{email} = {code, expire_time} - const expire_time = Date.now() + 5 * 60 * 1000; // 5分钟后过期 - - // 这里应该存储到缓存中,暂时使用全局变量(生产环境应使用Redis) - if (!global.emailCodeCache) { - global.emailCodeCache = {}; - } - global.emailCodeCache[email] = { + + // Redis key + const redis_key = `email_code:${email_lower}`; + + // 验证码数据 + const code_data = { code: code, - expire_time: expire_time + created_at: Date.now() }; + // 存储到 Redis,设置 5 分钟过期时间(300秒) + try { + await redis_service.set(redis_key, JSON.stringify(code_data), 300); + } catch (redis_error) { + console.error(`[邮箱验证] Redis 存储失败: ${email_lower}`, redis_error); + return { + success: false, + message: '验证码存储失败,请稍后重试' + }; + } + + console.log(`[邮箱验证] 生成验证码: ${email_lower} -> ${code}, 已存储到 Redis (5分钟过期)`); + // 调用邮件服务发送验证码 - const email_result = await email_service.send_verification_code(email, code); - + const email_result = await email_service.send_verification_code(email_lower, code); + if (!email_result.success) { // 如果邮件发送失败,删除已生成的验证码 - delete global.emailCodeCache[email]; + try { + await redis_service.del(redis_key); + } catch (del_error) { + console.error(`[邮箱验证] 删除验证码失败:`, del_error); + } + console.error(`[邮箱验证] 邮件发送失败,已删除验证码: ${email_lower}`); return { success: false, message: email_result.message || '发送验证码失败' }; } - console.log(`[邮箱验证] 验证码已发送到 ${email}: ${code} (5分钟内有效)`); + console.log(`[邮箱验证] 验证码已发送到 ${email_lower}: ${code} (5分钟内有效)`); return { success: true, @@ -306,32 +334,56 @@ async function sendEmailCode(email) { */ async function verifyEmailCode(email, code) { try { - if (!global.emailCodeCache) { + // 统一邮箱地址为小写,避免大小写不一致导致的问题 + const email_lower = email.toLowerCase().trim(); + + console.log(`[邮箱验证] 开始验证: ${email_lower}, 验证码: ${code}`); + + // Redis key + const redis_key = `email_code:${email_lower}`; + + // 从 Redis 获取验证码 + let cached_str; + try { + cached_str = await redis_service.get(redis_key); + } catch (redis_error) { + console.error(`[邮箱验证] Redis 获取失败:`, redis_error); return { success: false, - message: '验证码不存在或已过期' + message: '验证码获取失败,请稍后重试' }; } - const cached = global.emailCodeCache[email]; - if (!cached) { + if (!cached_str) { + console.log(`[邮箱验证] 未找到该邮箱的验证码: ${email_lower}`); return { success: false, - message: '验证码不存在或已过期' + message: '验证码不存在或已过期,请重新获取' }; } - // 检查是否过期 - if (Date.now() > cached.expire_time) { - delete global.emailCodeCache[email]; + // 解析验证码数据 + let cached; + try { + cached = JSON.parse(cached_str); + } catch (parse_error) { + console.error(`[邮箱验证] 解析验证码数据失败:`, parse_error); + try { + await redis_service.del(redis_key); + } catch (del_error) { + console.error(`[邮箱验证] 删除异常数据失败:`, del_error); + } return { success: false, - message: '验证码已过期,请重新获取' + message: '验证码数据异常,请重新获取' }; } + console.log(`[邮箱验证] 找到验证码,创建时间: ${new Date(cached.created_at).toLocaleString()}`); + // 验证码是否正确 if (cached.code !== code) { + console.log(`[邮箱验证] 验证码错误,期望: ${cached.code}, 实际: ${code}`); return { success: false, message: '验证码错误' @@ -339,7 +391,12 @@ async function verifyEmailCode(email, code) { } // 验证成功后删除缓存 - delete global.emailCodeCache[email]; + try { + await redis_service.del(redis_key); + } catch (del_error) { + console.error(`[邮箱验证] 删除验证码失败:`, del_error); + } + console.log(`[邮箱验证] 验证成功: ${email_lower}`); return { success: true