mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-28 04:40:37 +00:00
feat: 新增修改邮箱功能
This commit is contained in:
parent
1daba51286
commit
d80943ab6b
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 = "<p>{$user->nickname} 您好,您正在绑定 " . env('APP_NAME') . " 的邮箱,请于30分钟之内点击以下链接完成验证 :</p><p style='display: flex; justify-content: center;'><a href='{$url}' target='_blank'>{$url}</a></p>";
|
||||
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 = "<p>{$user->nickname} 您好,您正在修改 " . env('APP_NAME') . " 的邮箱,验证码如下。请在30分钟内输入验证码</p><p style='color: #0000DD; margin-left: 10%;'>$code</p><p>如果不是本人操作,您的账号可能存在风险,请及时修改密码!</p>";
|
||||
}else{
|
||||
$subject = env('APP_NAME') . "绑定邮箱验证";
|
||||
$content = "<p>{$user->nickname} 您好,您正在绑定 " . env('APP_NAME') . " 的邮箱,请于30分钟之内点击以下链接完成验证 :</p><p style='display: flex; justify-content: center;'><a href='{$url}' target='_blank'>{$url}</a></p>";
|
||||
}
|
||||
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");
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTypeToUserEmailVerificationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('user_email_verifications', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('user_email_verifications', 'type')) {
|
||||
$table->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");
|
||||
});
|
||||
}
|
||||
}
|
||||
13
public/js/language.all.js
vendored
13
public/js/language.all.js
vendored
@ -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)
|
||||
|
||||
120
resources/assets/js/pages/manage/setting/email.vue
Normal file
120
resources/assets/js/pages/manage/setting/email.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="setting-item submit">
|
||||
<Form ref="formDatum" :model="formDatum" :rules="ruleDatum" label-width="auto" @submit.native.prevent>
|
||||
<FormItem :label="$L('新邮箱地址')" prop="newEmail">
|
||||
<Row>
|
||||
<Col span="6">
|
||||
<Input v-model="formDatum.newEmail"></Input>
|
||||
</Col>
|
||||
<Col span="6" v-if="isRegVerify == 1">
|
||||
<Button v-if="isUpdateShow" @click="sendEmailCode" type="primary">{{ $L('发送验证码') }}</Button>
|
||||
<Button v-if="!isUpdateShow" disabled><span>{{ count }}</span>{{ $L('秒') }}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('验证码')" prop="code" v-if="isRegVerify == 1">
|
||||
<Input v-model="formDatum.code" :placeholder="$L('输入邮箱验证码')"/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div class="setting-footer">
|
||||
<Button :loading="loadIng > 0" type="primary" @click="submitForm">{{ $L('提交') }}</Button>
|
||||
<Button :loading="loadIng > 0" @click="resetForm" style="margin-left: 8px">{{ $L('重置') }}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
|
||||
formDatum: {
|
||||
newEmail: '',
|
||||
code: '',
|
||||
},
|
||||
ruleDatum: {},
|
||||
count: 0,
|
||||
isUpdateShow: true,
|
||||
codeShow: false,
|
||||
isRegVerify: 0,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getRegVerify();
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.ruleDatum = {
|
||||
newEmail: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error(this.$L('请输入新邮箱地址!')));
|
||||
} else if (!$A.isEmail(value)) {
|
||||
callback(new Error(this.$L('请输入正确的邮箱地址!')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
required: true,
|
||||
trigger: 'change'
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
sendEmailCode() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/send/email',
|
||||
data: {type: 2, email: this.formDatum.newEmail}
|
||||
}).then(({}) => {
|
||||
this.isUpdateShow = false;
|
||||
this.count = 120; //赋值120秒
|
||||
let times = setInterval(() => {
|
||||
this.count--; //递减
|
||||
if (this.count <= 0) {
|
||||
this.isUpdateShow = true;
|
||||
clearInterval(times);
|
||||
}
|
||||
}, 1000); //1000毫秒后执行
|
||||
}).catch(({msg}) => {
|
||||
$A.messageError(msg);
|
||||
})
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.formDatum.validate((valid) => {
|
||||
if (valid) {
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/editemail',
|
||||
data: this.formDatum,
|
||||
}).then(({data}) => {
|
||||
$A.messageSuccess('修改成功');
|
||||
this.$store.dispatch("saveUserInfo", data);
|
||||
this.$refs.formDatum.resetFields();
|
||||
this.isUpdateShow = true;
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
}).finally(_ => {
|
||||
this.loadIng--;
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.$refs.formDatum.resetFields();
|
||||
},
|
||||
|
||||
getRegVerify() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'system/get/regverify',
|
||||
}).then(({data}) => {
|
||||
this.isRegVerify = data;
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -73,6 +73,7 @@ export default {
|
||||
{path: 'personal', name: '个人设置'},
|
||||
{path: 'language', name: '语言设置'},
|
||||
{path: 'password', name: '密码设置'},
|
||||
{path: 'email', name: '修改邮箱'},
|
||||
]
|
||||
if ([
|
||||
'127.0.0.1:2222',
|
||||
|
||||
5
resources/assets/js/routes.js
vendored
5
resources/assets/js/routes.js
vendored
@ -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',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user