diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-03-21 21:35:51 +0100 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-03-21 21:35:51 +0100 |
| commit | bc54c8c31e7f50a7a365f9b4d22fe8c74a29f61a (patch) | |
| tree | 73a88384b9e472386d244119a0b4e4aa028c8b32 /src/app/Views | |
| parent | d1ef15fa39935bfa0420c5ac2b8c269e294c9a6d (diff) | |
| download | camagru-bc54c8c31e7f50a7a365f9b4d22fe8c74a29f61a.tar.gz camagru-bc54c8c31e7f50a7a365f9b4d22fe8c74a29f61a.zip | |
Add user authentication with email verification and password reset
Implements registration, login/logout, email verification via token,
and password reset flow. Includes CSRF protection, flash messages,
MailPit for dev email testing, and security docs in README.
Diffstat (limited to 'src/app/Views')
| -rw-r--r-- | src/app/Views/auth/forgot-password.php | 13 | ||||
| -rw-r--r-- | src/app/Views/auth/login.php | 17 | ||||
| -rw-r--r-- | src/app/Views/auth/register.php | 23 | ||||
| -rw-r--r-- | src/app/Views/auth/reset-password.php | 17 | ||||
| -rw-r--r-- | src/app/Views/layouts/main.php | 2 | ||||
| -rw-r--r-- | src/app/Views/partials/flash.php | 8 |
6 files changed, 79 insertions, 1 deletions
diff --git a/src/app/Views/auth/forgot-password.php b/src/app/Views/auth/forgot-password.php new file mode 100644 index 0000000..c0eb25e --- /dev/null +++ b/src/app/Views/auth/forgot-password.php @@ -0,0 +1,13 @@ +<?php // Forgot password form: enter email to receive a reset link.?> +<div class="auth-page"> + <h1>Forgot password</h1> + <?php include __DIR__ . '/../partials/flash.php'; ?> + <form method="POST" action="/forgot-password" class="auth-form"> + <?= \App\Csrf::field() ?> + <label for="email">Email</label> + <input type="email" id="email" name="email" required> + + <button type="submit">Send reset link</button> + </form> + <p><a href="/login">Back to login</a></p> +</div> diff --git a/src/app/Views/auth/login.php b/src/app/Views/auth/login.php new file mode 100644 index 0000000..da9e7e5 --- /dev/null +++ b/src/app/Views/auth/login.php @@ -0,0 +1,17 @@ +<?php // Login form.?> +<div class="auth-page"> + <h1>Login</h1> + <?php include __DIR__ . '/../partials/flash.php'; ?> + <form method="POST" action="/login" class="auth-form"> + <?= \App\Csrf::field() ?> + <label for="username">Username</label> + <input type="text" id="username" name="username" required> + + <label for="password">Password</label> + <input type="password" id="password" name="password" required> + + <button type="submit">Log in</button> + </form> + <p><a href="/forgot-password">Forgot your password?</a></p> + <p>Don't have an account? <a href="/register">Register</a></p> +</div> diff --git a/src/app/Views/auth/register.php b/src/app/Views/auth/register.php new file mode 100644 index 0000000..f98102e --- /dev/null +++ b/src/app/Views/auth/register.php @@ -0,0 +1,23 @@ +<?php // Registration form.?> +<div class="auth-page"> + <h1>Register</h1> + <?php include __DIR__ . '/../partials/flash.php'; ?> + <form method="POST" action="/register" class="auth-form"> + <?= \App\Csrf::field() ?> + <label for="username">Username</label> + <input type="text" id="username" name="username" required + pattern="[a-zA-Z0-9_]{3,20}" title="3-20 characters: letters, numbers, underscores"> + + <label for="email">Email</label> + <input type="email" id="email" name="email" required> + + <label for="password">Password</label> + <input type="password" id="password" name="password" required minlength="8"> + + <label for="password_confirm">Confirm password</label> + <input type="password" id="password_confirm" name="password_confirm" required minlength="8"> + + <button type="submit">Register</button> + </form> + <p>Already have an account? <a href="/login">Log in</a></p> +</div> diff --git a/src/app/Views/auth/reset-password.php b/src/app/Views/auth/reset-password.php new file mode 100644 index 0000000..dfdcab2 --- /dev/null +++ b/src/app/Views/auth/reset-password.php @@ -0,0 +1,17 @@ +<?php // Reset password form: set a new password using a valid reset token.?> +<div class="auth-page"> + <h1>Reset password</h1> + <?php include __DIR__ . '/../partials/flash.php'; ?> + <form method="POST" action="/reset-password" class="auth-form"> + <?= \App\Csrf::field() ?> + <input type="hidden" name="token" value="<?= htmlspecialchars($_GET['token'] ?? '') ?>"> + + <label for="password">New password</label> + <input type="password" id="password" name="password" required minlength="8"> + + <label for="password_confirm">Confirm new password</label> + <input type="password" id="password_confirm" name="password_confirm" required minlength="8"> + + <button type="submit">Reset password</button> + </form> +</div> diff --git a/src/app/Views/layouts/main.php b/src/app/Views/layouts/main.php index b4c7dad..fd9ca40 100644 --- a/src/app/Views/layouts/main.php +++ b/src/app/Views/layouts/main.php @@ -28,7 +28,7 @@ <?php include $content; ?> </main> <footer> - <p>Camagru © <?= date('Y') ?></p> + <p>Camagru <?= date('Y') ?></p> </footer> <script src="/js/app.js"></script> </body> diff --git a/src/app/Views/partials/flash.php b/src/app/Views/partials/flash.php new file mode 100644 index 0000000..e9a87e7 --- /dev/null +++ b/src/app/Views/partials/flash.php @@ -0,0 +1,8 @@ +<?php +// Displays a one-time flash message (success or error) if one is set. +$flash = \App\Flash::get(); +if ($flash): ?> +<div class="flash flash-<?= htmlspecialchars($flash['type']) ?>"> + <?= htmlspecialchars($flash['message']) ?> +</div> +<?php endif; ?> |
