47 lines
1.6 KiB
Python
47 lines
1.6 KiB
Python
|
|
"""Account bootstrap/lookup.
|
||
|
|
|
||
|
|
Full multi-tenant account issuance (``POST /v1/accounts``, registration-token
|
||
|
|
rotation, per-account management) is Phase 4 — see the plan's phased
|
||
|
|
delivery. Phase 2 only needs the single implicit account a
|
||
|
|
``GATEWAY_MODE=single`` deployment bootstraps itself with at startup: its
|
||
|
|
``registration_token_hash``/``account_token_hash`` are left blank because
|
||
|
|
single-tenant auth for box registration goes through the operator-set
|
||
|
|
``GATEWAY_BOX_TOKEN`` env var instead (see api.py), not through this row.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import sqlite3
|
||
|
|
from datetime import UTC, datetime
|
||
|
|
|
||
|
|
from control_plane.db import Database
|
||
|
|
|
||
|
|
SINGLE_TENANT_ACCOUNT_ID = "default"
|
||
|
|
|
||
|
|
|
||
|
|
def ensure_single_tenant_account(
|
||
|
|
db: Database, box_limit: int, route_limit_per_box: int
|
||
|
|
) -> str:
|
||
|
|
"""Idempotently create the one account a single-tenant gateway uses.
|
||
|
|
|
||
|
|
Returns the account id every registered box on this gateway belongs to.
|
||
|
|
"""
|
||
|
|
row = db.query_one("SELECT id FROM accounts WHERE id = ?", (SINGLE_TENANT_ACCOUNT_ID,))
|
||
|
|
if row is not None:
|
||
|
|
return SINGLE_TENANT_ACCOUNT_ID
|
||
|
|
now = datetime.now(UTC).isoformat()
|
||
|
|
db.execute(
|
||
|
|
"""
|
||
|
|
INSERT INTO accounts
|
||
|
|
(id, email, created_at, registration_token_hash, account_token_hash,
|
||
|
|
box_limit, route_limit_per_box)
|
||
|
|
VALUES (?, NULL, ?, '', '', ?, ?)
|
||
|
|
""",
|
||
|
|
(SINGLE_TENANT_ACCOUNT_ID, now, box_limit, route_limit_per_box),
|
||
|
|
)
|
||
|
|
return SINGLE_TENANT_ACCOUNT_ID
|
||
|
|
|
||
|
|
|
||
|
|
def get_account(db: Database, account_id: str) -> sqlite3.Row | None:
|
||
|
|
return db.query_one("SELECT * FROM accounts WHERE id = ?", (account_id,))
|