diff --git a/app/Auth/ResetPassword.php b/app/Auth/ResetPassword.php
new file mode 100644
index 00000000..61ce8508
--- /dev/null
+++ b/app/Auth/ResetPassword.php
@@ -0,0 +1,26 @@
+subject(Lang::get('Passwort zurücksetzen | Adrema'))
+ ->line(Lang::get('Du erhälst diese E-Mail, weil du eine Anfrage zum zurücksetzen deines Account-Passworts gestellt hast.'))
+ ->action(Lang::get('Passwort zurücksetzen'), $url)
+ ->line(Lang::get('Dieser Link wird in :count Minuten ablaufen.', ['count' => config('auth.passwords.' . config('auth.defaults.passwords') . '.expire')]))
+ ->line(Lang::get('Wenn du die Anfrage nicht selbst gestellt hast, ist keine weitere Aktion erforderlich.'));
+ }
+}
diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php
index 465c39cc..f912e2d1 100644
--- a/app/Http/Controllers/Auth/ForgotPasswordController.php
+++ b/app/Http/Controllers/Auth/ForgotPasswordController.php
@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
+use Inertia\Inertia;
+use Inertia\Response;
class ForgotPasswordController extends Controller
{
@@ -19,4 +21,9 @@ class ForgotPasswordController extends Controller
*/
use SendsPasswordResetEmails;
+
+ public function showLinkRequestForm(): Response
+ {
+ return Inertia::render('authentication/PasswordReset');
+ }
}
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
index 34914873..8dec071d 100644
--- a/app/Http/Controllers/Auth/LoginController.php
+++ b/app/Http/Controllers/Auth/LoginController.php
@@ -44,7 +44,7 @@ class LoginController extends Controller
{
session()->put('title', 'Anmelden');
- return \Inertia::render('VLogin');
+ return \Inertia::render('authentication/VLogin');
}
/**
diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php
index b1726a36..a2d83dcc 100644
--- a/app/Http/Controllers/Auth/ResetPasswordController.php
+++ b/app/Http/Controllers/Auth/ResetPasswordController.php
@@ -5,6 +5,9 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ResetsPasswords;
+use Illuminate\Http\Request;
+use Inertia\Inertia;
+use Inertia\Response;
class ResetPasswordController extends Controller
{
@@ -27,4 +30,21 @@ class ResetPasswordController extends Controller
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
+
+ /**
+ * Display the password reset view for the given token.
+ *
+ * If no token is present, display the link request form.
+ *
+ * @param \Illuminate\Http\Request $request
+ */
+ public function showResetForm(Request $request): Response
+ {
+ $token = $request->route()->parameter('token');
+
+ return Inertia::render('authentication/PasswordResetConfirm', [
+ 'token' => $token,
+ 'email' => $request->email,
+ ]);
+ }
}
diff --git a/app/User.php b/app/User.php
index 4b7c8d95..690c256a 100644
--- a/app/User.php
+++ b/app/User.php
@@ -2,12 +2,24 @@
namespace App;
+use App\Auth\ResetPassword;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
+use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory;
+ use Notifiable;
public $guarded = [];
+
+ /**
+ * @param string $token
+ * @return void
+ */
+ public function sendPasswordResetNotification($token)
+ {
+ $this->notify(new ResetPassword($token));
+ }
}
diff --git a/database/migrations/2014_10_12_100000_create_password_resets_table.php b/database/migrations/2014_10_12_100000_create_password_resets_table.php
new file mode 100644
index 00000000..fcacb80b
--- /dev/null
+++ b/database/migrations/2014_10_12_100000_create_password_resets_table.php
@@ -0,0 +1,32 @@
+string('email')->index();
+ $table->string('token');
+ $table->timestamp('created_at')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('password_resets');
+ }
+};
diff --git a/resources/js/views/authentication/PasswordReset.vue b/resources/js/views/authentication/PasswordReset.vue
new file mode 100644
index 00000000..ac46418a
--- /dev/null
+++ b/resources/js/views/authentication/PasswordReset.vue
@@ -0,0 +1,44 @@
+
+
+
+ Passwort vergessen
+
+
+
+
+
+
diff --git a/resources/js/views/authentication/PasswordResetConfirm.vue b/resources/js/views/authentication/PasswordResetConfirm.vue
new file mode 100644
index 00000000..b4c11f0b
--- /dev/null
+++ b/resources/js/views/authentication/PasswordResetConfirm.vue
@@ -0,0 +1,62 @@
+
+
+
+ Passwort vergessen
+
+
+
+
+
+
diff --git a/resources/js/views/authentication/VLogin.vue b/resources/js/views/authentication/VLogin.vue
new file mode 100644
index 00000000..1a6dbd4f
--- /dev/null
+++ b/resources/js/views/authentication/VLogin.vue
@@ -0,0 +1,40 @@
+
+
+
+ Login
+
+
+
+
+
+
diff --git a/tests/Feature/Authentication/ForgotPasswordTest.php b/tests/Feature/Authentication/ForgotPasswordTest.php
new file mode 100644
index 00000000..81682a13
--- /dev/null
+++ b/tests/Feature/Authentication/ForgotPasswordTest.php
@@ -0,0 +1,46 @@
+withoutExceptionHandling();
+ $response = $this->get('/password/reset');
+
+ $this->assertComponent('authentication/PasswordReset', $response);
+ }
+
+ public function testItRequiresAnEmailAddress(): void
+ {
+ $this->postJson('/password/email')->assertJsonValidationErrors(['email' => 'E-Mail Adresse ist erforderlich.']);
+ }
+
+ public function testItNeedsAnActiveUser(): void
+ {
+ $this->postJson('/password/email', [
+ 'email' => 'test@aa.de',
+ ])->assertJsonValidationErrors(['email' => 'Es konnte leider kein Nutzer mit dieser E-Mail-Adresse gefunden werden.']);
+ }
+
+ public function testItSendsPasswordResetLink(): void
+ {
+ Notification::fake();
+
+ $user = User::factory()->create(['email' => 'test@aa.de']);
+ $this->postJson('/password/email', [
+ 'email' => 'test@aa.de',
+ ])->assertOk();
+
+ Notification::assertSentTo($user, ResetPassword::class);
+ }
+}