towards multi-user
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""bincio init — bootstrap a fresh multi-user instance."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
@click.command("init")
|
||||
@click.option("--data-dir", required=True, type=click.Path(), help="BAS data directory to initialise")
|
||||
@click.option("--handle", required=True, help="Admin user handle (e.g. 'dave')")
|
||||
@click.option("--password", required=True, hide_input=True, confirmation_prompt=True, help="Admin password")
|
||||
@click.option("--display-name", default="", help="Admin display name (defaults to handle)")
|
||||
@click.option("--name", default="", help="Instance name shown in the feed")
|
||||
def init(data_dir: str, handle: str, password: str, display_name: str, name: str) -> None:
|
||||
"""Bootstrap a fresh bincio multi-user instance.
|
||||
|
||||
Creates the SQLite database, the admin user, the per-user data directory,
|
||||
and prints a first invite code. Safe to re-run — skips steps already done.
|
||||
"""
|
||||
from bincio.serve.db import create_invite, create_user, get_user, open_db
|
||||
|
||||
dd = Path(data_dir).expanduser().resolve()
|
||||
dd.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
console.print(f"[bold]Initialising bincio instance[/bold] at [cyan]{dd}[/cyan]")
|
||||
|
||||
# ── Database ─────────────────────────────────────────────────────────────
|
||||
db = open_db(dd)
|
||||
console.print(" [green]✓[/green] instance.db ready")
|
||||
|
||||
# ── Admin user ───────────────────────────────────────────────────────────
|
||||
existing = get_user(db, handle)
|
||||
if existing:
|
||||
console.print(f" [yellow]·[/yellow] user '{handle}' already exists — skipping")
|
||||
else:
|
||||
create_user(db, handle, display_name or handle, password, is_admin=True)
|
||||
console.print(f" [green]✓[/green] admin user '{handle}' created")
|
||||
|
||||
# ── User data directory ───────────────────────────────────────────────────
|
||||
user_dir = dd / handle
|
||||
user_dir.mkdir(exist_ok=True)
|
||||
(user_dir / "activities").mkdir(exist_ok=True)
|
||||
(user_dir / "edits").mkdir(exist_ok=True)
|
||||
console.print(f" [green]✓[/green] data dir {dd / handle}/ ready")
|
||||
|
||||
# ── Root index.json shard manifest ───────────────────────────────────────
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
root_index = dd / "index.json"
|
||||
if not root_index.exists():
|
||||
manifest = {
|
||||
"bas_version": "1.0",
|
||||
"instance": {"name": name or "BincioActivity", "private": True},
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"shards": [{"handle": handle, "url": f"{handle}/index.json"}],
|
||||
"activities": [],
|
||||
}
|
||||
root_index.write_text(json.dumps(manifest, indent=2))
|
||||
console.print(" [green]✓[/green] root index.json manifest written")
|
||||
else:
|
||||
console.print(" [yellow]·[/yellow] root index.json already exists — skipping")
|
||||
|
||||
# ── First invite code ─────────────────────────────────────────────────────
|
||||
code = create_invite(db, handle)
|
||||
|
||||
console.print()
|
||||
console.print(Panel(
|
||||
f"[bold green]Instance ready![/bold green]\n\n"
|
||||
f"Admin: [cyan]{handle}[/cyan]\n"
|
||||
f"Data dir: [cyan]{dd}[/cyan]\n\n"
|
||||
f"First invite code:\n\n"
|
||||
f" [bold yellow]{code}[/bold yellow]\n\n"
|
||||
f"Share this link with your first user:\n"
|
||||
f" /register/?code={code}",
|
||||
title="bincio init",
|
||||
border_style="green",
|
||||
))
|
||||
Reference in New Issue
Block a user