SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%
5.5 KB · 113 lines python
Raw Blame History
1"""`hfmd` CLI: idempotent seed from a JSON file / env var, users add/list/set-tier/disable, keys list/rotate,2--show-key discipline. No real address is hard-coded anywhere (A21)."""3from __future__ import annotations45import json67from sqlalchemy import func, select89SEED = [10    {"name": "Seed One", "email": "seed-one@example.com", "tier": "free", "role": "user"},11    {"name": "Seed Two", "email": "seed-two@example.com", "tier": "free", "role": "user"},12    {"name": "Seed Three", "email": "seed-three@example.com", "tier": "free", "role": "user"},13    {"name": "Seed Admin", "email": "seed-admin@example.com", "tier": "high_usage", "role": "admin"},14]151617def run(cli, capsys, *argv) -> tuple[int, str]:18    rc = cli.main(list(argv))19    out = capsys.readouterr()20    return rc, out.out + out.err212223def test_no_hardcoded_addresses(app):24    import inspect2526    from accounts import cli27    src = inspect.getsource(cli)28    assert "gmail.com" not in src and "@spboucher.ai" not in src.split('"""', 2)[2]   # author line in the docstring only293031def test_seed_from_file_is_idempotent(app, capsys, tmp_path):32    from accounts import cli33    from accounts.models import ApiKey, EmailToken, User34    from core.db import session3536    seed_file = tmp_path / "seed.json"37    seed_file.write_text(json.dumps(SEED))38    rc, out = run(cli, capsys, "seed", str(seed_file))39    assert rc == 0, out40    for u in SEED:41        assert u["email"] in out42    assert "accept-invite?token=" in out and "hfmd_live_" in out43    assert out.count("hfmd_live_") == 4                     # prefixes only, one per user44    assert "api_key" not in out                            # full keys hidden without --show-key4546    def counts():47        with session() as s:48            users = {u.email: u for u in s.execute(select(User)).scalars()}49            keys = s.execute(select(func.count()).select_from(ApiKey).where(ApiKey.status == "active",50                                                                            ApiKey.user_id.in_([u.id for u in users.values()]))).scalar_one()51            toks = s.execute(select(func.count()).select_from(EmailToken).where(EmailToken.used_at.is_(None),52                                                                                EmailToken.user_id.in_([u.id for u in users.values()]))).scalar_one()53            return users, keys, toks5455    users, keys, toks = counts()56    seeded = {u["email"]: users[u["email"]] for u in SEED}57    assert seeded["seed-admin@example.com"].role == "admin" and seeded["seed-one@example.com"].role == "user"58    assert all(u.status == "invited" for u in seeded.values())5960    rc, out2 = run(cli, capsys, "seed", str(seed_file))61    assert rc == 062    users2, keys2, toks2 = counts()63    assert len(users2) == len(users) and keys2 == keys and toks2 == toks     # nothing duplicated64    # the same pending invitation links are printed again65    links1 = sorted(line.split()[-1] for line in out.splitlines() if "accept-invite?token=" in line)66    links2 = sorted(line.split()[-1] for line in out2.splitlines() if "accept-invite?token=" in line)67    assert links1 == links2 and len(links1) == 4686970def test_seed_from_env_and_errors(app, capsys, monkeypatch, tmp_path):71    from accounts import cli72    monkeypatch.delenv(cli.SEED_ENV, raising=False)73    rc, out = run(cli, capsys, "seed")74    assert rc == 1 and "no seed" in out75    monkeypatch.setenv(cli.SEED_ENV, json.dumps([{"name": "Env Person", "email": "env-person@example.com"}]))76    rc, out = run(cli, capsys, "seed", "--no-mail")77    assert rc == 0 and "env-person@example.com" in out78    bad = tmp_path / "bad.json"79    bad.write_text("{not json")80    rc, out = run(cli, capsys, "seed", str(bad))81    assert rc == 1 and "not valid JSON" in out828384def test_users_add_show_key_and_management(app, capsys):85    from accounts import cli86    email = "cli-person@example.com"87    rc, out = run(cli, capsys, "users", "add", "CLI Person", email, "--tier", "high_usage", "--show-key", "--no-mail")88    assert rc == 0 and email in out and "high_usage" in out89    full = [tok for tok in out.split() if tok.startswith("hfmd_live_") and len(tok) == 42]90    assert len(full) == 1                                   # the full key, exactly once91    # second add: no new key, no key printed, tier untouched92    rc, out = run(cli, capsys, "users", "add", "CLI Person", email, "--tier", "free", "--show-key", "--no-mail")93    assert rc == 0 and "high_usage" in out94    assert not [tok for tok in out.split() if tok.startswith("hfmd_live_") and len(tok) == 42]95    rc, out = run(cli, capsys, "keys", "list", email)96    assert rc == 0 and out.count("active") == 197    rc, out = run(cli, capsys, "keys", "rotate", email, "--show-key")98    assert rc == 0 and len([tok for tok in out.split() if tok.startswith("hfmd_live_") and len(tok) == 42]) == 199    rc, out = run(cli, capsys, "keys", "list", email)100    assert rc == 0 and out.count("active") == 1 and out.count("revoked") == 1101    rc, out = run(cli, capsys, "users", "set-tier", email, "free")102    assert rc == 0 and "tier = free" in out103    rc, out = run(cli, capsys, "users", "disable", email)104    assert rc == 0 and "status = disabled" in out105    rc, out = run(cli, capsys, "users", "enable", email)106    assert rc == 0 and "status = active" in out107    rc, out = run(cli, capsys, "users", "invite-resend", email, "--no-mail")108    assert rc == 0 and "accept-invite?token=" in out109    rc, out = run(cli, capsys, "users", "list")110    assert rc == 0 and email in out111    rc, out = run(cli, capsys, "keys", "list", "nobody@example.com")112    assert rc == 1 and "USER_NOT_FOUND" in out113