wallet-svr/src/controllers/mail.controller.ts
2023-08-10 13:43:27 +08:00

189 lines
5.3 KiB
TypeScript

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 }
}
}