Show the OIDC profile picture with an identicon fallback
CI / Build and push docker image (push) Successful in 2m9s
CI / Build and push docker image (push) Successful in 2m9s
GET /api/me now carries the profile picture URL when the provider supplies an absolute http(s) one; the SPA shows it in the lobby navbar and draws a deterministic identicon from the sub otherwise, falling back to the identicon when the image fails to load. The identicon is a 5x5 mirrored grid seeded by an inline FNV-1a hash so it stays stable across Rust versions and is unit-testable on the host. The dev mock IdP hands alice and bob a picture claim.
This commit is contained in:
@@ -19,6 +19,7 @@ from tavolo.platform.auth import (
|
||||
current_user,
|
||||
display_name,
|
||||
get_ws_user,
|
||||
picture,
|
||||
require_auth,
|
||||
session_user,
|
||||
)
|
||||
@@ -121,6 +122,23 @@ class DisplayNameTest(unittest.TestCase):
|
||||
self.assertEqual("alice", display_name(user))
|
||||
|
||||
|
||||
class PictureTest(unittest.TestCase):
|
||||
"""Only absolute http(s) picture claims are exported to the SPA."""
|
||||
|
||||
def test_uses_an_absolute_http_url(self) -> None:
|
||||
user = OIDCUser({"sub": "alice", "picture": "https://cdn.example.com/a.png"})
|
||||
self.assertEqual("https://cdn.example.com/a.png", picture(user))
|
||||
|
||||
def test_rejects_relative_and_script_schemes(self) -> None:
|
||||
for value in ("/relative.png", "javascript:alert(1)", "data:image/png;base64,x"):
|
||||
with self.subTest(picture=value):
|
||||
user = OIDCUser({"sub": "alice", "picture": value})
|
||||
self.assertIsNone(picture(user))
|
||||
|
||||
def test_missing_claim_is_none(self) -> None:
|
||||
self.assertIsNone(picture(OIDCUser({"sub": "alice"})))
|
||||
|
||||
|
||||
class CurrentUserTest(unittest.TestCase):
|
||||
def test_anonymous_session_has_no_user(self) -> None:
|
||||
self.assertIsNone(current_user(_providers("default"), _ctx({})))
|
||||
|
||||
Reference in New Issue
Block a user