app.bettersight.io/backend/services/auth_service.py

47 lines
1.7 KiB
Python

from repositories.pocketbase_client import pb_client
from repositories.tenant_repository import tenant_repository
from repositories.seat_repository import seat_repository
def get_tenant_id_from_request(request):
"""
Resolves the tenant_id for a dashboard request from its
`Authorization: Bearer {jwt}` header. The JWT itself is issued and
verified by PocketBase (the dashboard authenticates directly against
PocketBase) — this backend doesn't hold the JWT signing secret, so
it validates the token by asking PocketBase to refresh it, then
resolves the returned email to a tenant via the existing seat record.
Data flow:
request.headers['Authorization'] → strip "Bearer " prefix →
PocketBase POST /api/collections/users/auth-refresh →
{ record: { email } } → seat lookup by email across known tenants
(via domain) → tenant_id returned, or None if unresolvable
"""
auth_header = request.headers.get('Authorization', '')
if not auth_header.startswith('Bearer '):
return None
token = auth_header[len('Bearer '):]
record = pb_client.auth_refresh(token)
if not record or not record.get('email'):
return None
email = record['email']
domain = email.split('@', 1)[1].lower() if '@' in email else None
if not domain:
return None
tenant = tenant_repository.get_by_domain(domain)
if not tenant:
return None
# Confirm this email actually holds an active seat on the tenant —
# a verified PocketBase login alone isn't sufficient authorization,
# the email must also be a registered, active seat.
seat = seat_repository.get_active(tenant['id'], email)
if not seat:
return None
return tenant['id']