triggershell users add/add-token now generate a TRIGGERSHELL_USER_<name>_
PASSWORD_HASH / TRIGGERSHELL_TOKEN_<name>_HASH variable in .env (creating
or updating it idempotently) and print a ${VAR} snippet to paste into
auth.users/auth.tokens, instead of printing the raw hash. Pass --inline to
get the old behavior, since a hash - unlike sessionSecret - is safe to
store directly in the config (same trust model as /etc/shadow); this just
gives people who don't want it there at all an easy option.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
from pathlib import Path
|
|
|
|
from dotenv import dotenv_values
|
|
from typer.testing import CliRunner
|
|
|
|
from triggershell.cli import _slug, app
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
def test_slug_normalizes_to_env_var_style() -> None:
|
|
assert _slug("ci-bot") == "CI_BOT"
|
|
assert _slug("Admin User") == "ADMIN_USER"
|
|
assert _slug("__weird--name__") == "WEIRD_NAME"
|
|
|
|
|
|
def test_users_add_stores_hash_in_dotenv(tmp_path: Path) -> None:
|
|
config_path = tmp_path / "triggershell.yml"
|
|
config_path.write_text("scripts: []\n")
|
|
|
|
result = runner.invoke(app, ["users", "add", "admin", "--config", str(config_path)], input="s3cret\ns3cret\n")
|
|
|
|
assert result.exit_code == 0, result.output
|
|
env_path = tmp_path / ".env"
|
|
assert env_path.exists()
|
|
values = dotenv_values(env_path)
|
|
assert values["TRIGGERSHELL_USER_ADMIN_PASSWORD_HASH"].startswith("$argon2id$")
|
|
assert "${TRIGGERSHELL_USER_ADMIN_PASSWORD_HASH}" in result.output
|
|
assert "$argon2id$" not in result.output.split("Stored")[0] # raw hash not printed pre-storage
|
|
|
|
|
|
def test_users_add_inline_does_not_touch_dotenv(tmp_path: Path) -> None:
|
|
config_path = tmp_path / "triggershell.yml"
|
|
config_path.write_text("scripts: []\n")
|
|
|
|
result = runner.invoke(
|
|
app, ["users", "add", "admin", "--config", str(config_path), "--inline"], input="s3cret\ns3cret\n"
|
|
)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert not (tmp_path / ".env").exists()
|
|
assert "$argon2id$" in result.output
|
|
|
|
|
|
def test_users_add_token_overwrites_existing_var(tmp_path: Path) -> None:
|
|
config_path = tmp_path / "triggershell.yml"
|
|
config_path.write_text("scripts: []\n")
|
|
|
|
first = runner.invoke(app, ["users", "add-token", "ci-bot", "--config", str(config_path)])
|
|
assert first.exit_code == 0, first.output
|
|
first_hash = dotenv_values(tmp_path / ".env")["TRIGGERSHELL_TOKEN_CI_BOT_HASH"]
|
|
|
|
second = runner.invoke(app, ["users", "add-token", "ci-bot", "--config", str(config_path)])
|
|
assert second.exit_code == 0, second.output
|
|
values = dotenv_values(tmp_path / ".env")
|
|
second_hash = values["TRIGGERSHELL_TOKEN_CI_BOT_HASH"]
|
|
|
|
assert first_hash != second_hash
|
|
env_content = (tmp_path / ".env").read_text()
|
|
assert env_content.count("TRIGGERSHELL_TOKEN_CI_BOT_HASH") == 1
|