Make config part of bootstrap.
This commit is contained in:
+11
-4
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
+13
-13
@@ -199,16 +199,14 @@ 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(
|
||||
rp_id=args.rp_id,
|
||||
rp_name=args.rp_name,
|
||||
origins=args.origins,
|
||||
auth_host=args.auth_host,
|
||||
listen=args.listen,
|
||||
)
|
||||
# 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,
|
||||
auth_host=args.auth_host,
|
||||
listen=args.listen,
|
||||
)
|
||||
|
||||
run_kwargs: dict = {
|
||||
"log_level": "warning", # Suppress startup messages; we use custom logging
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user