diff --git a/app/Http/Controllers/AppRegisterController.php b/app/Http/Controllers/AppRegisterController.php index 77d7b952d..824cec540 100644 --- a/app/Http/Controllers/AppRegisterController.php +++ b/app/Http/Controllers/AppRegisterController.php @@ -59,12 +59,14 @@ class AppRegisterController extends Controller 'message' => 'Too many attempts, please try again later.', ]); DB::rollBack(); + return redirect()->away("pixelfed://verifyEmail?{$errorParams}"); } $registration = AppRegister::create([ 'email' => $email, 'verify_code' => $code, + 'uses' => 1, 'email_delivered_at' => now(), ]); @@ -117,6 +119,82 @@ class AppRegisterController extends Controller ]); } + public function resendVerification(Request $request) + { + abort_unless(config('auth.in_app_registration'), 404); + $open = (bool) config_cache('pixelfed.open_registration'); + if (! $open || $request->user()) { + return redirect('/'); + } + + return view('auth.iar-resend'); + } + + public function resendVerificationStore(Request $request) + { + abort_unless(config('auth.in_app_registration'), 404); + $open = (bool) config_cache('pixelfed.open_registration'); + if (! $open || $request->user()) { + return redirect('/'); + } + + $rules = [ + 'email' => 'required|email:rfc,dns,spoof,strict|unique:users,email|exists:app_registers,email', + ]; + + if ((bool) config_cache('captcha.enabled') && (bool) config_cache('captcha.active.register')) { + $rules['h-captcha-response'] = 'required|captcha'; + } + + $this->validate($request, $rules); + + $email = strtolower($request->input('email')); + $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); + + DB::beginTransaction(); + + $exists = AppRegister::whereEmail($email)->first(); + + if (! $exists || $exists->uses > 5) { + $errorMessage = $exists->uses > 5 ? 'Too many attempts have been made, please contact the admins.' : 'Email not found'; + $errorParams = http_build_query([ + 'status' => 'error', + 'message' => $errorMessage, + ]); + DB::rollBack(); + + return redirect()->away("pixelfed://verifyEmail?{$errorParams}"); + } + + $registration = $exists->update([ + 'verify_code' => $code, + 'uses' => ($exists->uses + 1), + 'email_delivered_at' => now(), + ]); + + try { + Mail::to($email)->send(new InAppRegisterEmailVerify($code)); + } catch (\Exception $e) { + DB::rollBack(); + $errorParams = http_build_query([ + 'status' => 'error', + 'message' => 'Failed to send verification code', + ]); + + return redirect()->away("pixelfed://verifyEmail?{$errorParams}"); + } + + DB::commit(); + + $queryParams = http_build_query([ + 'email' => $request->email, + 'expires_in' => 3600, + 'status' => 'success', + ]); + + return redirect()->away("pixelfed://verifyEmail?{$queryParams}"); + } + public function onboarding(Request $request) { abort_unless(config('auth.in_app_registration'), 404); @@ -161,7 +239,7 @@ class AppRegisterController extends Controller 'email_verified_at' => now(), ]); - sleep(random_int(5,10)); + sleep(random_int(8, 10)); $user = User::findOrFail($user->id); $token = $user->createToken('Pixelfed App', ['read', 'write', 'follow', 'push']); $tokenModel = $token->token; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 129ff0f8b..c46509811 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -98,6 +98,10 @@ class AppServiceProvider extends ServiceProvider return Limit::perHour(10)->by($request->ip()); }); + RateLimiter::for('app-code-resend', function (Request $request) { + return Limit::perHour(5)->by($request->ip()); + }); + // Model::preventLazyLoading(true); } diff --git a/database/migrations/2025_03_02_060626_add_count_to_app_registers_table.php b/database/migrations/2025_03_02_060626_add_count_to_app_registers_table.php new file mode 100644 index 000000000..3f52d6257 --- /dev/null +++ b/database/migrations/2025_03_02_060626_add_count_to_app_registers_table.php @@ -0,0 +1,28 @@ +unsignedInteger('uses')->default(0); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('app_registers', function (Blueprint $table) { + $table->dropColumn('uses'); + }); + } +}; diff --git a/resources/views/auth/iar-resend.blade.php b/resources/views/auth/iar-resend.blade.php new file mode 100644 index 000000000..ea1ead33a --- /dev/null +++ b/resources/views/auth/iar-resend.blade.php @@ -0,0 +1,145 @@ +@extends('layouts.blank') + +@section('content') +
Enter your email so we can send another verification code via email
+ + + + @if ($errors->any()) +Click here to send a new request.
+Enter Your Email
- @if ($errors->any()) -If you need to resend the email verification, click here.
+