Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/opencmo/storage/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ async def get_user_account(user_id: int) -> dict | None:

async def create_user_with_account(email: str, password: str, name: str = "") -> tuple[dict, dict]:
normalized = (email or "").strip().lower()
admin_email = os.environ.get("OPENCMO_ADMIN_EMAIL", "hello@aidcmo.com").strip().lower()
if not is_valid_email(normalized):
raise ValueError("invalid_email")
if len(password or "") < MIN_PASSWORD_LENGTH:
Expand All @@ -189,6 +190,8 @@ async def create_user_with_account(email: str, password: str, name: str = "") ->
try:
existing = await db.execute("SELECT id, password_hash FROM users WHERE email = ?", (normalized,))
row = await existing.fetchone()
if row and row[1] == "!unusable" and normalized == admin_email:
raise ValueError("email_exists")
Comment on lines +193 to +194
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve bootstrap path for configured admin account

This guard locks out admin bootstrap on fresh deployments: _ensure_admin_account seeds OPENCMO_ADMIN_EMAIL with password_hash='!unusable', and authenticate_user rejects unusable hashes, so the only in-app way to claim that row was signup updating the password. After this change, signup for that email always returns email_exists, leaving no API path to ever set an admin password and making /api/v1/admin/* inaccessible unless operators manually edit the DB.

Useful? React with 👍 / 👎.

if row and row[1] != "!unusable":
raise ValueError("email_exists")

Expand All @@ -206,7 +209,7 @@ async def create_user_with_account(email: str, password: str, name: str = "") ->
normalized,
hash_password(password),
name.strip(),
"admin" if normalized == os.environ.get("OPENCMO_ADMIN_EMAIL", "hello@aidcmo.com").strip().lower() else "user",
"user",
),
)
user_id = int(cursor.lastrowid)
Expand Down
Loading