Make config part of bootstrap.

This commit is contained in:
2026-02-09 18:33:29 +00:00
parent d826146932
commit 16ab111a89
4 changed files with 39 additions and 19 deletions
+11 -4
View File
@@ -10,6 +10,7 @@ import asyncio
import logging
from paskia import authsession, db, globals
from paskia.db.structs import Config
from paskia.util import hostutil
logger = logging.getLogger(__name__)
@@ -30,15 +31,18 @@ def _log_reset_link(passphrase: str, message: str | None = None) -> str:
return reset_link
async def bootstrap_system() -> None:
async def bootstrap_system(config: Config | None = None) -> None:
"""
Bootstrap the entire system with default data.
Uses db.bootstrap() which performs all operations in a single transaction.
The transaction log will show a single "bootstrap" action with all changes.
Args:
config: Configuration to store (rp_id, rp_name, origins, etc.)
"""
# Call the single-transaction bootstrap function
reset_passphrase = db.bootstrap()
reset_passphrase = db.bootstrap(config=config)
# Log the reset link (this is separate from the transaction log)
_log_reset_link(reset_passphrase, "✅ Bootstrap completed!")
@@ -89,10 +93,13 @@ async def check_admin_credentials() -> bool:
return False
async def bootstrap_if_needed() -> bool:
async def bootstrap_if_needed(config: Config | None = None) -> bool:
"""
Check if system needs bootstrapping and perform it if necessary.
Args:
config: Configuration to store during bootstrap (rp_id, rp_name, origins, etc.)
Returns:
bool: True if bootstrapping was performed, False if system was already set up
"""
@@ -105,7 +112,7 @@ async def bootstrap_if_needed() -> bool:
# No admin permission found, need to bootstrap
# Bootstrap creates the admin user AND the reset link, so no need to check credentials after
await bootstrap_system()
await bootstrap_system(config=config)
return True
+8 -2
View File
@@ -109,13 +109,19 @@ class UuidResolver:
return role_data["display_name"]
# Check permissions
if "permissions" in self._previous and uuid_str in self._previous["permissions"]:
if (
"permissions" in self._previous
and uuid_str in self._previous["permissions"]
):
perm_data = self._previous["permissions"][uuid_str]
if isinstance(perm_data, dict) and "display_name" in perm_data:
return perm_data["display_name"]
# Check credentials - look up user name
if "credentials" in self._previous and uuid_str in self._previous["credentials"]:
if (
"credentials" in self._previous
and uuid_str in self._previous["credentials"]
):
cred_data = self._previous["credentials"][uuid_str]
if isinstance(cred_data, dict) and "user" in cred_data:
user_uuid = cred_data["user"]
+7
View File
@@ -723,6 +723,7 @@ def bootstrap(
admin_name: str = "Admin",
reset_passphrase: str | None = None,
reset_expiry: datetime | None = None,
config: Config | None = None,
) -> str:
"""Bootstrap the entire system in a single transaction.
@@ -732,6 +733,7 @@ def bootstrap(
- Organization with Administration role
- Admin user with Administration role
- Reset token for admin registration
- Config (if provided)
This is the only way to create a new database file.
All data is created atomically - if any step fails, nothing is written.
@@ -741,6 +743,7 @@ def bootstrap(
admin_name: Display name for the admin user (default: "Admin")
reset_passphrase: Passphrase for the reset token (generated if not provided)
reset_expiry: Expiry datetime for the reset token (default: 14 days)
config: Configuration to store (rp_id, rp_name, origins, etc.)
Returns:
The reset passphrase for admin registration.
@@ -821,6 +824,10 @@ def bootstrap(
)
_db.reset_tokens[reset_token.key] = reset_token
# Set config if provided
if config is not None:
_db.config = config
return reset_passphrase
+7 -7
View File
@@ -199,10 +199,8 @@ def main():
startupbox.print_startup_config(config)
# Build config to save (will be saved after bootstrap in async_main)
save_config = None
if args.save:
save_config = Config(
# Build config to save (for bootstrap or explicit --save)
cli_config = Config(
rp_id=args.rp_id,
rp_name=args.rp_name,
origins=args.origins,
@@ -230,9 +228,11 @@ def main():
origins=config.origins,
bootstrap=False,
)
await bootstrap_if_needed()
if save_config is not None:
await set_config(save_config)
# Pass config to bootstrap - it will be saved within the bootstrap transaction
await bootstrap_if_needed(config=cli_config)
# Also save config if --save was explicitly used (even without bootstrap)
if args.save:
await set_config(cli_config)
await flush()
if len(endpoints) > 1: