Browse Source

重置密码接口&发送重置密码邮件

langshi 8 months ago
parent
commit
20197ad6ac

+ 62 - 2
app/Http/Controllers/API/AuthController.php

@@ -3,13 +3,18 @@
 namespace App\Http\Controllers\API;
 
 use App\Http\Controllers\Controller;
+use App\Http\Requests\API\User\ForgetPasswordEmialRequest;
 use App\Http\Requests\API\User\LoginRequest;
+use App\Http\Requests\API\User\ResetPasswordRequest;
+use App\Mail\ForgetPasswordMailable;
 use App\Models\User;
-use Illuminate\Http\Request;
+use Carbon\Carbon;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Facades\Mail;
+use Illuminate\Support\Str;
 use Illuminate\Validation\ValidationException;
-use Laravel\Sanctum\PersonalAccessToken;
 
 class AuthController extends Controller
 {
@@ -45,4 +50,59 @@ class AuthController extends Controller
 
         return $this->noContent();
     }
+
+    /**
+     * 发送重置密码邮件
+     * @param ForgetPasswordEmialRequest $request username用户名或邮箱
+     * @return \Illuminate\Http\Response
+     * @throws \Random\RandomException
+     */
+    public function sendForgetPasswordEmail(ForgetPasswordEmialRequest $request)
+    {
+        //1.通过用户名或邮箱检索用户
+       $user = User::query()
+            ->where('username',$request->username)
+            ->orWhere('email',$request->username)
+            ->first();
+        //2.生成 验证码
+        $captcha = random_int(100000, 999999);
+        DB::table('password_reset_tokens')->insert([
+            'email' => $user->email,
+            'token' => $captcha,
+            'created_at' => Carbon::now()
+        ]);
+        //3.发送重置验证码邮件
+        Mail::to($user)->send(new ForgetPasswordMailable($captcha));
+        return $this->noContent();
+    }
+
+    /**
+     * 重置用户密码
+     * @param ResetPasswordRequest $request
+     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
+     */
+    public function resetPassword(ResetPasswordRequest $request)
+    {
+        //1.通过用户名或邮箱检索用户
+        $user = User::query()
+            ->where('username',$request->username)
+            ->orWhere('email',$request->username)
+            ->first();
+        //2.获取该用户的最后验证码信息
+        $resetToken = DB::table('password_reset_tokens')
+            ->where('email', $user->email)
+            ->orderBy('created_at', 'desc')
+            ->first(); // 获取第一条记录;
+
+        //3.判断验证码是否存在 验证码是否一致 验证码是否过期(15分钟) 若过期,执行以下if代码
+        if (!$resetToken || $resetToken->token != $request->code || Carbon::parse($resetToken->created_at)->diffInMinutes(Carbon::now()) > 15){
+            // 这里抛出错误是否更好?
+            return $this->badRequest('Verification code error or expired');
+        }
+        //4.一切没问题,则修改该用户的密码
+        $user->password = Hash::make($request->new_password);
+        $user->save();
+        return $this->noContent();
+
+    }
 }

+ 28 - 0
app/Http/Requests/API/User/ForgetPasswordEmialRequest.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Http\Requests\API\User;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class ForgetPasswordEmialRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'username' => 'required'
+        ];
+    }
+}

+ 30 - 0
app/Http/Requests/API/User/ResetPasswordRequest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Http\Requests\API\User;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class ResetPasswordRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'username' => 'required',
+            'code' => 'required',
+            'new_password' => 'required|min:6|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{6,}$/',// 至少6位,包含大小写字母和数字,At least 6 digits, including upper and lower case letters and numbers
+        ];
+    }
+}

+ 56 - 0
app/Mail/ForgetPasswordMailable.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace App\Mail;
+
+use App\Models\Enums\ObjectAction;
+use App\Models\Requirement;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Mail\Mailable;
+use Illuminate\Mail\Mailables\Content;
+use Illuminate\Mail\Mailables\Envelope;
+use Illuminate\Queue\SerializesModels;
+
+class ForgetPasswordMailable extends Mailable
+{
+    use Queueable, SerializesModels;
+
+    /**
+     * Create a new message instance.
+     */
+    public function __construct(public  int $code)
+    {
+
+    }
+
+    /**
+     * Get the message envelope.
+     */
+    public function envelope(): Envelope
+    {
+        return new Envelope(
+            subject: 'Password Reset Verification Code: '.$this->code,
+        );
+    }
+
+    /**
+     * Get the message content definition.
+     */
+    public function content(): Content
+    {
+        return new Content(
+            //view: 'view.name',
+            markdown: 'emails.user.forgetPasswordCaptcha',
+        );
+    }
+
+    /**
+     * Get the attachments for the message.
+     *
+     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
+     */
+    public function attachments(): array
+    {
+        return [];
+    }
+}

+ 11 - 0
resources/views/emails/user/forgetPasswordCaptcha.blade.php

@@ -0,0 +1,11 @@
+<x-mail::message>
+    ## You are resetting your password, please ignore it if you are not doing it yourself.
+
+    # CODE
+
+    # {{$code}}
+
+    ### Valid in 15 minutes
+
+    {{ config('app.name') }}
+</x-mail::message>

+ 2 - 0
routes/api.php

@@ -16,6 +16,8 @@ use App\Http\Controllers\API;
 */
 
 Route::post("/login", [API\AuthController::class, "login"]);
+Route::post("/send-forget-password-email", [API\AuthController::class, "sendForgetPasswordEmail"]);
+Route::post("/reset-password", [API\AuthController::class, "resetPassword"]);
 //暂时为免登录
 Route::get("file/download/{uuid}/share-file", [API\FileController::class, "downloadShareFile"])
     ->name("file.download-share-file");