API & Client - update username max length

This commit is contained in:
Sam 2022-03-13 08:38:45 +01:00
parent d968a76fcc
commit 8988a0266a
7 changed files with 89 additions and 36 deletions

View File

@ -0,0 +1,30 @@
"""update username length
Revision ID: 5e3a3a31c432
Revises: e30007d681cb
Create Date: 2022-02-23 11:05:24.223304
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '5e3a3a31c432'
down_revision = 'e30007d681cb'
branch_labels = None
depends_on = None
def upgrade():
op.alter_column(
'users', 'username', existing_type=sa.String(length=20),
type_=sa.String(length=255), existing_nullable=False
)
def downgrade():
op.alter_column(
'users', 'username', existing_type=sa.String(length=255),
type_=sa.String(length=20), existing_nullable=False
)

View File

@ -93,7 +93,7 @@ class TestUserRegistration(ApiTestCaseMixin):
'/api/auth/register', '/api/auth/register',
data=json.dumps( data=json.dumps(
dict( dict(
username='t', username='',
email='test@test.com', email='test@test.com',
password='12345678', password='12345678',
password_conf='12345678', password_conf='12345678',
@ -102,17 +102,25 @@ class TestUserRegistration(ApiTestCaseMixin):
content_type='application/json', content_type='application/json',
) )
self.assert_400(response, "username: 3 to 12 characters required\n") self.assert_400(
response,
(
'username: 3 to 30 characters required\n'
'username: only alphanumeric characters and '
'the underscore character "_" allowed\n'
),
)
def test_it_returns_error_if_username_is_too_long( def test_it_returns_error_if_username_is_too_long(
self, app: Flask self, app: Flask
) -> None: ) -> None:
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps( data=json.dumps(
dict( dict(
username='testestestestestest', username='a' * 31,
email='test@test.com', email='test@test.com',
password='12345678', password='12345678',
password_conf='12345678', password_conf='12345678',
@ -121,7 +129,38 @@ class TestUserRegistration(ApiTestCaseMixin):
content_type='application/json', content_type='application/json',
) )
self.assert_400(response, "username: 3 to 12 characters required\n") self.assert_400(response, "username: 3 to 30 characters required\n")
@pytest.mark.parametrize(
'input_description,input_username',
[
('account_handle', '@sam@example.com'),
('with special characters', 'sam*'),
],
)
def test_it_returns_error_if_username_is_invalid(
self, app: Flask, input_description: str, input_username: str
) -> None:
client = app.test_client()
response = client.post(
'/api/auth/register',
data=json.dumps(
dict(
username=input_username,
email='test@test.com',
password='12345678',
password_conf='12345678',
)
),
content_type='application/json',
)
self.assert_400(
response,
'username: only alphanumeric characters and '
'the underscore character "_" allowed\n',
)
def test_it_returns_error_if_email_is_invalid(self, app: Flask) -> None: def test_it_returns_error_if_email_is_invalid(self, app: Flask) -> None:
client = app.test_client() client = app.test_client()
@ -261,24 +300,6 @@ class TestUserRegistration(ApiTestCaseMixin):
self.assert_400(response) self.assert_400(response)
def test_it_returns_error_if_username_is_invalid(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
'/api/auth/register',
data=json.dumps(
dict(
username=1,
email='test@test.com',
password='12345678',
password_conf='12345678',
)
),
content_type='application/json',
)
self.assert_500(response)
class TestUserLogin(ApiTestCaseMixin): class TestUserLogin(ApiTestCaseMixin):
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -120,7 +120,7 @@ class TestIsUsernameValid:
('input_username_length',), ('input_username_length',),
[ [
(2,), (2,),
(13,), (31,),
], ],
) )
def test_it_returns_error_message_when_username_length_is_invalid( def test_it_returns_error_message_when_username_length_is_invalid(
@ -128,9 +128,9 @@ class TestIsUsernameValid:
) -> None: ) -> None:
assert ( assert (
check_username( check_username(
username=random_string(input_username_length), username=random_string(31),
) )
== 'username: 3 to 12 characters required\n' == 'username: 3 to 30 characters required\n'
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -154,9 +154,9 @@ class TestIsUsernameValid:
assert check_username(username=random_string()) == '' assert check_username(username=random_string()) == ''
def test_it_returns_multiple_errors(self) -> None: def test_it_returns_multiple_errors(self) -> None:
username = random_string(1) + '.' username = random_string(31) + '.'
assert check_username(username=username) == ( assert check_username(username=username) == (
'username: 3 to 12 characters required\n' 'username: 3 to 30 characters required\n'
'username: only alphanumeric characters and the underscore ' 'username: only alphanumeric characters and the underscore '
'character "_" allowed\n' 'character "_" allowed\n'
) )
@ -201,14 +201,14 @@ class TestRegisterControls:
) )
def test_it_returns_multiple_errors_when_inputs_are_invalid(self) -> None: def test_it_returns_multiple_errors_when_inputs_are_invalid(self) -> None:
invalid_username = random_string(2) invalid_username = random_string(31)
assert register_controls( assert register_controls(
username=invalid_username, username=invalid_username,
email=invalid_username, email=invalid_username,
password=random_string(8), password=random_string(8),
password_conf=random_string(8), password_conf=random_string(8),
) == ( ) == (
'username: 3 to 12 characters required\n' 'username: 3 to 30 characters required\n'
'email: valid email must be provided\n' 'email: valid email must be provided\n'
'password: password and password confirmation do not match\n' 'password: password and password confirmation do not match\n'
) )

View File

@ -74,7 +74,7 @@ def register_user() -> Union[Tuple[Dict, int], HttpResponse]:
"status": "error" "status": "error"
} }
:<json string username: user name (3 to 12 characters required) :<json string username: user name (3 to 30 characters required)
:<json string email: user email :<json string email: user email
:<json string password: password (8 characters required) :<json string password: password (8 characters required)
:<json string password_conf: password confirmation :<json string password_conf: password confirmation
@ -84,7 +84,9 @@ def register_user() -> Union[Tuple[Dict, int], HttpResponse]:
- invalid payload - invalid payload
- sorry, that user already exists - sorry, that user already exists
- Errors: - Errors:
- username: 3 to 12 characters required - username: 3 to 30 characters required
- username: only alphanumeric characters and the underscore
character "_" allowed
- email: valid email must be provided - email: valid email must be provided
- password: password and password confirmation don't match - password: password and password confirmation don't match
- password: 8 characters required - password: 8 characters required

View File

@ -19,7 +19,7 @@ BaseModel: DeclarativeMeta = db.Model
class User(BaseModel): class User(BaseModel):
__tablename__ = 'users' __tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True) id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20), unique=True, nullable=False) username = db.Column(db.String(255), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(255), nullable=False) password = db.Column(db.String(255), nullable=False)
created_at = db.Column(db.DateTime, nullable=False) created_at = db.Column(db.DateTime, nullable=False)
@ -32,7 +32,7 @@ class User(BaseModel):
picture = db.Column(db.String(255), nullable=True) picture = db.Column(db.String(255), nullable=True)
timezone = db.Column(db.String(50), nullable=True) timezone = db.Column(db.String(50), nullable=True)
# does the week start Monday? # does the week start Monday?
weekm = db.Column(db.Boolean(50), default=False, nullable=False) weekm = db.Column(db.Boolean, default=False, nullable=False)
workouts = db.relationship( workouts = db.relationship(
'Workout', 'Workout',
lazy=True, lazy=True,

View File

@ -40,8 +40,8 @@ def check_username(username: str) -> str:
Return if username is valid Return if username is valid
""" """
ret = '' ret = ''
if not 2 < len(username) < 13: if not (2 < len(username) < 31):
ret += 'username: 3 to 12 characters required\n' ret += 'username: 3 to 30 characters required\n'
if not re.match(r'^[a-zA-Z0-9_]+$', username): if not re.match(r'^[a-zA-Z0-9_]+$', username):
ret += ( ret += (
'username: only alphanumeric characters and the ' 'username: only alphanumeric characters and the '

View File

@ -23,7 +23,7 @@
required required
pattern="[a-zA-Z0-9_]+" pattern="[a-zA-Z0-9_]+"
minlength="3" minlength="3"
maxlength="12" maxlength="30"
@invalid="invalidateForm" @invalid="invalidateForm"
v-model="formData.username" v-model="formData.username"
:placeholder="$t('user.USERNAME')" :placeholder="$t('user.USERNAME')"