64 lines · 2.1 KB
| 1 | --- |
| 2 | import Base from '../layouts/Base.astro'; |
| 3 | import { apiPost } from '../lib/api'; |
| 4 | |
| 5 | let error = ''; |
| 6 | |
| 7 | if (Astro.request.method === 'POST') { |
| 8 | try { |
| 9 | const formData = await Astro.request.formData(); |
| 10 | const username = formData.get('username') as string; |
| 11 | const email = formData.get('email') as string; |
| 12 | const password = formData.get('password') as string; |
| 13 | |
| 14 | await apiPost('/api/register', { username, email, password }); |
| 15 | |
| 16 | // Auto-login after registration |
| 17 | const { data, headers } = await apiPost('/api/login', { username, password }); |
| 18 | const setCookie = headers.get('set-cookie'); |
| 19 | if (setCookie) { |
| 20 | Astro.cookies.set('session', setCookie.match(/session=([^;]+)/)?.[1] || '', { |
| 21 | path: '/', |
| 22 | httpOnly: true, |
| 23 | secure: true, |
| 24 | sameSite: 'strict', |
| 25 | maxAge: 7 * 24 * 60 * 60, |
| 26 | }); |
| 27 | } |
| 28 | |
| 29 | return Astro.redirect('/'); |
| 30 | } catch (e: any) { |
| 31 | error = e.message; |
| 32 | } |
| 33 | } |
| 34 | --- |
| 35 | |
| 36 | <Base title="Sign up"> |
| 37 | <div class="container" style="max-width: 400px; padding-top: 48px;"> |
| 38 | <div class="card"> |
| 39 | <h1 style="font-size: 1.25rem; margin-bottom: 20px; text-align: center;">Create your account</h1> |
| 40 | |
| 41 | {error && <div class="flash-error">{error}</div>} |
| 42 | |
| 43 | <form method="POST"> |
| 44 | <div class="form-group"> |
| 45 | <label for="username">Username</label> |
| 46 | <input type="text" id="username" name="username" required pattern="[a-zA-Z0-9_-]{2,32}" /> |
| 47 | </div> |
| 48 | <div class="form-group"> |
| 49 | <label for="email">Email</label> |
| 50 | <input type="email" id="email" name="email" required /> |
| 51 | </div> |
| 52 | <div class="form-group"> |
| 53 | <label for="password">Password</label> |
| 54 | <input type="password" id="password" name="password" required minlength="8" autocomplete="new-password" /> |
| 55 | </div> |
| 56 | <button type="submit" class="btn btn-primary" style="width: 100%;">Create account</button> |
| 57 | </form> |
| 58 | </div> |
| 59 | <p style="text-align: center; margin-top: 16px; font-size: 0.875rem; color: var(--text-muted);"> |
| 60 | Already have an account? <a href="/login">Sign in</a> |
| 61 | </p> |
| 62 | </div> |
| 63 | </Base> |
| 64 |