Avoid multi-line heredoc paste issues over SSH. Run:
docker compose -f deploy/docker-compose.prod.yml \
--env-file deploy/.env.prod \
exec api python scripts/reset_password.py user@example.com NEWPW
Sets password_hash + is_active=True, prints user role on success.
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Reset a user's password.
|
|
|
|
Usage (inside the api container):
|
|
python scripts/reset_password.py <email> <new_password>
|
|
|
|
Or via docker:
|
|
docker compose -f deploy/docker-compose.prod.yml --env-file deploy/.env.prod \\
|
|
exec api python scripts/reset_password.py user@example.com hunter2
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import sys
|
|
|
|
|
|
async def _main(email: str, new_password: str) -> int:
|
|
from sqlalchemy import select
|
|
|
|
from app.db import session_scope
|
|
from app.models import User
|
|
from app.services.auth import hash_password
|
|
|
|
async with session_scope() as db:
|
|
user = (
|
|
await db.execute(select(User).where(User.email == email))
|
|
).scalar_one_or_none()
|
|
if user is None:
|
|
print(f"no user with email {email!r}", file=sys.stderr)
|
|
return 2
|
|
user.password_hash = hash_password(new_password)
|
|
user.is_active = True
|
|
print(f"password reset for {user.email} (role={user.role})")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 3:
|
|
print(__doc__, file=sys.stderr)
|
|
sys.exit(2)
|
|
sys.exit(asyncio.run(_main(sys.argv[1], sys.argv[2])))
|