diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/app.py')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/app.py | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/app.py b/packages/meshbay-hub/src/meshbay_hub/app.py index 7ccf598..ca05fd8 100644 --- a/packages/meshbay-hub/src/meshbay_hub/app.py +++ b/packages/meshbay-hub/src/meshbay_hub/app.py @@ -21,7 +21,6 @@ from meshbay_hub.api.admin import router as admin_router from meshbay_hub.api.deps import set_admin_usernames from meshbay_hub.api.federation import router as federation_router from meshbay_hub.api.groups import router as groups_router -from meshbay_hub.api.groups import swarm_router from meshbay_hub.api.health import router as health_router from meshbay_hub.api.hub import router as hub_router from meshbay_hub.api.hub import set_config as hub_set_config @@ -31,7 +30,6 @@ from meshbay_hub.api.middleware import limiter from meshbay_hub.api.moderation import router as moderation_router from meshbay_hub.api.nodes import router as nodes_router from meshbay_hub.api.notifications import router as notifications_router -from meshbay_hub.api.relay import router as relay_router from meshbay_hub.api.revocation import router as revocation_router from meshbay_hub.api.signaling import router as signaling_router from meshbay_hub.api.users import router as users_router @@ -41,26 +39,55 @@ from meshbay_hub.api.webapp import configure as webapp_configure from meshbay_hub.api.webapp import router as webapp_router from meshbay_hub.auth import generate_hub_keypair, load_hub_keypair from meshbay_hub.config import HubConfig -from meshbay_hub.csam import csam_router from meshbay_hub.db.engine import close_db, init_db -async def _sync_admin_roles(admin_usernames: list[str]) -> None: - """Ensure config-listed admin usernames have role='admin' in the DB.""" +async def _pin_config_admins(admin_usernames: list[str]) -> None: + """Pin each allow-listed admin name to the account holding it, once. + + A name already pinned keeps its account whoever holds the name now, which is + what stops a released name from being registered into the admin role. Pins + of names no longer listed are dropped: removing a name, restarting, then + listing it again is how an operator hands it to a new account. + """ + import logging + from sqlalchemy import select + from meshbay_hub.api.deps import set_admin_pins from meshbay_hub.db.engine import get_session_factory - from meshbay_hub.db.models import User + from meshbay_hub.db.models import AdminPin, User + log = logging.getLogger(__name__) + listed = set(admin_usernames) factory = get_session_factory() async with factory() as session: - result = await session.execute( - select(User).where(User.username.in_(admin_usernames)) - ) - for user in result.scalars().all(): - if user.role != "admin": - user.role = "admin" + pins: dict[str, str] = {} + for pin in (await session.execute(select(AdminPin))).scalars().all(): + if pin.username in listed: + pins[pin.username] = pin.user_id + else: + log.info("Admin allow-list: %s is no longer listed, its pin is dropped", + pin.username) + await session.delete(pin) + + unpinned = listed - pins.keys() + if unpinned: + holders = (await session.execute(select(User).where( + User.username.in_(unpinned), User.status == "active"))).scalars().all() + for user in holders: + session.add(AdminPin(username=user.username, user_id=user.id)) + pins[user.username] = user.id + log.info("Admin allow-list: %s pinned to account %s", + user.username, user.id[:8]) + + if pins: + for user in (await session.execute(select(User).where( + User.id.in_(pins.values()), User.status == "active"))).scalars().all(): + if user.role != "admin": + user.role = "admin" await session.commit() + set_admin_pins(pins) async def _backfill_email_hashes() -> None: @@ -126,11 +153,7 @@ def create_app(cfg: HubConfig | None = None) -> FastAPI: # back to. _hub_settings.set_mail_defaults(cfg.mail) - if cfg.identity.admin_usernames: - await _sync_admin_roles(cfg.identity.admin_usernames) - - from meshbay_hub.csam import get_csam_checker - get_csam_checker().load() + await _pin_config_admins(cfg.identity.admin_usernames) from meshbay_hub.db.engine import get_session_factory from meshbay_hub.tasks.cleanup import cleanup_loop @@ -203,13 +226,10 @@ def create_app(cfg: HubConfig | None = None) -> FastAPI: app.include_router(groups_router) app.include_router(invite_links_router) app.include_router(invite_links_redeem_router) - app.include_router(swarm_router) app.include_router(revocation_router) app.include_router(moderation_router) app.include_router(federation_router) - app.include_router(csam_router) app.include_router(health_router) - app.include_router(relay_router) app.include_router(signaling_router) app.include_router(admin_router) app.include_router(notifications_router) |