Prefer preferred_username for the displayed player name
CI / Build and push docker image (push) Successful in 1m8s
CI / Build and push docker image (push) Successful in 1m8s
The free-form "name" claim can change and two accounts can share it; preferred_username is the account's stable handle. display_name() now falls back preferred_username -> name -> email -> sub, with tests pinning the claim priority.
This commit is contained in:
@@ -47,8 +47,13 @@ def get_ws_user(ws: WebSocket) -> Optional[OIDCUser]:
|
||||
|
||||
|
||||
def display_name(user: OIDCUser) -> str:
|
||||
"""Best-effort human-readable name for a user."""
|
||||
for key in ("name", "preferred_username", "email"):
|
||||
"""Best-effort human-readable name for a user.
|
||||
|
||||
``preferred_username`` is preferred: it is the account's stable handle,
|
||||
while ``name`` is a free-form display name a user may change (and two
|
||||
accounts can share). ``email`` is a last resort before the ``sub``.
|
||||
"""
|
||||
for key in ("preferred_username", "name", "email"):
|
||||
value = user.get(key)
|
||||
if isinstance(value, str) and value:
|
||||
return value
|
||||
|
||||
@@ -11,11 +11,17 @@ import unittest
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
|
||||
from kaya.oidc import OIDCConfig, OIDCProviders
|
||||
from kaya.oidc import OIDCConfig, OIDCProviders, OIDCUser
|
||||
from kaya.session import InMemorySessionStore, Session, SessionMixin
|
||||
|
||||
from helpers import async_test
|
||||
from tavolo.platform.auth import current_user, get_ws_user, require_auth, session_user
|
||||
from tavolo.platform.auth import (
|
||||
current_user,
|
||||
display_name,
|
||||
get_ws_user,
|
||||
require_auth,
|
||||
session_user,
|
||||
)
|
||||
|
||||
|
||||
def _providers(*names: str) -> OIDCProviders:
|
||||
@@ -87,6 +93,32 @@ class GetWsUserTest(unittest.TestCase):
|
||||
self.assertIsNone(get_ws_user(SimpleNamespace()))
|
||||
|
||||
|
||||
class DisplayNameTest(unittest.TestCase):
|
||||
"""The claim priority used for the name shown at the table."""
|
||||
|
||||
def test_prefers_preferred_username_over_name(self) -> None:
|
||||
user = OIDCUser(
|
||||
{"sub": "alice", "preferred_username": "alice", "name": "Alice"}
|
||||
)
|
||||
self.assertEqual("alice", display_name(user))
|
||||
|
||||
def test_falls_back_to_name(self) -> None:
|
||||
user = OIDCUser({"sub": "alice", "name": "Alice"})
|
||||
self.assertEqual("Alice", display_name(user))
|
||||
|
||||
def test_falls_back_to_email(self) -> None:
|
||||
user = OIDCUser({"sub": "alice", "email": "alice@example.com"})
|
||||
self.assertEqual("alice@example.com", display_name(user))
|
||||
|
||||
def test_falls_back_to_sub(self) -> None:
|
||||
user = OIDCUser({"sub": "alice"})
|
||||
self.assertEqual("alice", display_name(user))
|
||||
|
||||
def test_ignores_empty_and_non_string_claims(self) -> None:
|
||||
user = OIDCUser({"sub": "alice", "preferred_username": "", "name": 42})
|
||||
self.assertEqual("alice", display_name(user))
|
||||
|
||||
|
||||
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