From d80943ab6b4e4cd0b88f5aeb259e526909b52c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=8D=A3=E8=B6=85?= <302645122@qq.com> Date: Tue, 12 Jul 2022 18:23:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=82=AE=E7=AE=B1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/SystemController.php | 20 +++ app/Http/Controllers/Api/UsersController.php | 96 ++++++++++++++ app/Models/UserEmailVerification.php | 47 ++++--- ...type_to_user_email_verifications_table.php | 34 +++++ public/js/language.all.js | 13 ++ .../assets/js/pages/manage/setting/email.vue | 120 ++++++++++++++++++ .../assets/js/pages/manage/setting/index.vue | 1 + resources/assets/js/routes.js | 5 + 8 files changed, 316 insertions(+), 20 deletions(-) create mode 100644 database/migrations/2022_07_12_104211_add_type_to_user_email_verifications_table.php create mode 100644 resources/assets/js/pages/manage/setting/email.vue diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index 1b38b15e8..5550e393b 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -753,4 +753,24 @@ class SystemController extends AbstractController } return $array; } + + /** + * @api {get} api/system/get/regverify 18. 获取是否开启邮箱验证 + * + * @apiDescription 获取邮箱配置是否开启注册邮箱验证 + * @apiVersion 1.0.0 + * @apiGroup system + * @apiName get__regverify + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function get__regverify() + { + User::auth(); + $isRegVerify = Base::settingFind('emailSetting', 'reg_verify') === 'open'; + return Base::retSuccess('success', $isRegVerify ? 1 : 0); + } + } diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index e42b9a973..f42aec0b1 100755 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -983,4 +983,100 @@ class UsersController extends AbstractController $data['msgs'] = $msgs; return Base::retSuccess('发送邀请成功', $data); } + + /** + * @api {get} api/users/send/email 18. 发送邮箱验证码 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup users + * @apiName send__email + * + * @apiParam {Number} type 邮件类型 + * @apiParam {String} email 邮箱地址 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function send__email() + { + $type = Request::input('type', 2); + $email = Request::input('email'); + $user = User::auth(); + if (!$email) { + return Base::retError('请输入新邮箱地址'); + } + if (!Base::isEmail($email)) { + return Base::retError('邮箱地址错误'); + } + if ($user->email == $email) { + return Base::retError('不能与旧邮箱一致'); + } + if (User::where('userid', '<>', $user->userid)->whereEmail($email)->exists()) { + return Base::retError('邮箱地址已存在'); + } + UserEmailVerification::userEmailSend($user, $type, $email); + return Base::retSuccess('发送成功'); + } + + /** + * @api {get} api/users/editemail 19. 修改邮箱 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup users + * @apiName editemail + * + * @apiParam {String} newEmail 新邮箱地址 + * @apiParam {String} code 邮箱验证码 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function editemail() + { + $user = User::auth(); + $user->checkSystem(); + // + $newEmail = trim(Request::input('newEmail')); + $code = trim(Request::input('code')); + if (!$newEmail) { + return Base::retError('请输入新邮箱地址'); + } + if (!Base::isEmail($newEmail)) { + return Base::retError('邮箱地址错误'); + } + + $isRegVerify = Base::settingFind('emailSetting', 'reg_verify') === 'open'; + if ($isRegVerify) { + if (!$code) { + return Base::retError('请输入验证码'); + } + + $res = UserEmailVerification::whereEmail($newEmail)->whereCode($code)->whereType(2)->orderByDesc('id')->first(); + + if (empty($res)) { + return Base::retError('验证码错误'); + } + + $oldTime = Carbon::parse($res->created_at)->timestamp; + $time = Base::Time(); + + // 30分钟失效 + if (abs($time - $oldTime) > 1800) { + return Base::retError("验证码已失效"); + } + + UserEmailVerification::whereUserid($user->userid)->whereCode($code)->whereType(2)->update([ + 'status' => 1 + ]); + } + + $user->email = $newEmail; + $user->save(); + User::token($user); + return Base::retSuccess('修改成功', $user); + } } diff --git a/app/Models/UserEmailVerification.php b/app/Models/UserEmailVerification.php index eb0f2b4dd..755ea47fb 100644 --- a/app/Models/UserEmailVerification.php +++ b/app/Models/UserEmailVerification.php @@ -36,39 +36,46 @@ class UserEmailVerification extends AbstractModel /** * 发验证邮箱 * @param User $user + * @param int $type + * @param null $newEmail */ - public static function userEmailSend(User $user) + public static function userEmailSend(User $user, $type = 1, $newEmail = null) { - $res = self::whereUserid($user->userid)->where('created_at', '>', Carbon::now()->subMinutes(30))->first(); + $email = $type == 2 ? $newEmail : $user->email; + $res = self::whereEmail($email)->where('created_at', '>', Carbon::now()->subMinutes(30))->whereType($type)->first(); if ($res) return; //删除 - self::whereUserid($user->userid)->delete(); + self::whereUserid($email)->delete(); + $code = $type == 2 ? rand(100000, 999999) : Base::generatePassword(64); $userEmailVerification = self::createInstance([ 'userid' => $user->userid, - 'email' => $user->email, - 'code' => Base::generatePassword(64), + 'email' => $email, + 'code' => $code, 'status' => 0, + 'type' => $type ]); $userEmailVerification->save(); - $setting = Base::setting('emailSetting'); $url = Base::fillUrl('single/valid/email') . '?code=' . $userEmailVerification->code; try { - if (!Base::isEmail($user->email)) { - throw new \Exception("User email '{$user->email}' address error"); + if (!Base::isEmail($email)) { + throw new \Exception("User email '{$email}' address error"); } - $subject = env('APP_NAME') . " 绑定邮箱验证"; - $content = "

{$user->nickname} 您好,您正在绑定 " . env('APP_NAME') . " 的邮箱,请于30分钟之内点击以下链接完成验证 :

{$url}

"; - Setting::validateAddr($user->email, function ($to) use ($content, $subject, $setting) { - Factory::mailer() - ->setDsn("smtp://{$setting['account']}:{$setting['password']}@{$setting['smtp_server']}:{$setting['port']}?verify_peer=0") - ->setMessage(EmailMessage::create() - ->from(env('APP_NAME', 'Task') . " <{$setting['account']}>") - ->to($to) - ->subject($subject) - ->html($content)) - ->send(); - }); + if($type ==2){ + $subject = env('APP_NAME') . "修改邮箱验证"; + $content = "

{$user->nickname} 您好,您正在修改 " . env('APP_NAME') . " 的邮箱,验证码如下。请在30分钟内输入验证码

$code

如果不是本人操作,您的账号可能存在风险,请及时修改密码!

"; + }else{ + $subject = env('APP_NAME') . "绑定邮箱验证"; + $content = "

{$user->nickname} 您好,您正在绑定 " . env('APP_NAME') . " 的邮箱,请于30分钟之内点击以下链接完成验证 :

{$url}

"; + } + Factory::mailer() + ->setDsn("smtp://{$setting['account']}:{$setting['password']}@{$setting['smtp_server']}:{$setting['port']}?verify_peer=0") + ->setMessage(EmailMessage::create() + ->from(env('APP_NAME', 'Task') . " <{$setting['account']}>") + ->to($email) + ->subject($subject) + ->html($content)) + ->send(); } catch (\Throwable $e) { if (str_contains($e->getMessage(), "Timed Out")) { throw new ApiException("language.TimedOut"); diff --git a/database/migrations/2022_07_12_104211_add_type_to_user_email_verifications_table.php b/database/migrations/2022_07_12_104211_add_type_to_user_email_verifications_table.php new file mode 100644 index 000000000..c196a46ea --- /dev/null +++ b/database/migrations/2022_07_12_104211_add_type_to_user_email_verifications_table.php @@ -0,0 +1,34 @@ +tinyInteger('type')->nullable()->default(1)->after('status')->comment('邮件类型:1-邮箱认证,2-修改邮箱'); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('user_email_verifications', function (Blueprint $table) { + $table->dropColumn("type"); + }); + } +} diff --git a/public/js/language.all.js b/public/js/language.all.js index 541f70053..a2c0182b3 100644 --- a/public/js/language.all.js +++ b/public/js/language.all.js @@ -500,5 +500,18 @@ {"CN": "邀请码:注册时需填写下方邀请码。","EN": "Invitation code: You need to fill in the following invitation code when registering.","TC": "邀請碼:註冊時需填寫下方邀請碼。","KM": "លេខកូដលិខិតអញ្ជើញ: អ្នកត្រូវបំពេញលេខកូដលិខិតអញ្ជើញខាងក្រោមនៅពេលចុះឈ្មោះ។","TH": "รหัสเชิญ: คุณต้องกรอกรหัสคำเชิญต่อไปนี้เมื่อลงทะเบียน","KO": "초대 코드 : 등록 할 때 다음 초대 코드를 입력해야합니다.","JA": "招待コード:登録時に次の招待コードを入力する必要があります。"}, {"CN": "添加模板","EN": "Add template","TC": "添加模板","KM": "បន្ថែមគំរូ","TH": "เพิ่มเทมเพลต","KO": "템플릿을 추가하십시오","JA": "テンプレートを追加します"}, {"CN": "版本","EN": "Version","TC": "版本","KM": "កមបុរក្នា","TH": "รุ่น","KO": "버전","JA": "バージョン"}, + {"CN": "请输入新邮箱地址","EN": "Please enter the new mailbox address","TC": "請輸入新郵箱地址","KM": "សូមបញ្ចូលអាសយដ្ឋានប្រអប់សំបុត្រថ្មី","TH": "โปรดป้อนที่อยู่กล่องจดหมายใหม่","KO": "새 사서함 주소를 입력하십시오","JA": "新しいメールボックスアドレスを入力してください"}, + {"CN": "邮箱地址错误","EN": "Email address error","TC": "郵箱地址錯誤","KM": "កំហុសអាសយដ្ឋានអ៊ីមែល","TH": "ข้อผิดพลาดที่อยู่อีเมล","KO": "이메일 주소 오류","JA": "メールアドレスエラー"}, + {"CN": "不能与旧邮箱一致","EN": "Can't be consistent with the old mailbox","TC": "不能與舊郵箱一致","KM": "មិនអាចត្រូវបានស្របជាមួយនឹងប្រអប់សំបុត្រចាស់","TH": "ไม่สามารถสอดคล้องกับกล่องจดหมายเก่า","KO": "이전 사서함과 일치 할 수 없습니다","JA": "古いメールボックスと一致することはできません"}, + {"CN": "验证码错误","EN": "Verification code error","TC": "驗證碼錯誤","KM": "កំហុសក្នុងការផ្ទៀងផ្ទាត់លេខកូដ","TH": "ข้อผิดพลาดของรหัสการตรวจสอบ","KO": "Verifin 코드 오류","JA": "検証コードエラー"}, + {"CN": "验证码已失效","EN": "The verification code has failed","TC": "驗證碼已失效","KM": "លេខកូដផ្ទៀងផ្ទាត់បានបរាជ័យ","TH": "รหัสการยืนยันล้มเหลว","KO": "검증 코드가 실패했습니다","JA": "検証コードは失敗しました"}, + {"CN": "发送验证码","EN": "Send the verification code","TC": "發送驗證碼","KM": "ផ្ញើកូដផ្ទៀងផ្ទាត់","TH": "ส่งรหัสการยืนยัน","KO": "확인 코드를 보냅니다","JA": "確認コードを送信します"}, + {"CN": "秒","EN": "Second","TC": "秒","KM": "ដេលរេបីរយចហើយ","TH": "ที่สอง","KO": "섹스","JA": "2番目"}, + {"CN": "输入邮箱验证码","EN": "Enter the mailbox verification code","TC": "輸入郵箱驗證碼","KM": "បញ្ចូលលេខកូដផ្ទៀងផ្ទាត់ប្រអប់សំបុត្រ","TH": "ป้อนรหัสการยืนยันกล่องจดหมาย","KO": "사서함 확인 코드를 입력하십시오","JA": "メールボックス検証コードを入力します"}, + {"CN": "新邮箱地址","EN": "New mailbox address","TC": "新郵箱地址","KM": "អាសយដ្ឋានប្រអប់សំបុត្រថ្មី","TH": "ที่อยู่กล่องจดหมายใหม่","KO": "새로운 사서함 주소","JA": "新しいメールボックスアドレス"}, + {"CN": "请输入新邮箱地址!","EN": "Please enter the new mailbox address!","TC": "請輸入新郵箱地址!","KM": "សូមបញ្ចូលអាសយដ្ឋានប្រអប់សំបុត្រថ្មី!","TH": "กรุณากรอกที่อยู่กล่องจดหมายใหม่!","KO": "새 사서함 주소를 입력하십시오!","JA": "新しいメールボックスアドレスを入力してください!"}, + {"CN": "请输入正确的邮箱地址!","EN": "Please input the correct email address!","TC": "請輸入正確的郵箱地址!","KM": "សូមបញ្ចូលអាសយដ្ឋានអ៊ីមែលត្រឹមត្រូវ!","TH": "กรุณาป้อนที่อยู่อีเมลที่ถูกต้อง!","KO": "thecorct 이메일 주소를 입력하십시오!","JA": "正しいメールアドレスを入力してください!"}, + {"CN": "验证码","EN": "Verification code","TC": "驗證碼","KM": "កូដ​ផ្ទៀង​ផ្ទាត់","TH": "รหัสการตรวจสอบ","KO": "Verifin 코드","JA": "検証コード"}, + {"CN": "修改邮箱","EN": "Modify the mailbox","TC": "修改郵箱","KM": "កែប្រែប្រអប់សំបុត្រ","TH": "แก้ไขกล่องจดหมาย","KO": "사서함을 수정하십시오","JA": "メールボックスを変更します"}, ] })(window) diff --git a/resources/assets/js/pages/manage/setting/email.vue b/resources/assets/js/pages/manage/setting/email.vue new file mode 100644 index 000000000..be598a7c9 --- /dev/null +++ b/resources/assets/js/pages/manage/setting/email.vue @@ -0,0 +1,120 @@ + + + + diff --git a/resources/assets/js/pages/manage/setting/index.vue b/resources/assets/js/pages/manage/setting/index.vue index 81284523b..7f91414b8 100644 --- a/resources/assets/js/pages/manage/setting/index.vue +++ b/resources/assets/js/pages/manage/setting/index.vue @@ -73,6 +73,7 @@ export default { {path: 'personal', name: '个人设置'}, {path: 'language', name: '语言设置'}, {path: 'password', name: '密码设置'}, + {path: 'email', name: '修改邮箱'}, ] if ([ '127.0.0.1:2222', diff --git a/resources/assets/js/routes.js b/resources/assets/js/routes.js index df8e61c1b..39f95110e 100755 --- a/resources/assets/js/routes.js +++ b/resources/assets/js/routes.js @@ -49,6 +49,11 @@ export default [ path: 'password', component: () => import('./pages/manage/setting/password.vue'), }, + { + name: 'manage-setting-email', + path: 'email', + component: () => import('./pages/manage/setting/email.vue'), + }, { name: 'manage-setting-system', path: 'system',