import BaseController, { ROLE_ANON } from 'common/base.controller' import { ZError } from 'common/ZError' import { role, router } from 'decorators/router' import logger from 'logger/logger' import { Account, PlatEnum } from 'modules/Account' import { CodeRecord, CodeStatus, CodeType, DEFAULT_CODE, DEFAULT_EXPIRE_TIME } from 'modules/CodeRecord' import { DEFAULT_REGIST_HTML, DEFAULT_REGIST_SUBJECT, DEFAULT_RESET_HTML, DEFAULT_RESET_SUBJECT, DEFAULT_VERIFY_MAIL_HTML, DEFAULT_VERIFY_MAIL_SUBJECT, EmailSvr, } from 'service/email.svr' import { uuid } from 'utils/security.util' class MailController extends BaseController { /** * 通过邮件, 密码形式的登录 */ @role(ROLE_ANON) @router('post /wallet/login/email') async loginWithEmail(req, res) { let { email, password } = req.params if (!email || !password) { throw new ZError(10, 'params mismatch') } // check Account exists let record = await Account.findByEmail(email) if (!record) { throw new ZError(11, 'account not exists') } if (record.locked) { throw new ZError(12, 'account locked') } if (!record.verifyPassword(password)) { throw new ZError(13, 'password error') } const token = await res.jwtSign({ id: record.id, openid: record.openId, version: record.accountVersion || 0, plat: PlatEnum.EMAIL, }) return { token: token } } /** * 注册email账号 */ @role(ROLE_ANON) @router('post /email/regist') async registMailAccount(req, res) { let { email, code, password } = req.params if (!email || !code || !password) { throw new ZError(10, 'params mismatch') } let account = await Account.findByEmail(email) if (account) { throw new ZError(11, 'account exists') } let record = await CodeRecord.findByEmail(email, CodeType.REGIST) if (!record) { throw new ZError(12, 'code not exists') } if (record.status !== CodeStatus.PENDING) { throw new ZError(13, 'code expired') } if (record.code !== code) { throw new ZError(14, 'code error') } account = new Account({ plat: PlatEnum.EMAIL, email, openId: uuid() }) account.updatePassword(password) account.emailReal = email account.emailVerified = true await account.save() record.status = CodeStatus.SUCCESS await record.save() const ztoken = await res.jwtSign({ id: account.id, openid: account.openId, plat: PlatEnum.EMAIL }) return { token: ztoken } } /** * 通过email重置密码 */ @role(ROLE_ANON) @router('post /email/reset_password') async resetMailPassword(req, res) { let { email, code, password } = req.params if (!email || !code || !password) { throw new ZError(10, 'params mismatch') } let account = await Account.findByEmail(email) if (!account) { throw new ZError(11, 'account not exists') } let record = await CodeRecord.findByEmail(email, CodeType.RESET) if (!record) { throw new ZError(12, 'code not exists') } if (record.status !== CodeStatus.PENDING) { throw new ZError(13, 'code expired') } if (record.code !== code) { throw new ZError(14, 'code error') } account.updatePassword(password) await account.save() record.status = CodeStatus.SUCCESS await record.save() return {} } /** * 发送验证码 */ @role(ROLE_ANON) @router('post /email/send_code') async sendVerifyCode(req, res) { let { email, type } = req.params if (!email || !type) { throw new ZError(10, 'params mismatch') } type = parseInt(type) if (type === CodeType.REGIST) { let account = await Account.findByEmail(email) if (account) { throw new ZError(11, 'account exists') } } let record = await CodeRecord.findByEmail(email, type) if (!record) { record = new CodeRecord({ email, type, code: DEFAULT_CODE }) await record.save() } let html, subject switch (type) { case CodeType.REGIST: html = DEFAULT_REGIST_HTML subject = DEFAULT_REGIST_SUBJECT break case CodeType.RESET: html = DEFAULT_RESET_HTML subject = DEFAULT_RESET_SUBJECT break case CodeType.VERIFY: html = DEFAULT_VERIFY_MAIL_HTML subject = DEFAULT_VERIFY_MAIL_SUBJECT } subject = record.code + ' ' + subject html = html.replace('{{ocde}}', record.code) html = html.replace('{{time}}', new Date().format('yyyy-MM-dd hh:mm:ss')) let msgData = { to: email, html, subject, } try { let result = await new EmailSvr().sendMail(msgData) record.mailSend = true record.emailId = result.messageId record.expiredAt = Date.now() + DEFAULT_EXPIRE_TIME await record.save() } catch (err) { logger.info(`error send mail:: email: ${email}, type: ${type}`) logger.error(err) record.status = CodeStatus.FAIL await record.save() throw new ZError(14, 'send mail error') } return {} } /** * 检查email是否已经被注册 */ @role(ROLE_ANON) @router('post /email/check') async checkMailExists(req, res) { let { email } = req.params if (!email) { throw new ZError(10, 'params mismatch') } let account = await Account.findByEmail(email) return { exists: !!account } } }