diff --git a/app/controllers/register.py b/app/controllers/register.py
index 7e99617..413e56b 100644
--- a/app/controllers/register.py
+++ b/app/controllers/register.py
@@ -52,13 +52,19 @@ def register_post():
name = request.form.get('name', '')
email = request.form.get('email', '').lower()
password = request.form.get('password', '')
+ password_verify = request.form.get('password_verify', '')
# Validate required fields
- if not name or not email or not password:
- missing = 'name' if not name else ('email' if not email else 'password')
+ if not name or not email or not password or not password_verify:
+ missing = ('name' if not name else 'email' if not email else
+ 'password' if not password else 'password_verify')
flash(f'Field missing: {missing}', FLASH_ERROR)
return render_template('register/register.html', name=name, email=email)
+ if password != password_verify:
+ flash('Passwords do not match', FLASH_ERROR)
+ return render_template('register/register.html', name=name, email=email)
+
# Validate reCAPTCHA
if not verify_recaptcha(request):
flash('reCAPTCHA invalid!', FLASH_ERROR)
diff --git a/templates/register/register.html b/templates/register/register.html
index c65140e..88e4dd1 100644
--- a/templates/register/register.html
+++ b/templates/register/register.html
@@ -14,7 +14,7 @@
Username
-
+
@@ -22,7 +22,7 @@
Email
-
+
@@ -30,7 +30,7 @@
Password
-
+
@@ -38,7 +38,7 @@
Verify Password
-
+
{% if RECAPTCHA_SITEKEY %}
diff --git a/tests/test_controller_edge_cases.py b/tests/test_controller_edge_cases.py
index 5702954..3154c95 100644
--- a/tests/test_controller_edge_cases.py
+++ b/tests/test_controller_edge_cases.py
@@ -41,9 +41,11 @@ def test_login_database_failure_is_generic(client):
def test_registration_rejects_duplicate_email_and_username(client, alice):
duplicate_email = client.post('/register', data={
'name': 'different', 'email': 'alice@example.test', 'password': 'password123',
+ 'password_verify': 'password123',
})
duplicate_name = client.post('/register', data={
'name': 'alice', 'email': 'different@example.test', 'password': 'password123',
+ 'password_verify': 'password123',
})
assert b'Account already exists' in duplicate_email.data
assert b'Account already exists' in duplicate_name.data
@@ -56,11 +58,11 @@ def test_registration_cross_field_conflicts(client, db):
})
username_is_email = client.post('/register', data={
'name': 'existing-email@example.test', 'email': 'new@example.test',
- 'password': 'password123',
+ 'password': 'password123', 'password_verify': 'password123',
})
email_is_username = client.post('/register', data={
'name': 'new-user', 'email': 'existing@example.test',
- 'password': 'password123',
+ 'password': 'password123', 'password_verify': 'password123',
})
assert b'username is not available' in username_is_email.data
assert b'email is not available' in email_is_username.data
@@ -69,17 +71,22 @@ def test_registration_cross_field_conflicts(client, db):
def test_registration_rejects_invalid_chars_and_recaptcha(client):
invalid = client.post('/register', data={
'name': 'bad name', 'email': 'valid@example.test', 'password': 'password123',
+ 'password_verify': 'password123',
})
with patch('app.controllers.register.verify_recaptcha', return_value=False):
captcha = client.post('/register', data={
'name': 'valid', 'email': 'valid@example.test', 'password': 'password123',
+ 'password_verify': 'password123',
})
assert b'Non allowed chars' in invalid.data
assert b'reCAPTCHA invalid' in captcha.data
def test_registration_hash_and_create_failures(client):
- data = {'name': 'newuser', 'email': 'new@example.test', 'password': 'password123'}
+ data = {
+ 'name': 'newuser', 'email': 'new@example.test',
+ 'password': 'password123', 'password_verify': 'password123',
+ }
with patch('app.controllers.register.hash_string', side_effect=RuntimeError):
hashing = client.post('/register', data=data)
with patch('app.controllers.register.user_create', side_effect=RuntimeError):
diff --git a/tests/test_routes.py b/tests/test_routes.py
index 852eabc..e39b553 100644
--- a/tests/test_routes.py
+++ b/tests/test_routes.py
@@ -66,6 +66,7 @@ def test_registration_creates_a_user(client, db):
'name': 'charlie',
'email': 'CHARLIE@example.test',
'password': 'charlie-password',
+ 'password_verify': 'charlie-password',
})
assert response.status_code == 302
@@ -75,6 +76,27 @@ def test_registration_creates_a_user(client, db):
assert match_string(user['password'], 'charlie-password') is True
+def test_registration_requires_matching_password_confirmation(client, db):
+ registration = {
+ 'name': 'charlie',
+ 'email': 'charlie@example.test',
+ 'password': 'charlie-password',
+ }
+
+ missing = client.post('/register', data=registration)
+ assert missing.status_code == 200
+ assert b'Field missing: password_verify' in missing.data
+ assert db.user.find_one({'name': 'charlie'}) is None
+
+ mismatch = client.post('/register', data={
+ **registration,
+ 'password_verify': 'different-password',
+ })
+ assert mismatch.status_code == 200
+ assert b'Passwords do not match' in mismatch.data
+ assert db.user.find_one({'name': 'charlie'}) is None
+
+
def test_logout_clears_only_main_auth(alice_client):
with alice_client.session_transaction() as session:
session['unrelated'] = 'preserved'