Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ client = VolcanoClient(
)

session = client.auth.sign_in(email="user@example.com", password="secret")
current_session = client.auth.get_session()
assert current_session == session

rows = client.database("main").from_("items").select("*").eq("slug", "a").execute()

Expand All @@ -30,6 +32,8 @@ lease = client.locks.acquire("build", ttl=30)
client.locks.release("build", lease)
```

`get_session()` reads immutable local state. It does not refresh or validate the token.

Realtime is async. Channels wrap `centrifuge-python`; the underlying client and
subscription objects are not part of the public API.

Expand Down
9 changes: 9 additions & 0 deletions features/contract/auth.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@ Feature: SDK authentication contract
Then the SDK operation succeeds
And the current session belongs to the contract user
And the current session exposes access and refresh tokens

@auth @SDK-AUTH-002
Scenario: The auth facade returns the current session
Given the confirmed contract user
When the client signs in with the contract user's credentials
And the client reads the current session
Then the SDK operation succeeds
And the current session belongs to the contract user
And the current session exposes access and refresh tokens
6 changes: 6 additions & 0 deletions features/steps/sdk_contract_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ def sign_in(context: Any) -> None:
)


@when("the client reads the current session")
def read_current_session(context: Any) -> None:
world = _world(context)
world.record(world.client.auth.get_session)


@then("the SDK operation succeeds")
def operation_succeeds(context: Any) -> None:
outcome = _world(context).last_outcome
Expand Down
9 changes: 9 additions & 0 deletions src/volcano_sdk/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class AuthContext(Protocol):

_transport: Transport

@property
def current_session(self) -> Session | None:
"""Return the locally held session, if one exists."""
...

def _anon_token(self) -> str: ...

def _set_session(self, session: Session) -> None: ...
Expand All @@ -25,6 +30,10 @@ def __init__(self, client: AuthContext) -> None:
"""Create an authentication facade backed by a client."""
self._client = client

def get_session(self) -> Session | None:
"""Return the immutable locally held session without validating it."""
return self._client.current_session

def sign_in(self, *, email: str, password: str) -> Session:
"""Sign in a user and store the returned session."""
response = invoke(
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/test_contract_bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

ROOT = Path(__file__).parents[2]
FEATURE_SHA256 = {
"auth.feature": "6e6bcc6244bbdb9b1c141a3f0d8f1256d2be0057429457084a094ed98cbcbd07",
"auth.feature": "70289856dcca9854464ae92659363f3395b2fe79d92ebb8374973f29f5c1994d",
"database.feature": (
"4685b29357a621068b25984ff0de29cd4c504eebe5cfb597f0b999e29878a668"
),
Expand Down Expand Up @@ -66,6 +66,7 @@ def test_every_contract_phrase_is_bound_verbatim() -> None:
"the SDK operation succeeds",
"the client acquires and releases the contract lock",
'the client selects the contract table where "slug" equals the fixture slug',
"the client reads the current session",
"the client signs in with the contract user's credentials",
"the client uploads and downloads the contract object",
"the confirmed contract user",
Expand Down
27 changes: 26 additions & 1 deletion tests/unit/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from dataclasses import dataclass
from typing import Any

from volcano_sdk import VolcanoClient
from volcano_sdk import Session, VolcanoClient


@dataclass(frozen=True)
Expand Down Expand Up @@ -107,3 +107,28 @@ def test_each_request_reads_the_current_credentials() -> None:
("acquire", "service-1"),
("release", "service-2"),
]


def test_auth_facade_reads_an_empty_session_without_transport() -> None:
transport = StateTransport()
client = VolcanoClient(anon_key="anon", _transport=transport)

assert client.auth.get_session() is None
assert transport.authorizations == []


def test_auth_facade_reads_established_immutable_session_without_transport() -> None:
transport = StateTransport()
client = VolcanoClient(anon_key="anon", _transport=transport)
established = client.auth.sign_in(email="user@example.com", password="secret")
calls_after_sign_in = list(transport.authorizations)

current = client.auth.get_session()

assert current is established
assert current == Session(
access_token="access-1",
refresh_token="refresh-access-1",
user_id="user-123",
)
assert transport.authorizations == calls_after_sign_in
Loading