Adds optional SSO via Authentik (or any OIDC provider) alongside the existing password flow, and pulls profile images from the provider's `picture` claim or Gravatar so the sharing UI stops looking anonymous. Password login stays available as a recovery path; JIT provisioning and admin-group mapping are env-configurable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
29 lines
1.0 KiB
Python
29 lines
1.0 KiB
Python
"""Gravatar URL helper.
|
|
|
|
Pure function — no HTTP calls. The browser does the actual image
|
|
fetch. We just build the deterministic URL from the user's email and
|
|
let Gravatar serve an identicon when no account exists for that hash,
|
|
so the avatar is never a broken image.
|
|
|
|
Current Gravatar guidance is SHA-256 of the trimmed, lower-cased email.
|
|
MD5 still works but is deprecated, so we prefer SHA-256.
|
|
"""
|
|
import hashlib
|
|
from typing import Optional
|
|
|
|
|
|
def gravatar_url(email: Optional[str], size: int = 240) -> Optional[str]:
|
|
"""Return a Gravatar image URL for `email`, or None when email is empty.
|
|
|
|
The `d=identicon` fallback guarantees a deterministic placeholder when
|
|
the address has no Gravatar account, so callers can treat the result
|
|
as a valid image URL.
|
|
"""
|
|
if not email:
|
|
return None
|
|
normalized = email.strip().lower()
|
|
if not normalized:
|
|
return None
|
|
digest = hashlib.sha256(normalized.encode("utf-8")).hexdigest()
|
|
return f"https://gravatar.com/avatar/{digest}?d=identicon&s={size}"
|