feat: implement Story 4.2 - New Participant Registration
Implement participant registration with the following features: - POST handler for /exchange/<slug>/register - Create Participant record with lowercased email - Generate magic token and send confirmation email - Redirect to success page after registration - Rate limiting: 10 registrations per hour per IP - Validation for exchange state (must be registration_open) - Form validation for required fields (name, email) - Email format validation - Optional fields support (gift_ideas, reminder_enabled) Also includes: - Registration success page template - 429 error handling template - Flash message support in base template - Test config update for email service dev mode - Comprehensive test suite with 8 tests All tests passing (86 total), 91% coverage maintained. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
12
src/templates/errors/429.html
Normal file
12
src/templates/errors/429.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Too Many Requests - Sneaky Klaus{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<article>
|
||||
<header>
|
||||
<h1>429 - Too Many Requests</h1>
|
||||
</header>
|
||||
<p>Too many registration attempts. Please try again later.</p>
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -12,6 +12,15 @@
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<article role="alert">
|
||||
<p>{{ message }}</p>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
|
||||
33
src/templates/participant/register_success.html
Normal file
33
src/templates/participant/register_success.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Registration Complete - {{ exchange.name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<article>
|
||||
<header>
|
||||
<h1>Registration Complete!</h1>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<p>You've successfully registered for <strong>{{ exchange.name }}</strong>.</p>
|
||||
|
||||
<p>Check your email for a confirmation message with a magic link to access your participant dashboard.</p>
|
||||
|
||||
<h3>What's Next?</h3>
|
||||
<ul>
|
||||
<li>You'll receive an email with a link to access your dashboard</li>
|
||||
<li>After registration closes, you'll be assigned your Secret Santa recipient</li>
|
||||
<li>You'll receive reminders about important dates</li>
|
||||
</ul>
|
||||
|
||||
<h3>Exchange Details</h3>
|
||||
<dl>
|
||||
<dt>Budget</dt>
|
||||
<dd>{{ exchange.budget }}</dd>
|
||||
|
||||
<dt>Gift Exchange Date</dt>
|
||||
<dd>{{ exchange.exchange_date.strftime('%Y-%m-%d') }}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user