- New POST /api/auth/microsoft endpoint validates Azure ID token via JWKS - Removed POST /api/auth/login and /change-password - Added azure_oid + nullable password_hash to users (migration 0007) - Auto-provisions all @oliver.agency accounts on first SSO login - Case-insensitive email matching links existing vadymsamoilenko@ account - DEV_AUTH_BYPASS flag for local development without MSAL - Frontend: MSAL loginPopup replaces email/password form - Added scripts/grant_admin.py for role management Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
32 lines
972 B
Python
32 lines
972 B
Python
"""Grant admin role to a user by email (SSO users).
|
|
|
|
Usage:
|
|
docker compose exec app python scripts/grant_admin.py user@oliver.agency
|
|
"""
|
|
import asyncio
|
|
import sys
|
|
|
|
from sqlalchemy import func, select
|
|
|
|
from src.database import async_session_factory
|
|
from src.models import User
|
|
|
|
|
|
async def grant_admin(email: str) -> None:
|
|
email = email.strip().lower()
|
|
async with async_session_factory() as db:
|
|
result = await db.execute(select(User).where(func.lower(User.email) == email))
|
|
user = result.scalar_one_or_none()
|
|
if user is None:
|
|
print(f"User {email!r} not found. They must log in via SSO first.")
|
|
sys.exit(1)
|
|
user.role = "admin"
|
|
await db.commit()
|
|
print(f"Granted admin to {user.email} (id={user.id})")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 2:
|
|
print("Usage: python scripts/grant_admin.py user@oliver.agency")
|
|
sys.exit(1)
|
|
asyncio.run(grant_admin(sys.argv[1]))
|