Skip to content

Commit 10d11e5

Browse files
committed
Convert authenticators to pydantic models
1 parent cb7c46f commit 10d11e5

File tree

6 files changed

+111
-190
lines changed

6 files changed

+111
-190
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Write the date in place of the "Unreleased" in the case a new version is release
1919
of Closure Table to track ancestors and descendands of the nodes.
2020
- Shorter string representation of chunks in `ArrayClient`.
2121
- Refactored internal Zarr version detection
22+
- Convert authenticators into pydantic models
2223

2324
### Fixed
2425

tiled/_tests/test_access_control.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import json
2+
import secrets
3+
from typing import Any
24

35
import numpy
46
import pytest
57
from starlette.status import HTTP_403_FORBIDDEN
8+
from typing_extensions import TypedDict
69

7-
from tiled.authenticators import DictionaryAuthenticator
8-
from tiled.server.protocols import UserSessionState
10+
from tiled.server.protocols import InternalAuthenticator, UserSessionState
911

1012
from ..access_policies import NO_ACCESS
1113
from ..adapters.array import ArrayAdapter
@@ -531,22 +533,23 @@ def test_service_principal_access(tmpdir, sqlite_or_postgres_uri):
531533
assert list(sp_client) == ["x"]
532534

533535

534-
class CustomAttributesAuthenticator(DictionaryAuthenticator):
536+
UserAttributes = TypedDict(
537+
"UserAttributes", {"password": str, "attributes": dict[str, Any]}, total=False
538+
)
539+
540+
541+
class CustomAttributesAuthenticator(InternalAuthenticator):
535542
"""An example authenticator that enriches the stored user information."""
536543

537-
def __init__(self, users: dict, confirmation_message: str = ""):
538-
self._users = users
539-
super().__init__(
540-
{username: user["password"] for username, user in users.items()},
541-
confirmation_message,
542-
)
544+
users: dict[str, UserAttributes] = {}
543545

544546
async def authenticate(self, username, password):
545-
state = await super().authenticate(username, password)
546-
if isinstance(state, UserSessionState):
547-
# enrich the auth state
548-
state.state["attributes"] = self._users[username].get("attributes", {})
549-
return state
547+
if (attrs := self.users.get(username)) and (pw := attrs.get("password")):
548+
if secrets.compare_digest(pw, password):
549+
state = UserSessionState(
550+
username, {"attributes": attrs.get("attributes", {})}
551+
)
552+
return state
550553

551554

552555
class CustomAttributesAccessPolicy:

tiled/_tests/test_authenticators.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@
2525
])
2626
# fmt: on
2727
@pytest.mark.parametrize("use_tls,use_ssl", [(False, False)])
28+
@pytest.mark.skipif(not TILED_TEST_LDAP, reason="Requires an LDAP container and TILED_TEST_LDAP to be set")
2829
def test_LDAPAuthenticator_01(use_tls, use_ssl, ldap_server_address, ldap_server_port):
2930
"""
3031
Basic test for ``LDAPAuthenticator``.
3132
3233
TODO: The test could be extended with enabled TLS or SSL, but it requires configuration
3334
of the LDAP server.
3435
"""
35-
if not TILED_TEST_LDAP:
36-
pytest.skip("Run an LDAP container and set TILED_TEST_LDAP to run")
37-
authenticator = LDAPAuthenticator(
38-
ldap_server_address,
39-
ldap_server_port,
40-
bind_dn_template="cn={username},ou=users,dc=example,dc=org",
41-
use_tls=use_tls,
42-
use_ssl=use_ssl,
43-
)
36+
37+
params = dict(server_address=ldap_server_address,
38+
bind_dn_template="cn={username},ou=users,dc=example,dc=org",
39+
use_ssl=use_ssl,
40+
use_tls=use_tls)
41+
if ldap_server_port is not None:
42+
params["server_port"] = ldap_server_port
43+
authenticator = LDAPAuthenticator(**params)
4444

4545
async def testing():
4646
assert (await authenticator.authenticate("user01", "password1")).user_name == "user01"

0 commit comments

Comments
 (0)