diff --git a/l4d2web/cli.py b/l4d2web/cli.py index 8ac84e3..d71fc01 100644 --- a/l4d2web/cli.py +++ b/l4d2web/cli.py @@ -5,7 +5,7 @@ import click from sqlalchemy.exc import IntegrityError from sqlalchemy import select -from l4d2web.auth import hash_password +from l4d2web.auth import hash_password, validate_new_password from l4d2web.db import session_scope from l4d2web.models import Overlay, User from l4d2web.services.overlay_creation import ( @@ -31,8 +31,9 @@ def create_user(username: str, admin: bool) -> None: password = os.getenv("LEFT4ME_ADMIN_PASSWORD") if password is None: password = click.prompt("Password", hide_input=True, confirmation_prompt=True) - if password == "": - raise click.ClickException("password must not be empty") + policy_error = validate_new_password(password) + if policy_error is not None: + raise click.ClickException(policy_error) try: with session_scope() as db: diff --git a/l4d2web/tests/test_auth.py b/l4d2web/tests/test_auth.py index 18d83ef..38f2f07 100644 --- a/l4d2web/tests/test_auth.py +++ b/l4d2web/tests/test_auth.py @@ -202,7 +202,7 @@ def test_login_stamps_password_changed_at_in_session(client) -> None: def test_create_user_cli_uses_environment_password(tmp_path, monkeypatch) -> None: db_url = f"sqlite:///{tmp_path/'create_user.db'}" monkeypatch.setenv("DATABASE_URL", db_url) - monkeypatch.setenv("LEFT4ME_ADMIN_PASSWORD", "secret") + monkeypatch.setenv("LEFT4ME_ADMIN_PASSWORD", "secretpw1") app = create_app({"TESTING": True, "DATABASE_URL": db_url, "SECRET_KEY": "test"}) init_db() @@ -215,6 +215,19 @@ def test_create_user_cli_uses_environment_password(tmp_path, monkeypatch) -> Non assert user.admin is True +def test_create_user_cli_rejects_short_password(tmp_path, monkeypatch) -> None: + db_url = f"sqlite:///{tmp_path/'short_pw.db'}" + monkeypatch.setenv("DATABASE_URL", db_url) + monkeypatch.setenv("LEFT4ME_ADMIN_PASSWORD", "short7x") + app = create_app({"TESTING": True, "DATABASE_URL": db_url, "SECRET_KEY": "test"}) + init_db() + + result = app.test_cli_runner().invoke(args=["create-user", "admin", "--admin"]) + + assert result.exit_code != 0 + assert "at least 8" in result.output + + def test_create_user_cli_rejects_empty_environment_password(tmp_path, monkeypatch) -> None: db_url = f"sqlite:///{tmp_path/'empty_password.db'}" monkeypatch.setenv("DATABASE_URL", db_url) @@ -247,7 +260,7 @@ def test_validate_new_password_accepts_min_length(): def test_create_user_cli_rejects_duplicate_username(tmp_path, monkeypatch) -> None: db_url = f"sqlite:///{tmp_path/'duplicate_user.db'}" monkeypatch.setenv("DATABASE_URL", db_url) - monkeypatch.setenv("LEFT4ME_ADMIN_PASSWORD", "secret") + monkeypatch.setenv("LEFT4ME_ADMIN_PASSWORD", "secretpw1") app = create_app({"TESTING": True, "DATABASE_URL": db_url, "SECRET_KEY": "test"}) init_db() with session_scope() as session: