Skip to content
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,8 @@ for provider in providers:

The method returns an immutable tuple of `LinkedOAuthProvider` values and raises
`SessionChangedError` if the active session changes while the request is in flight.
It also accepts responses from older servers that omit provider IDs and logins;
the public result contains the provider name and linkage timestamps.

Start linking another OAuth provider to the current account:

Expand Down
39,854 changes: 24,989 additions & 14,865 deletions openapi/openapi.yaml

Large diffs are not rendered by default.

41 changes: 37 additions & 4 deletions src/volcano_sdk/_auth_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import re
import secrets
from collections.abc import Mapping
from datetime import datetime
Expand Down Expand Up @@ -77,6 +78,11 @@
INVALID_LINKED_OAUTH_PROVIDERS = "Expected complete linked OAuth providers"


OAUTH_PROVIDER_TIMESTAMP = re.compile(
r"\d{4}-\d{2}-\d{2}T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)"
)


INVALID_OAUTH_LINK = "Expected an OAuth authorization URL"


Expand Down Expand Up @@ -387,16 +393,19 @@ def session_page_from_payload(payload: object) -> SessionPage:
def linked_oauth_provider_from_model(
item: AuthListOAuthProvidersResponse200ProvidersItem,
) -> LinkedOAuthProvider:
provider = item.provider
if not isinstance(provider, str) or not provider.strip():
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS)
return LinkedOAuthProvider(
provider=provider,
provider=linked_oauth_provider_string(item.provider),
linked_at=linked_oauth_datetime(item.linked_at),
updated_at=linked_oauth_datetime(item.updated_at),
)


def linked_oauth_provider_string(value: object) -> str:
if not isinstance(value, str) or not value.strip():
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS)
return value


def linked_oauth_datetime(value: object) -> datetime:
if not isinstance(value, datetime):
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS)
Expand All @@ -406,6 +415,11 @@ def linked_oauth_datetime(value: object) -> datetime:
def linked_oauth_providers_from_payload(
payload: object,
) -> tuple[LinkedOAuthProvider, ...]:
if is_object_mapping(payload):
providers = payload.get("providers")
if not is_object_sequence(providers):
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS)
return tuple(linked_oauth_provider_from_wire(item) for item in providers)
if not isinstance(payload, AuthListOAuthProvidersResponse200) or isinstance(
payload.providers, Unset
):
Expand All @@ -415,6 +429,25 @@ def linked_oauth_providers_from_payload(
)


def linked_oauth_provider_from_wire(value: object) -> LinkedOAuthProvider:
if not is_object_mapping(value):
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS)
return LinkedOAuthProvider(
provider=linked_oauth_provider_string(value.get("provider")),
linked_at=linked_oauth_wire_datetime(value.get("linked_at")),
updated_at=linked_oauth_wire_datetime(value.get("updated_at")),
)


def linked_oauth_wire_datetime(value: object) -> datetime:
if not isinstance(value, str) or not OAUTH_PROVIDER_TIMESTAMP.fullmatch(value):
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS)
try:
return datetime.fromisoformat(value)
except ValueError as error:
raise VolcanoError(INVALID_LINKED_OAUTH_PROVIDERS) from error


def oauth_provider_name(value: object) -> OAuthProviderName:
if not isinstance(value, str) or value not in OAUTH_PROVIDERS:
raise ValueError(UNSUPPORTED_OAUTH_PROVIDER)
Expand Down
Loading
Loading