From 5ee74c8a38f502ef0b4b06b13677ac9a59f1edd2 Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Fri, 10 May 2024 18:53:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9email=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/login.controller.ts | 2 ++ src/modules/CodeRecord.ts | 1 + src/plats/PlatEmail.ts | 49 +++++++++++++++++++++++++++++ src/service/email.svr.ts | 9 ++++++ 4 files changed, 61 insertions(+) create mode 100644 src/plats/PlatEmail.ts diff --git a/src/controllers/login.controller.ts b/src/controllers/login.controller.ts index 3a7484b..363a3fe 100644 --- a/src/controllers/login.controller.ts +++ b/src/controllers/login.controller.ts @@ -7,6 +7,7 @@ import { IPlat } from 'plats/IPlat' import { PlatApple } from 'plats/PlatApple' import { PlatClient } from 'plats/PlatClient' import { PlatDiscord } from 'plats/PlatDiscord' +import { PlatEmail } from 'plats/PlatEmail' import { PlatExternalWallet } from 'plats/PlatExternalWallet' import { PlatFacebook } from 'plats/PlatFacebook' import { PlatGoogle } from 'plats/PlatGoogle' @@ -24,6 +25,7 @@ const plats: Map = new Map([ [PlatEnum.EXTERNAL_WALLET, new PlatExternalWallet()], [PlatEnum.RELAY_WALLET, new PlatExternalWallet()], [PlatEnum.DISCORD, new PlatDiscord()], + [PlatEnum.EMAIL, new PlatEmail()], ]) // 如果客户端有传入account, 则说明该次登录是绑定账号 diff --git a/src/modules/CodeRecord.ts b/src/modules/CodeRecord.ts index 737b34c..d8e1ca4 100644 --- a/src/modules/CodeRecord.ts +++ b/src/modules/CodeRecord.ts @@ -13,6 +13,7 @@ export enum CodeType { REGIST = 1, // 注册 RESET = 2, // 重置密码 VERIFY = 3, // 验证邮箱 + LOGIN = 4, // 验证码登录 } export enum CodeStatus { diff --git a/src/plats/PlatEmail.ts b/src/plats/PlatEmail.ts new file mode 100644 index 0000000..a04f55a --- /dev/null +++ b/src/plats/PlatEmail.ts @@ -0,0 +1,49 @@ +import { ZError } from 'zutils' +import { IPlat } from './IPlat' +import { CodeRecord, CodeStatus, CodeType } from 'modules/CodeRecord' +import { sha1 } from 'zutils/utils/security.util' + +const isEmail = (email: string) => { + const reg = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/ + return reg.test(email) +} + +const isCode = (code: string) => { + const reg = /^\d{6}$/ + return reg.test(code) +} + +export class PlatEmail implements IPlat { + async verifyToken(req: any): Promise { + let { code, token } = req.params + code = code || token + try { + JSON.parse(code) + } catch (err) { + throw new ZError(20, 'error parse token') + } + let payload = JSON.parse(code) + let { email, password } = payload + if (!email || !password || !isEmail(email) || !isCode(password)) { + throw new ZError(10, 'params mismatch') + } + let recordCode = await CodeRecord.findByEmail(email, CodeType.LOGIN) + if (!recordCode) { + throw new ZError(11, 'code not exists') + } + if (recordCode.status !== CodeStatus.PENDING) { + throw new ZError(13, 'code expired') + } + if (recordCode.code !== password) { + throw new ZError(14, 'code error') + } + const openId = sha1(email) + let data: any = { email, emailVerified: true } + const { api_platform } = req.headers + if (api_platform) { + data.platform = api_platform + } + + return { openId, data } + } +} diff --git a/src/service/email.svr.ts b/src/service/email.svr.ts index 3580641..f0e6a6d 100644 --- a/src/service/email.svr.ts +++ b/src/service/email.svr.ts @@ -34,6 +34,15 @@ export const DEFAULT_VERIFY_MAIL_HTML = `

Use it to login CEBG. Never share this code with anyone.

` +export const DEFAULT_LOGIN_MAIL_SUBJECT = 'Counter Fire email login code' +export const DEFAULT_LOGIN_MAIL_HTML = ` +

Your Counter Fire email login code is

+

{{ocde}}

+

{{time}}

+

This is your one time code that expires in 5 minutes.

+

Use it to login Counter Fire. Never share this code with anyone.

+` + export interface IMailData { from?: string to: string