const API = require("../../../lib/API") const { v4: uuidv4 } = require('uuid') const db = require("../../../plugin/DataBase/db") const Redis = require('../../../plugin/DataBase/Redis') const { BaseStdResponse } = require("../../../BaseStdResponse") const { fetchUniLoginProfile, normalizeSocialType } = require('../../../lib/UniLoginClient') const { getBindingByIdentity, getLegacyUserByIdentity, insertSocialBinding, updateSocialBindingProfile, syncLegacySocialMirror } = require('../../../lib/UserSocialBinding') class Login extends API { constructor() { super() this.setPath('/UniLogin/Login') this.setMethod('POST') } async onRequest(req, res) { let { type, code } = req.body type = normalizeSocialType(type) if ([code].some(value => value === '' || value === null || value === undefined)) return res.json({ ...BaseStdResponse.MISSING_PARAMETER }) if (!type) return res.json({ ...BaseStdResponse.ERR, msg: '不支持的第三方登录类型' }) try { let { social_uid, nickname, faceimg, ip } = await fetchUniLoginProfile(type, code) const session = uuidv4() const time = new Date().getTime() let binding = await getBindingByIdentity(type, social_uid) let uuid = binding?.user_uuid let selectRows = [] if (uuid) { selectRows = await db.query('SELECT * FROM users WHERE uuid = ? LIMIT 1', [uuid]) } else { const legacyUser = await getLegacyUserByIdentity(type, social_uid) if (legacyUser?.uuid) { uuid = legacyUser.uuid await insertSocialBinding(uuid, type, social_uid, nickname, faceimg) selectRows = await db.query('SELECT * FROM users WHERE uuid = ? LIMIT 1', [uuid]) } } if (!uuid) { uuid = uuidv4() const username = `用户${uuid.slice(0, 8)}` let regSql = 'INSERT INTO users (uuid, username, registTime, social_uid, social_type, nickname, avatar, email) VALUES (?,?,?,?,?,?,?,?) ' let regRows = await db.query(regSql, [uuid, username, time, social_uid, type, nickname, faceimg, '未设置']) if (!regRows || regRows.affectedRows !== 1) { this.logger.error(`聚合登录用户注册失败!数据库错误`) return res.json({ ...BaseStdResponse.ERR, msg: '用户注册失败!' }) } await insertSocialBinding(uuid, type, social_uid, nickname, faceimg) selectRows = await db.query('SELECT * FROM users WHERE uuid = ? LIMIT 1', [uuid]) } if (!selectRows || selectRows.length === 0) return res.json({ ...BaseStdResponse.ERR, msg: '用户登录失败!请稍后再试' }) const user = selectRows[0] await Redis.set(`userSession:${uuid}`, session, { EX: 2592000 }) await db.query( 'UPDATE users SET lastTime = ?, avatar = ?, nickname = ? WHERE uuid = ?', [time, faceimg, nickname, uuid] ) await updateSocialBindingProfile(type, social_uid, nickname, faceimg) await syncLegacySocialMirror(uuid, type) res.json({ ...BaseStdResponse.OK, data: { uuid, username: user.username, session, nickname, type, roles: user.permission || [], vip: user.vip, ic_count: user.ic_count, lepao_count: user.lepao_count, crouse_count: user.crouse_count, avatar: faceimg || user.avatar, email: user.email } }) // 增加登录记录 try { const userAgent = req.headers['user-agent'] let insertSql = 'INSERT INTO login_history (uuid, time, deviceInfo, type, ip) VALUES (?, ?, ?, ?, ?)' await db.query(insertSql, [uuid, time, { 'ua': userAgent }, type, ip]) } catch (error) { this.logger.error(`写入登录记录失败!${error}`) } } catch (error) { this.logger.error(`获取用户信息失败!${error.message || 'api接口错误'}`) return res.json({ ...BaseStdResponse.ERR, msg: '获取用户信息失败!' }) } } } module.exports.Login = Login