Skip to content

Commit

Permalink
Clean up leftover signup birthdate logic and database column (#1422)
Browse files Browse the repository at this point in the history
The removal has been deployed for a while now, so nobody should be inconvenienced by breaking postback of the old version of the form.

Migration runs after deployment.
  • Loading branch information
charmander authored Aug 22, 2024
1 parent ab0c731 commit 978aeec
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Remove signup birthdate column
Revision ID: 63baa2713e72
Revises: 57171ee9e989
Create Date: 2024-08-21 23:50:18.122609
"""

# revision identifiers, used by Alembic.
revision = '63baa2713e72'
down_revision = '57171ee9e989'

from alembic import op
import sqlalchemy as sa


def upgrade():
op.drop_column('logincreate', 'birthday')


def downgrade():
op.add_column('logincreate', sa.Column('birthday', sa.INTEGER(), autoincrement=False, nullable=True))
1 change: 0 additions & 1 deletion libweasyl/models/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ def default_fkey(*args, **kwargs):
Column('login_name', String(length=40), nullable=False, unique=True),
Column('hashpass', String(length=100), nullable=False),
Column('email', String(length=100), nullable=False, unique=True),
Column('birthday', WeasylTimestampColumn(), nullable=True),
Column('created_at', TIMESTAMP(timezone=True), nullable=False, server_default=func.now()),
# Used to determine if a record is invalid for purposes of plausible deniability of email addresses
# AKA, create a logincreate entry if an in-use email address is provided, thus preserving the effect of
Expand Down
3 changes: 1 addition & 2 deletions weasyl/controllers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ def signup_get_(request):
@token_checked
def signup_post_(request):
form = request.web_input(
username="", password="", email="",
day="", month="", year="")
username="", password="", email="")

login.create(form)
return Response(define.errorpage(
Expand Down
22 changes: 1 addition & 21 deletions weasyl/login.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
from io import open

import arrow
import bcrypt
from publicsuffixlist import PublicSuffixList
from sqlalchemy.sql.expression import select
Expand Down Expand Up @@ -204,27 +203,11 @@ def create(form):
# Normalize form data
username = clean_display_name(form.username)
sysname = d.get_sysname(username)

email = emailer.normalize_address(form.email)

# TODO: remove birth date check after checkbox-only form has been deployed for a while
password = form.password
if form.day and form.month and form.year:
try:
birthday = arrow.Arrow(int(form.year), int(form.month), int(form.day))
except ValueError:
raise WeasylError("birthdayInvalid")

if d.age_in_years(birthday) < 13:
raise WeasylError("birthdayInvalid")
else:
birthday = None

if "age" in form and form.age != "13+":
raise WeasylError("birthdayInvalid")

# Check invalid form data
if birthday is None and "age" not in form:
if "age" not in form or form.age != "13+":
raise WeasylError("birthdayInvalid")
if not password_secure(password):
raise WeasylError("passwordInsecure")
Expand All @@ -251,7 +234,6 @@ def create(form):
"login_name": sysname,
"hashpass": passhash(password),
"email": email,
"birthday": birthday,
})

# Send verification email
Expand All @@ -268,7 +250,6 @@ def create(form):
"login_name": sysname,
"hashpass": passhash(password),
"email": token,
"birthday": None,
"invalid": True,
# So we have a way for admins to determine which email address collided in the View Pending Accounts Page
"invalid_email_addr": email,
Expand Down Expand Up @@ -320,7 +301,6 @@ def verify(token, ip_address=None):
})
db.execute(d.meta.tables["userinfo"].insert(), {
"userid": userid,
"birthday": query.birthday,
})

# Update logincreate records
Expand Down
124 changes: 19 additions & 105 deletions weasyl/test/login/test_create.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest
import arrow
from web.utils import Storage as Bag

from weasyl import define as d
Expand All @@ -16,92 +15,9 @@


@pytest.mark.usefixtures('db')
def test_DMY_not_integer_raises_birthdayInvalid_WeasylError():
# Check for failure state if 'day' is not an integer, e.g., string
def test_age_minimum():
form = Bag(username=user_name, password='',
email='[email protected]',
day='test', month='31', year='1942')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value

# Check for failure state if 'month' is not an integer, e.g., string
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month='test', year='1942')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value

# Check for failure state if 'year' is not an integer, e.g., string
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month='31', year='test')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value


@pytest.mark.usefixtures('db')
def test_DMY_out_of_valid_ranges_raises_birthdayInvalid_WeasylError():
# Check for failure state if 'day' is not an valid day e.g., 42
form = Bag(username=user_name, password='',
email='[email protected]',
day='42', month='12', year='2000')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value

# Check for failure state if 'month' is not an valid month e.g., 42
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month='42', year='2000')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value

# Check for failure state if 'year' is not an valid year e.g., -1
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month='12', year='-1')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value


@pytest.mark.usefixtures('db')
def test_DMY_missing_raises_birthdayInvalid_WeasylError():
# Check for failure state if 'year' is not an valid year e.g., -1
form = Bag(username=user_name, password='',
email='[email protected]',
day=None, month='12', year='2000')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value

# Check for failure state if 'year' is not an valid year e.g., -1
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month=None, year='2000')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value

# Check for failure state if 'year' is not an valid year e.g., -1
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month='12', year=None)
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value


@pytest.mark.usefixtures('db')
def test_under_13_age_raises_birthdayInvalid_WeasylError():
# Check for failure state if computed birthday is <13 years old
form = Bag(username=user_name, password='',
email='[email protected]',
day='12', month='12', year=arrow.utcnow().year - 11)
email='[email protected]')
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'birthdayInvalid' == err.value.value
Expand All @@ -112,7 +28,7 @@ def test_passwords_must_be_of_sufficient_length():
password = "tooShort"
form = Bag(username=user_name, password=password,
email='foo',
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
# Insecure length
with pytest.raises(WeasylError) as err:
login.create(form)
Expand All @@ -130,7 +46,7 @@ def test_passwords_must_be_of_sufficient_length():
def test_create_fails_if_email_is_invalid():
form = Bag(username=user_name, password='0123456789',
email=';--',
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'emailInvalid' == err.value.value
Expand All @@ -146,7 +62,7 @@ def test_create_fails_if_another_account_has_email_linked_to_their_account():
db_utils.create_user(username=user_name, email_addr=email_addr)
form = Bag(username="user", password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
login.create(form)
query = d.engine.scalar("""
SELECT username FROM logincreate WHERE username = %(username)s AND invalid IS TRUE
Expand All @@ -167,11 +83,10 @@ def test_create_fails_if_pending_account_has_same_email():
"login_name": "existing",
"hashpass": login.passhash(raw_password),
"email": email_addr,
"birthday": arrow.Arrow(2000, 1, 1),
})
form = Bag(username="test", password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
login.create(form)
query = d.engine.scalar("""
SELECT username FROM logincreate WHERE username = %(username)s AND invalid IS TRUE
Expand All @@ -183,7 +98,7 @@ def test_create_fails_if_pending_account_has_same_email():
def test_username_cant_be_blank_or_have_semicolon():
form = Bag(username='...', password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'usernameInvalid' == err.value.value
Expand All @@ -199,7 +114,7 @@ def test_username_cant_be_blank_or_have_semicolon():
def test_create_fails_if_username_is_a_prohibited_name():
form = Bag(username='testloginsuite', password='0123456789',
email='[email protected]',
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
prohibited_names = ["admin", "administrator", "mod", "moderator", "weasyl",
"weasyladmin", "weasylmod", "staff", "security"]
for name in prohibited_names:
Expand All @@ -214,7 +129,7 @@ def test_usernames_must_be_unique():
db_utils.create_user(username=user_name, email_addr="[email protected]")
form = Bag(username=user_name, password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'usernameExists' == err.value.value
Expand All @@ -228,11 +143,10 @@ def test_usernames_cannot_match_pending_account_usernames():
"login_name": user_name,
"hashpass": login.passhash(raw_password),
"email": "[email protected]",
"birthday": arrow.Arrow(2000, 1, 1),
})
form = Bag(username=user_name, password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'usernameExists' == err.value.value
Expand All @@ -244,7 +158,7 @@ def test_username_cannot_match_an_active_alias():
d.engine.execute("INSERT INTO useralias VALUES (%(userid)s, %(username)s, 'p')", userid=user_id, username=user_name)
form = Bag(username=user_name, password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'usernameExists' == err.value.value
Expand All @@ -254,7 +168,7 @@ def test_username_cannot_match_an_active_alias():
def test_verify_correct_information_creates_account():
form = Bag(username=user_name, password='0123456789',
email=email_addr,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
login.create(form)
# This record should exist when this function completes successfully
assert d.engine.scalar(
Expand All @@ -278,7 +192,7 @@ def test_create_fails_if_email_domain_is_blacklisted(self):
blacklisted_email = "[email protected]"
form = Bag(username=user_name, password='0123456789',
email=blacklisted_email,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'emailBlacklisted' == err.value.value
Expand All @@ -299,7 +213,7 @@ def test_verify_subdomains_of_blocked_sites_blocked(self):
blacklisted_email = "[email protected]"
form = Bag(username=user_name, password='0123456789',
email=blacklisted_email,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'emailBlacklisted' == err.value.value
Expand All @@ -308,7 +222,7 @@ def test_verify_subdomains_of_blocked_sites_blocked(self):
blacklisted_email = "[email protected]"
form = Bag(username=user_name, password='0123456789',
email=blacklisted_email,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'emailBlacklisted' == err.value.value
Expand All @@ -317,7 +231,7 @@ def test_verify_subdomains_of_blocked_sites_blocked(self):
blacklisted_email = "[email protected]"
form = Bag(username=user_name, password='0123456789',
email=blacklisted_email,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
with pytest.raises(WeasylError) as err:
login.create(form)
assert 'emailBlacklisted' == err.value.value
Expand All @@ -337,17 +251,17 @@ def test_similarly_named_domains_are_not_blocked(self):
mail = "[email protected]"
form = Bag(username=user_name, password='0123456789',
email=mail,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
login.create(form)

mail = "[email protected]"
form = Bag(username=user_name + "1", password='0123456789',
email=mail,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
login.create(form)

mail = "[email protected]"
form = Bag(username=user_name + "2", password='0123456789',
email=mail,
day='12', month='12', year=arrow.utcnow().year - 19)
age="13+")
login.create(form)
3 changes: 0 additions & 3 deletions weasyl/test/login/test_get_account_verification_token.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest
import arrow

from weasyl import login
from weasyl import define as d
Expand All @@ -21,7 +20,6 @@ def test_acct_verif_token_returned_if_email_provided_to_function():
"login_name": user_name,
"hashpass": login.passhash(raw_password),
"email": email_addr,
"birthday": arrow.Arrow(2000, 1, 1),
})
acct_verification_token = login.get_account_verification_token(email=email_addr, username=None)
assert token == acct_verification_token
Expand All @@ -35,7 +33,6 @@ def test_acct_verif_token_returned_if_username_provided_to_function():
"login_name": user_name,
"hashpass": login.passhash(raw_password),
"email": email_addr,
"birthday": arrow.Arrow(2000, 1, 1),
})
acct_verification_token = login.get_account_verification_token(email=None, username=user_name)
assert token == acct_verification_token
2 changes: 0 additions & 2 deletions weasyl/test/login/test_verify.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest
import arrow

from weasyl import login
from weasyl import define as d
Expand All @@ -18,7 +17,6 @@ def _create_pending_account(invalid=False):
"login_name": username,
"hashpass": login.passhash('0123456789'),
"email": email,
"birthday": arrow.Arrow(2000, 1, 1),
"invalid": invalid,
})

Expand Down

0 comments on commit 978aeec

Please sign in to comment.