diff --git a/robosystems_client/api/auth/generate_sso_token.py b/robosystems_client/api/auth/generate_sso_token.py index cba81fd..f952422 100644 --- a/robosystems_client/api/auth/generate_sso_token.py +++ b/robosystems_client/api/auth/generate_sso_token.py @@ -81,8 +81,8 @@ def sync_detailed( ) -> Response[ErrorResponse | HTTPValidationError | SSOTokenResponse]: """Generate SSO Token - Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (60s TTL) for handoff to a target - application. + Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (5 minute TTL) for handoff to a + target application. Args: auth_token (None | str | Unset): @@ -113,8 +113,8 @@ def sync( ) -> ErrorResponse | HTTPValidationError | SSOTokenResponse | None: """Generate SSO Token - Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (60s TTL) for handoff to a target - application. + Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (5 minute TTL) for handoff to a + target application. Args: auth_token (None | str | Unset): @@ -140,8 +140,8 @@ async def asyncio_detailed( ) -> Response[ErrorResponse | HTTPValidationError | SSOTokenResponse]: """Generate SSO Token - Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (60s TTL) for handoff to a target - application. + Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (5 minute TTL) for handoff to a + target application. Args: auth_token (None | str | Unset): @@ -170,8 +170,8 @@ async def asyncio( ) -> ErrorResponse | HTTPValidationError | SSOTokenResponse | None: """Generate SSO Token - Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (60s TTL) for handoff to a target - application. + Step 1 of 3 in the cross-app SSO flow. Issues a single-use token (5 minute TTL) for handoff to a + target application. Args: auth_token (None | str | Unset): diff --git a/robosystems_client/api/auth/get_auth_providers.py b/robosystems_client/api/auth/get_auth_providers.py new file mode 100644 index 0000000..9a1e830 --- /dev/null +++ b/robosystems_client/api/auth/get_auth_providers.py @@ -0,0 +1,156 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.auth_providers_response import AuthProvidersResponse +from ...models.error_response import ErrorResponse +from ...types import Response + + +def _get_kwargs() -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/v1/auth/providers", + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> AuthProvidersResponse | ErrorResponse | None: + if response.status_code == 200: + response_200 = AuthProvidersResponse.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[AuthProvidersResponse | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, +) -> Response[AuthProvidersResponse | ErrorResponse]: + """Get Auth Providers + + Returns which authentication methods this deployment offers. The login surface renders its posture + from this instead of hardcoding methods. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[AuthProvidersResponse | ErrorResponse] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, +) -> AuthProvidersResponse | ErrorResponse | None: + """Get Auth Providers + + Returns which authentication methods this deployment offers. The login surface renders its posture + from this instead of hardcoding methods. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + AuthProvidersResponse | ErrorResponse + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, +) -> Response[AuthProvidersResponse | ErrorResponse]: + """Get Auth Providers + + Returns which authentication methods this deployment offers. The login surface renders its posture + from this instead of hardcoding methods. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[AuthProvidersResponse | ErrorResponse] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, +) -> AuthProvidersResponse | ErrorResponse | None: + """Get Auth Providers + + Returns which authentication methods this deployment offers. The login surface renders its posture + from this instead of hardcoding methods. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + AuthProvidersResponse | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index 8719cd5..0586c28 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -13,6 +13,7 @@ from .asserted_metric_lite import AssertedMetricLite from .association_response import AssociationResponse from .attribution_filter import AttributionFilter +from .auth_providers_response import AuthProvidersResponse from .auth_response import AuthResponse from .auth_response_org_type_0 import AuthResponseOrgType0 from .auth_response_user import AuthResponseUser @@ -358,6 +359,7 @@ from .offering_repository_plan_rate_limits_type_0 import ( OfferingRepositoryPlanRateLimitsType0, ) +from .oidc_provider_info import OIDCProviderInfo from .operation_costs import OperationCosts from .operation_costs_ai_operations import OperationCostsAiOperations from .operation_costs_token_pricing import OperationCostsTokenPricing @@ -888,6 +890,7 @@ "AssertMetricsResponse", "AssociationResponse", "AttributionFilter", + "AuthProvidersResponse", "AuthResponse", "AuthResponseOrgType0", "AuthResponseUser", @@ -1173,6 +1176,7 @@ "OAuthInitResponse", "OfferingRepositoryPlan", "OfferingRepositoryPlanRateLimitsType0", + "OIDCProviderInfo", "OperationCosts", "OperationCostsAiOperations", "OperationCostsTokenPricing", diff --git a/robosystems_client/models/auth_providers_response.py b/robosystems_client/models/auth_providers_response.py new file mode 100644 index 0000000..e5d4726 --- /dev/null +++ b/robosystems_client/models/auth_providers_response.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.oidc_provider_info import OIDCProviderInfo + + +T = TypeVar("T", bound="AuthProvidersResponse") + + +@_attrs_define +class AuthProvidersResponse: + """Auth posture response model. + + Describes which authentication methods this deployment offers so the + login surface can render the correct posture from runtime configuration. + + Attributes: + password_auth (bool): Whether password authentication is available + oidc (OIDCProviderInfo): OIDC provider availability model. + registration (bool): Whether self-service registration is open + passkeys (bool): Whether passkey authentication is available + """ + + password_auth: bool + oidc: OIDCProviderInfo + registration: bool + passkeys: bool + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + password_auth = self.password_auth + + oidc = self.oidc.to_dict() + + registration = self.registration + + passkeys = self.passkeys + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "password_auth": password_auth, + "oidc": oidc, + "registration": registration, + "passkeys": passkeys, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.oidc_provider_info import OIDCProviderInfo + + d = dict(src_dict) + password_auth = d.pop("password_auth") + + oidc = OIDCProviderInfo.from_dict(d.pop("oidc")) + + registration = d.pop("registration") + + passkeys = d.pop("passkeys") + + auth_providers_response = cls( + password_auth=password_auth, + oidc=oidc, + registration=registration, + passkeys=passkeys, + ) + + auth_providers_response.additional_properties = d + return auth_providers_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/oidc_provider_info.py b/robosystems_client/models/oidc_provider_info.py new file mode 100644 index 0000000..a0ad274 --- /dev/null +++ b/robosystems_client/models/oidc_provider_info.py @@ -0,0 +1,84 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="OIDCProviderInfo") + + +@_attrs_define +class OIDCProviderInfo: + """OIDC provider availability model. + + Attributes: + enabled (bool): Whether OIDC SSO is available + provider_label (None | str | Unset): Display label for the OIDC provider (e.g. 'Okta') + """ + + enabled: bool + provider_label: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + enabled = self.enabled + + provider_label: None | str | Unset + if isinstance(self.provider_label, Unset): + provider_label = UNSET + else: + provider_label = self.provider_label + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "enabled": enabled, + } + ) + if provider_label is not UNSET: + field_dict["provider_label"] = provider_label + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + enabled = d.pop("enabled") + + def _parse_provider_label(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + provider_label = _parse_provider_label(d.pop("provider_label", UNSET)) + + oidc_provider_info = cls( + enabled=enabled, + provider_label=provider_label, + ) + + oidc_provider_info.additional_properties = d + return oidc_provider_info + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties