From 8c548f7bb0b4447f013db23642bfaff5357d5244 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 6 Jun 2024 23:21:30 +0000 Subject: [PATCH] feat(api): update via SDK Studio (#862) --- .stats.yml | 2 +- api.md | 43 +- src/cloudflare/resources/dns/__init__.py | 14 + src/cloudflare/resources/dns/dns.py | 32 + src/cloudflare/resources/dns/settings.py | 311 +++++++ .../resources/zero_trust/access/__init__.py | 14 + .../resources/zero_trust/access/access.py | 32 + .../resources/zero_trust/access/policies.py | 784 ++++++++++++++++++ src/cloudflare/types/dns/__init__.py | 7 + src/cloudflare/types/dns/dns_setting.py | 76 ++ src/cloudflare/types/dns/dns_setting_param.py | 76 ++ src/cloudflare/types/dns/nameserver.py | 12 + src/cloudflare/types/dns/nameserver_param.py | 12 + .../types/dns/setting_edit_params.py | 19 + .../types/dns/setting_edit_response.py | 12 + .../types/dns/setting_get_response.py | 12 + .../types/zero_trust/access/__init__.py | 7 + .../zero_trust/access/policy_create_params.py | 70 ++ .../access/policy_create_response.py | 79 ++ .../access/policy_delete_response.py | 12 + .../zero_trust/access/policy_get_response.py | 79 ++ .../zero_trust/access/policy_list_response.py | 79 ++ .../zero_trust/access/policy_update_params.py | 70 ++ .../access/policy_update_response.py | 79 ++ tests/api_resources/dns/test_settings.py | 256 ++++++ .../zero_trust/access/test_policies.py | 761 +++++++++++++++++ 26 files changed, 2941 insertions(+), 9 deletions(-) create mode 100644 src/cloudflare/resources/dns/settings.py create mode 100644 src/cloudflare/resources/zero_trust/access/policies.py create mode 100644 src/cloudflare/types/dns/dns_setting.py create mode 100644 src/cloudflare/types/dns/dns_setting_param.py create mode 100644 src/cloudflare/types/dns/nameserver.py create mode 100644 src/cloudflare/types/dns/nameserver_param.py create mode 100644 src/cloudflare/types/dns/setting_edit_params.py create mode 100644 src/cloudflare/types/dns/setting_edit_response.py create mode 100644 src/cloudflare/types/dns/setting_get_response.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_create_params.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_create_response.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_delete_response.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_get_response.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_list_response.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_update_params.py create mode 100644 src/cloudflare/types/zero_trust/access/policy_update_response.py create mode 100644 tests/api_resources/dns/test_settings.py create mode 100644 tests/api_resources/zero_trust/access/test_policies.py diff --git a/.stats.yml b/.stats.yml index 5cc013e4dcc..563ec8b4af0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 1336 +configured_endpoints: 1343 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-efdb1c15faba015f2904e7db0946e71b5bd84a6e4b96256aed210e7e0113cf17.yml diff --git a/api.md b/api.md index 81d0684fe74..c59b31a84a1 100644 --- a/api.md +++ b/api.md @@ -303,14 +303,6 @@ Methods: - client.zones.activation_check.trigger(\*, zone_id) -> Optional -## DNSSettings - -Types: - -```python -from cloudflare.types.zones import DNSSetting, Nameserver -``` - ## Settings ### ZeroRTT @@ -1650,6 +1642,19 @@ Methods: - client.dns.records.import\_(\*, zone_id, \*\*params) -> Optional - client.dns.records.scan(\*, zone_id, \*\*params) -> Optional +## Settings + +Types: + +```python +from cloudflare.types.dns import DNSSetting, Nameserver, SettingEditResponse, SettingGetResponse +``` + +Methods: + +- client.dns.settings.edit(\*, account_id, zone_id, \*\*params) -> Optional +- client.dns.settings.get(\*, account_id, zone_id) -> Optional + ## Analytics ### Reports @@ -5635,6 +5640,28 @@ Methods: - client.zero_trust.access.tags.delete(tag_name, \*, account_id) -> Optional - client.zero_trust.access.tags.get(tag_name, \*, account_id) -> Optional +### Policies + +Types: + +```python +from cloudflare.types.zero_trust.access import ( + PolicyCreateResponse, + PolicyUpdateResponse, + PolicyListResponse, + PolicyDeleteResponse, + PolicyGetResponse, +) +``` + +Methods: + +- client.zero_trust.access.policies.create(\*, account_id, \*\*params) -> Optional +- client.zero_trust.access.policies.update(policy_id, \*, account_id, \*\*params) -> Optional +- client.zero_trust.access.policies.list(\*, account_id) -> SyncSinglePage[PolicyListResponse] +- client.zero_trust.access.policies.delete(policy_id, \*, account_id) -> Optional +- client.zero_trust.access.policies.get(policy_id, \*, account_id) -> Optional + ## DEX Types: diff --git a/src/cloudflare/resources/dns/__init__.py b/src/cloudflare/resources/dns/__init__.py index 6f835256c8d..7e394f00159 100644 --- a/src/cloudflare/resources/dns/__init__.py +++ b/src/cloudflare/resources/dns/__init__.py @@ -24,6 +24,14 @@ FirewallResourceWithStreamingResponse, AsyncFirewallResourceWithStreamingResponse, ) +from .settings import ( + SettingsResource, + AsyncSettingsResource, + SettingsResourceWithRawResponse, + AsyncSettingsResourceWithRawResponse, + SettingsResourceWithStreamingResponse, + AsyncSettingsResourceWithStreamingResponse, +) from .analytics import ( AnalyticsResource, AsyncAnalyticsResource, @@ -40,6 +48,12 @@ "AsyncRecordsResourceWithRawResponse", "RecordsResourceWithStreamingResponse", "AsyncRecordsResourceWithStreamingResponse", + "SettingsResource", + "AsyncSettingsResource", + "SettingsResourceWithRawResponse", + "AsyncSettingsResourceWithRawResponse", + "SettingsResourceWithStreamingResponse", + "AsyncSettingsResourceWithStreamingResponse", "AnalyticsResource", "AsyncAnalyticsResource", "AnalyticsResourceWithRawResponse", diff --git a/src/cloudflare/resources/dns/dns.py b/src/cloudflare/resources/dns/dns.py index 2f71f123a84..7f758f9e906 100644 --- a/src/cloudflare/resources/dns/dns.py +++ b/src/cloudflare/resources/dns/dns.py @@ -18,6 +18,14 @@ FirewallResourceWithStreamingResponse, AsyncFirewallResourceWithStreamingResponse, ) +from .settings import ( + SettingsResource, + AsyncSettingsResource, + SettingsResourceWithRawResponse, + AsyncSettingsResourceWithRawResponse, + SettingsResourceWithStreamingResponse, + AsyncSettingsResourceWithStreamingResponse, +) from ..._compat import cached_property from .analytics import ( AnalyticsResource, @@ -39,6 +47,10 @@ class DNSResource(SyncAPIResource): def records(self) -> RecordsResource: return RecordsResource(self._client) + @cached_property + def settings(self) -> SettingsResource: + return SettingsResource(self._client) + @cached_property def analytics(self) -> AnalyticsResource: return AnalyticsResource(self._client) @@ -61,6 +73,10 @@ class AsyncDNSResource(AsyncAPIResource): def records(self) -> AsyncRecordsResource: return AsyncRecordsResource(self._client) + @cached_property + def settings(self) -> AsyncSettingsResource: + return AsyncSettingsResource(self._client) + @cached_property def analytics(self) -> AsyncAnalyticsResource: return AsyncAnalyticsResource(self._client) @@ -86,6 +102,10 @@ def __init__(self, dns: DNSResource) -> None: def records(self) -> RecordsResourceWithRawResponse: return RecordsResourceWithRawResponse(self._dns.records) + @cached_property + def settings(self) -> SettingsResourceWithRawResponse: + return SettingsResourceWithRawResponse(self._dns.settings) + @cached_property def analytics(self) -> AnalyticsResourceWithRawResponse: return AnalyticsResourceWithRawResponse(self._dns.analytics) @@ -103,6 +123,10 @@ def __init__(self, dns: AsyncDNSResource) -> None: def records(self) -> AsyncRecordsResourceWithRawResponse: return AsyncRecordsResourceWithRawResponse(self._dns.records) + @cached_property + def settings(self) -> AsyncSettingsResourceWithRawResponse: + return AsyncSettingsResourceWithRawResponse(self._dns.settings) + @cached_property def analytics(self) -> AsyncAnalyticsResourceWithRawResponse: return AsyncAnalyticsResourceWithRawResponse(self._dns.analytics) @@ -120,6 +144,10 @@ def __init__(self, dns: DNSResource) -> None: def records(self) -> RecordsResourceWithStreamingResponse: return RecordsResourceWithStreamingResponse(self._dns.records) + @cached_property + def settings(self) -> SettingsResourceWithStreamingResponse: + return SettingsResourceWithStreamingResponse(self._dns.settings) + @cached_property def analytics(self) -> AnalyticsResourceWithStreamingResponse: return AnalyticsResourceWithStreamingResponse(self._dns.analytics) @@ -137,6 +165,10 @@ def __init__(self, dns: AsyncDNSResource) -> None: def records(self) -> AsyncRecordsResourceWithStreamingResponse: return AsyncRecordsResourceWithStreamingResponse(self._dns.records) + @cached_property + def settings(self) -> AsyncSettingsResourceWithStreamingResponse: + return AsyncSettingsResourceWithStreamingResponse(self._dns.settings) + @cached_property def analytics(self) -> AsyncAnalyticsResourceWithStreamingResponse: return AsyncAnalyticsResourceWithStreamingResponse(self._dns.analytics) diff --git a/src/cloudflare/resources/dns/settings.py b/src/cloudflare/resources/dns/settings.py new file mode 100644 index 00000000000..635b4b77250 --- /dev/null +++ b/src/cloudflare/resources/dns/settings.py @@ -0,0 +1,311 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Optional, cast + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import ( + maybe_transform, + async_maybe_transform, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._wrappers import ResultWrapper +from ...types.dns import setting_edit_params +from ..._base_client import ( + make_request_options, +) +from ...types.dns.dns_setting_param import DNSSettingParam +from ...types.dns.setting_get_response import SettingGetResponse +from ...types.dns.setting_edit_response import SettingEditResponse + +__all__ = ["SettingsResource", "AsyncSettingsResource"] + + +class SettingsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> SettingsResourceWithRawResponse: + return SettingsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> SettingsResourceWithStreamingResponse: + return SettingsResourceWithStreamingResponse(self) + + def edit( + self, + *, + account_id: str | NotGiven = NOT_GIVEN, + zone_id: str | NotGiven = NOT_GIVEN, + zone_defaults: DNSSettingParam | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[SettingEditResponse]: + """ + Update DNS settings for an account or zone + + Args: + account_id: The Account ID to use for this endpoint. Mutually exclusive with the Zone ID. + + zone_id: The Zone ID to use for this endpoint. Mutually exclusive with the Account ID. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if account_id and zone_id: + raise ValueError("You cannot provide both account_id and zone_id") + + if account_id: + account_or_zone = "accounts" + account_or_zone_id = account_id + else: + if not zone_id: + raise ValueError("You must provide either account_id or zone_id") + + account_or_zone = "zones" + account_or_zone_id = zone_id + return self._patch( + f"/{account_or_zone}/{account_or_zone_id}/dns_settings", + body=maybe_transform({"zone_defaults": zone_defaults}, setting_edit_params.SettingEditParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[SettingEditResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[SettingEditResponse]], ResultWrapper[SettingEditResponse]), + ) + + def get( + self, + *, + account_id: str | NotGiven = NOT_GIVEN, + zone_id: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[SettingGetResponse]: + """ + Show DNS settings for an account or zone + + Args: + account_id: The Account ID to use for this endpoint. Mutually exclusive with the Zone ID. + + zone_id: The Zone ID to use for this endpoint. Mutually exclusive with the Account ID. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if account_id and zone_id: + raise ValueError("You cannot provide both account_id and zone_id") + + if account_id: + account_or_zone = "accounts" + account_or_zone_id = account_id + else: + if not zone_id: + raise ValueError("You must provide either account_id or zone_id") + + account_or_zone = "zones" + account_or_zone_id = zone_id + return self._get( + f"/{account_or_zone}/{account_or_zone_id}/dns_settings", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[SettingGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[SettingGetResponse]], ResultWrapper[SettingGetResponse]), + ) + + +class AsyncSettingsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncSettingsResourceWithRawResponse: + return AsyncSettingsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSettingsResourceWithStreamingResponse: + return AsyncSettingsResourceWithStreamingResponse(self) + + async def edit( + self, + *, + account_id: str | NotGiven = NOT_GIVEN, + zone_id: str | NotGiven = NOT_GIVEN, + zone_defaults: DNSSettingParam | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[SettingEditResponse]: + """ + Update DNS settings for an account or zone + + Args: + account_id: The Account ID to use for this endpoint. Mutually exclusive with the Zone ID. + + zone_id: The Zone ID to use for this endpoint. Mutually exclusive with the Account ID. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if account_id and zone_id: + raise ValueError("You cannot provide both account_id and zone_id") + + if account_id: + account_or_zone = "accounts" + account_or_zone_id = account_id + else: + if not zone_id: + raise ValueError("You must provide either account_id or zone_id") + + account_or_zone = "zones" + account_or_zone_id = zone_id + return await self._patch( + f"/{account_or_zone}/{account_or_zone_id}/dns_settings", + body=await async_maybe_transform({"zone_defaults": zone_defaults}, setting_edit_params.SettingEditParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[SettingEditResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[SettingEditResponse]], ResultWrapper[SettingEditResponse]), + ) + + async def get( + self, + *, + account_id: str | NotGiven = NOT_GIVEN, + zone_id: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[SettingGetResponse]: + """ + Show DNS settings for an account or zone + + Args: + account_id: The Account ID to use for this endpoint. Mutually exclusive with the Zone ID. + + zone_id: The Zone ID to use for this endpoint. Mutually exclusive with the Account ID. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if account_id and zone_id: + raise ValueError("You cannot provide both account_id and zone_id") + + if account_id: + account_or_zone = "accounts" + account_or_zone_id = account_id + else: + if not zone_id: + raise ValueError("You must provide either account_id or zone_id") + + account_or_zone = "zones" + account_or_zone_id = zone_id + return await self._get( + f"/{account_or_zone}/{account_or_zone_id}/dns_settings", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[SettingGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[SettingGetResponse]], ResultWrapper[SettingGetResponse]), + ) + + +class SettingsResourceWithRawResponse: + def __init__(self, settings: SettingsResource) -> None: + self._settings = settings + + self.edit = to_raw_response_wrapper( + settings.edit, + ) + self.get = to_raw_response_wrapper( + settings.get, + ) + + +class AsyncSettingsResourceWithRawResponse: + def __init__(self, settings: AsyncSettingsResource) -> None: + self._settings = settings + + self.edit = async_to_raw_response_wrapper( + settings.edit, + ) + self.get = async_to_raw_response_wrapper( + settings.get, + ) + + +class SettingsResourceWithStreamingResponse: + def __init__(self, settings: SettingsResource) -> None: + self._settings = settings + + self.edit = to_streamed_response_wrapper( + settings.edit, + ) + self.get = to_streamed_response_wrapper( + settings.get, + ) + + +class AsyncSettingsResourceWithStreamingResponse: + def __init__(self, settings: AsyncSettingsResource) -> None: + self._settings = settings + + self.edit = async_to_streamed_response_wrapper( + settings.edit, + ) + self.get = async_to_streamed_response_wrapper( + settings.get, + ) diff --git a/src/cloudflare/resources/zero_trust/access/__init__.py b/src/cloudflare/resources/zero_trust/access/__init__.py index b34af407a86..d3fe1996f9d 100644 --- a/src/cloudflare/resources/zero_trust/access/__init__.py +++ b/src/cloudflare/resources/zero_trust/access/__init__.py @@ -48,6 +48,14 @@ GroupsResourceWithStreamingResponse, AsyncGroupsResourceWithStreamingResponse, ) +from .policies import ( + PoliciesResource, + AsyncPoliciesResource, + PoliciesResourceWithRawResponse, + AsyncPoliciesResourceWithRawResponse, + PoliciesResourceWithStreamingResponse, + AsyncPoliciesResourceWithStreamingResponse, +) from .bookmarks import ( BookmarksResource, AsyncBookmarksResource, @@ -150,6 +158,12 @@ "AsyncTagsResourceWithRawResponse", "TagsResourceWithStreamingResponse", "AsyncTagsResourceWithStreamingResponse", + "PoliciesResource", + "AsyncPoliciesResource", + "PoliciesResourceWithRawResponse", + "AsyncPoliciesResourceWithRawResponse", + "PoliciesResourceWithStreamingResponse", + "AsyncPoliciesResourceWithStreamingResponse", "AccessResource", "AsyncAccessResource", "AccessResourceWithRawResponse", diff --git a/src/cloudflare/resources/zero_trust/access/access.py b/src/cloudflare/resources/zero_trust/access/access.py index 6707c0f7745..b0be13c5cb8 100644 --- a/src/cloudflare/resources/zero_trust/access/access.py +++ b/src/cloudflare/resources/zero_trust/access/access.py @@ -42,6 +42,14 @@ GroupsResourceWithStreamingResponse, AsyncGroupsResourceWithStreamingResponse, ) +from .policies import ( + PoliciesResource, + AsyncPoliciesResource, + PoliciesResourceWithRawResponse, + AsyncPoliciesResourceWithRawResponse, + PoliciesResourceWithStreamingResponse, + AsyncPoliciesResourceWithStreamingResponse, +) from .bookmarks import ( BookmarksResource, AsyncBookmarksResource, @@ -133,6 +141,10 @@ def custom_pages(self) -> CustomPagesResource: def tags(self) -> TagsResource: return TagsResource(self._client) + @cached_property + def policies(self) -> PoliciesResource: + return PoliciesResource(self._client) + @cached_property def with_raw_response(self) -> AccessResourceWithRawResponse: return AccessResourceWithRawResponse(self) @@ -183,6 +195,10 @@ def custom_pages(self) -> AsyncCustomPagesResource: def tags(self) -> AsyncTagsResource: return AsyncTagsResource(self._client) + @cached_property + def policies(self) -> AsyncPoliciesResource: + return AsyncPoliciesResource(self._client) + @cached_property def with_raw_response(self) -> AsyncAccessResourceWithRawResponse: return AsyncAccessResourceWithRawResponse(self) @@ -236,6 +252,10 @@ def custom_pages(self) -> CustomPagesResourceWithRawResponse: def tags(self) -> TagsResourceWithRawResponse: return TagsResourceWithRawResponse(self._access.tags) + @cached_property + def policies(self) -> PoliciesResourceWithRawResponse: + return PoliciesResourceWithRawResponse(self._access.policies) + class AsyncAccessResourceWithRawResponse: def __init__(self, access: AsyncAccessResource) -> None: @@ -281,6 +301,10 @@ def custom_pages(self) -> AsyncCustomPagesResourceWithRawResponse: def tags(self) -> AsyncTagsResourceWithRawResponse: return AsyncTagsResourceWithRawResponse(self._access.tags) + @cached_property + def policies(self) -> AsyncPoliciesResourceWithRawResponse: + return AsyncPoliciesResourceWithRawResponse(self._access.policies) + class AccessResourceWithStreamingResponse: def __init__(self, access: AccessResource) -> None: @@ -326,6 +350,10 @@ def custom_pages(self) -> CustomPagesResourceWithStreamingResponse: def tags(self) -> TagsResourceWithStreamingResponse: return TagsResourceWithStreamingResponse(self._access.tags) + @cached_property + def policies(self) -> PoliciesResourceWithStreamingResponse: + return PoliciesResourceWithStreamingResponse(self._access.policies) + class AsyncAccessResourceWithStreamingResponse: def __init__(self, access: AsyncAccessResource) -> None: @@ -370,3 +398,7 @@ def custom_pages(self) -> AsyncCustomPagesResourceWithStreamingResponse: @cached_property def tags(self) -> AsyncTagsResourceWithStreamingResponse: return AsyncTagsResourceWithStreamingResponse(self._access.tags) + + @cached_property + def policies(self) -> AsyncPoliciesResourceWithStreamingResponse: + return AsyncPoliciesResourceWithStreamingResponse(self._access.policies) diff --git a/src/cloudflare/resources/zero_trust/access/policies.py b/src/cloudflare/resources/zero_trust/access/policies.py new file mode 100644 index 00000000000..6cddea86c29 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/access/policies.py @@ -0,0 +1,784 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Iterable, Optional, cast + +import httpx + +from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ...._utils import ( + maybe_transform, + async_maybe_transform, +) +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._wrappers import ResultWrapper +from ....pagination import SyncSinglePage, AsyncSinglePage +from ...._base_client import ( + AsyncPaginator, + make_request_options, +) +from ....types.zero_trust.access import Decision, policy_create_params, policy_update_params +from ....types.zero_trust.access.decision import Decision +from ....types.zero_trust.access_rule_param import AccessRuleParam +from ....types.zero_trust.access.policy_get_response import PolicyGetResponse +from ....types.zero_trust.access.policy_list_response import PolicyListResponse +from ....types.zero_trust.access.policy_create_response import PolicyCreateResponse +from ....types.zero_trust.access.policy_delete_response import PolicyDeleteResponse +from ....types.zero_trust.access.policy_update_response import PolicyUpdateResponse +from ....types.zero_trust.access.applications.approval_group_param import ApprovalGroupParam + +__all__ = ["PoliciesResource", "AsyncPoliciesResource"] + + +class PoliciesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> PoliciesResourceWithRawResponse: + return PoliciesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PoliciesResourceWithStreamingResponse: + return PoliciesResourceWithStreamingResponse(self) + + def create( + self, + *, + account_id: str, + decision: Decision, + include: Iterable[AccessRuleParam], + name: str, + approval_groups: Iterable[ApprovalGroupParam] | NotGiven = NOT_GIVEN, + approval_required: bool | NotGiven = NOT_GIVEN, + exclude: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + isolation_required: bool | NotGiven = NOT_GIVEN, + purpose_justification_prompt: str | NotGiven = NOT_GIVEN, + purpose_justification_required: bool | NotGiven = NOT_GIVEN, + require: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + session_duration: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyCreateResponse]: + """ + Creates a new Access reusable policy. + + Args: + account_id: Identifier + + decision: The action Access will take if a user matches this policy. + + include: Rules evaluated with an OR logical operator. A user needs to meet only one of + the Include rules. + + name: The name of the Access policy. + + approval_groups: Administrators who can approve a temporary authentication request. + + approval_required: Requires the user to request access from an administrator at the start of each + session. + + exclude: Rules evaluated with a NOT logical operator. To match the policy, a user cannot + meet any of the Exclude rules. + + isolation_required: Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + + purpose_justification_prompt: A custom message that will appear on the purpose justification screen. + + purpose_justification_required: Require users to enter a justification when they log in to the application. + + require: Rules evaluated with an AND logical operator. To match the policy, a user must + meet all of the Require rules. + + session_duration: The amount of time that tokens issued for the application will be valid. Must be + in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), ms, s, + m, h. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._post( + f"/accounts/{account_id}/access/policies", + body=maybe_transform( + { + "decision": decision, + "include": include, + "name": name, + "approval_groups": approval_groups, + "approval_required": approval_required, + "exclude": exclude, + "isolation_required": isolation_required, + "purpose_justification_prompt": purpose_justification_prompt, + "purpose_justification_required": purpose_justification_required, + "require": require, + "session_duration": session_duration, + }, + policy_create_params.PolicyCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyCreateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyCreateResponse]], ResultWrapper[PolicyCreateResponse]), + ) + + def update( + self, + policy_id: str, + *, + account_id: str, + decision: Decision, + include: Iterable[AccessRuleParam], + name: str, + approval_groups: Iterable[ApprovalGroupParam] | NotGiven = NOT_GIVEN, + approval_required: bool | NotGiven = NOT_GIVEN, + exclude: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + isolation_required: bool | NotGiven = NOT_GIVEN, + purpose_justification_prompt: str | NotGiven = NOT_GIVEN, + purpose_justification_required: bool | NotGiven = NOT_GIVEN, + require: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + session_duration: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyUpdateResponse]: + """ + Updates a Access reusable policy. + + Args: + account_id: Identifier + + policy_id: The UUID of the policy + + decision: The action Access will take if a user matches this policy. + + include: Rules evaluated with an OR logical operator. A user needs to meet only one of + the Include rules. + + name: The name of the Access policy. + + approval_groups: Administrators who can approve a temporary authentication request. + + approval_required: Requires the user to request access from an administrator at the start of each + session. + + exclude: Rules evaluated with a NOT logical operator. To match the policy, a user cannot + meet any of the Exclude rules. + + isolation_required: Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + + purpose_justification_prompt: A custom message that will appear on the purpose justification screen. + + purpose_justification_required: Require users to enter a justification when they log in to the application. + + require: Rules evaluated with an AND logical operator. To match the policy, a user must + meet all of the Require rules. + + session_duration: The amount of time that tokens issued for the application will be valid. Must be + in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), ms, s, + m, h. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not policy_id: + raise ValueError(f"Expected a non-empty value for `policy_id` but received {policy_id!r}") + return self._put( + f"/accounts/{account_id}/access/policies/{policy_id}", + body=maybe_transform( + { + "decision": decision, + "include": include, + "name": name, + "approval_groups": approval_groups, + "approval_required": approval_required, + "exclude": exclude, + "isolation_required": isolation_required, + "purpose_justification_prompt": purpose_justification_prompt, + "purpose_justification_required": purpose_justification_required, + "require": require, + "session_duration": session_duration, + }, + policy_update_params.PolicyUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyUpdateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyUpdateResponse]], ResultWrapper[PolicyUpdateResponse]), + ) + + def list( + self, + *, + account_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> SyncSinglePage[PolicyListResponse]: + """ + Lists Access reusable policies. + + Args: + account_id: Identifier + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get_api_list( + f"/accounts/{account_id}/access/policies", + page=SyncSinglePage[PolicyListResponse], + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + model=PolicyListResponse, + ) + + def delete( + self, + policy_id: str, + *, + account_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyDeleteResponse]: + """ + Deletes an Access reusable policy. + + Args: + account_id: Identifier + + policy_id: The UUID of the policy + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not policy_id: + raise ValueError(f"Expected a non-empty value for `policy_id` but received {policy_id!r}") + return self._delete( + f"/accounts/{account_id}/access/policies/{policy_id}", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyDeleteResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyDeleteResponse]], ResultWrapper[PolicyDeleteResponse]), + ) + + def get( + self, + policy_id: str, + *, + account_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyGetResponse]: + """ + Fetches a single Access reusable policy. + + Args: + account_id: Identifier + + policy_id: The UUID of the policy + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not policy_id: + raise ValueError(f"Expected a non-empty value for `policy_id` but received {policy_id!r}") + return self._get( + f"/accounts/{account_id}/access/policies/{policy_id}", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyGetResponse]], ResultWrapper[PolicyGetResponse]), + ) + + +class AsyncPoliciesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncPoliciesResourceWithRawResponse: + return AsyncPoliciesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPoliciesResourceWithStreamingResponse: + return AsyncPoliciesResourceWithStreamingResponse(self) + + async def create( + self, + *, + account_id: str, + decision: Decision, + include: Iterable[AccessRuleParam], + name: str, + approval_groups: Iterable[ApprovalGroupParam] | NotGiven = NOT_GIVEN, + approval_required: bool | NotGiven = NOT_GIVEN, + exclude: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + isolation_required: bool | NotGiven = NOT_GIVEN, + purpose_justification_prompt: str | NotGiven = NOT_GIVEN, + purpose_justification_required: bool | NotGiven = NOT_GIVEN, + require: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + session_duration: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyCreateResponse]: + """ + Creates a new Access reusable policy. + + Args: + account_id: Identifier + + decision: The action Access will take if a user matches this policy. + + include: Rules evaluated with an OR logical operator. A user needs to meet only one of + the Include rules. + + name: The name of the Access policy. + + approval_groups: Administrators who can approve a temporary authentication request. + + approval_required: Requires the user to request access from an administrator at the start of each + session. + + exclude: Rules evaluated with a NOT logical operator. To match the policy, a user cannot + meet any of the Exclude rules. + + isolation_required: Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + + purpose_justification_prompt: A custom message that will appear on the purpose justification screen. + + purpose_justification_required: Require users to enter a justification when they log in to the application. + + require: Rules evaluated with an AND logical operator. To match the policy, a user must + meet all of the Require rules. + + session_duration: The amount of time that tokens issued for the application will be valid. Must be + in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), ms, s, + m, h. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return await self._post( + f"/accounts/{account_id}/access/policies", + body=await async_maybe_transform( + { + "decision": decision, + "include": include, + "name": name, + "approval_groups": approval_groups, + "approval_required": approval_required, + "exclude": exclude, + "isolation_required": isolation_required, + "purpose_justification_prompt": purpose_justification_prompt, + "purpose_justification_required": purpose_justification_required, + "require": require, + "session_duration": session_duration, + }, + policy_create_params.PolicyCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyCreateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyCreateResponse]], ResultWrapper[PolicyCreateResponse]), + ) + + async def update( + self, + policy_id: str, + *, + account_id: str, + decision: Decision, + include: Iterable[AccessRuleParam], + name: str, + approval_groups: Iterable[ApprovalGroupParam] | NotGiven = NOT_GIVEN, + approval_required: bool | NotGiven = NOT_GIVEN, + exclude: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + isolation_required: bool | NotGiven = NOT_GIVEN, + purpose_justification_prompt: str | NotGiven = NOT_GIVEN, + purpose_justification_required: bool | NotGiven = NOT_GIVEN, + require: Iterable[AccessRuleParam] | NotGiven = NOT_GIVEN, + session_duration: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyUpdateResponse]: + """ + Updates a Access reusable policy. + + Args: + account_id: Identifier + + policy_id: The UUID of the policy + + decision: The action Access will take if a user matches this policy. + + include: Rules evaluated with an OR logical operator. A user needs to meet only one of + the Include rules. + + name: The name of the Access policy. + + approval_groups: Administrators who can approve a temporary authentication request. + + approval_required: Requires the user to request access from an administrator at the start of each + session. + + exclude: Rules evaluated with a NOT logical operator. To match the policy, a user cannot + meet any of the Exclude rules. + + isolation_required: Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + + purpose_justification_prompt: A custom message that will appear on the purpose justification screen. + + purpose_justification_required: Require users to enter a justification when they log in to the application. + + require: Rules evaluated with an AND logical operator. To match the policy, a user must + meet all of the Require rules. + + session_duration: The amount of time that tokens issued for the application will be valid. Must be + in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), ms, s, + m, h. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not policy_id: + raise ValueError(f"Expected a non-empty value for `policy_id` but received {policy_id!r}") + return await self._put( + f"/accounts/{account_id}/access/policies/{policy_id}", + body=await async_maybe_transform( + { + "decision": decision, + "include": include, + "name": name, + "approval_groups": approval_groups, + "approval_required": approval_required, + "exclude": exclude, + "isolation_required": isolation_required, + "purpose_justification_prompt": purpose_justification_prompt, + "purpose_justification_required": purpose_justification_required, + "require": require, + "session_duration": session_duration, + }, + policy_update_params.PolicyUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyUpdateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyUpdateResponse]], ResultWrapper[PolicyUpdateResponse]), + ) + + def list( + self, + *, + account_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> AsyncPaginator[PolicyListResponse, AsyncSinglePage[PolicyListResponse]]: + """ + Lists Access reusable policies. + + Args: + account_id: Identifier + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get_api_list( + f"/accounts/{account_id}/access/policies", + page=AsyncSinglePage[PolicyListResponse], + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + model=PolicyListResponse, + ) + + async def delete( + self, + policy_id: str, + *, + account_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyDeleteResponse]: + """ + Deletes an Access reusable policy. + + Args: + account_id: Identifier + + policy_id: The UUID of the policy + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not policy_id: + raise ValueError(f"Expected a non-empty value for `policy_id` but received {policy_id!r}") + return await self._delete( + f"/accounts/{account_id}/access/policies/{policy_id}", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyDeleteResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyDeleteResponse]], ResultWrapper[PolicyDeleteResponse]), + ) + + async def get( + self, + policy_id: str, + *, + account_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> Optional[PolicyGetResponse]: + """ + Fetches a single Access reusable policy. + + Args: + account_id: Identifier + + policy_id: The UUID of the policy + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not policy_id: + raise ValueError(f"Expected a non-empty value for `policy_id` but received {policy_id!r}") + return await self._get( + f"/accounts/{account_id}/access/policies/{policy_id}", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[PolicyGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[PolicyGetResponse]], ResultWrapper[PolicyGetResponse]), + ) + + +class PoliciesResourceWithRawResponse: + def __init__(self, policies: PoliciesResource) -> None: + self._policies = policies + + self.create = to_raw_response_wrapper( + policies.create, + ) + self.update = to_raw_response_wrapper( + policies.update, + ) + self.list = to_raw_response_wrapper( + policies.list, + ) + self.delete = to_raw_response_wrapper( + policies.delete, + ) + self.get = to_raw_response_wrapper( + policies.get, + ) + + +class AsyncPoliciesResourceWithRawResponse: + def __init__(self, policies: AsyncPoliciesResource) -> None: + self._policies = policies + + self.create = async_to_raw_response_wrapper( + policies.create, + ) + self.update = async_to_raw_response_wrapper( + policies.update, + ) + self.list = async_to_raw_response_wrapper( + policies.list, + ) + self.delete = async_to_raw_response_wrapper( + policies.delete, + ) + self.get = async_to_raw_response_wrapper( + policies.get, + ) + + +class PoliciesResourceWithStreamingResponse: + def __init__(self, policies: PoliciesResource) -> None: + self._policies = policies + + self.create = to_streamed_response_wrapper( + policies.create, + ) + self.update = to_streamed_response_wrapper( + policies.update, + ) + self.list = to_streamed_response_wrapper( + policies.list, + ) + self.delete = to_streamed_response_wrapper( + policies.delete, + ) + self.get = to_streamed_response_wrapper( + policies.get, + ) + + +class AsyncPoliciesResourceWithStreamingResponse: + def __init__(self, policies: AsyncPoliciesResource) -> None: + self._policies = policies + + self.create = async_to_streamed_response_wrapper( + policies.create, + ) + self.update = async_to_streamed_response_wrapper( + policies.update, + ) + self.list = async_to_streamed_response_wrapper( + policies.list, + ) + self.delete = async_to_streamed_response_wrapper( + policies.delete, + ) + self.get = async_to_streamed_response_wrapper( + policies.get, + ) diff --git a/src/cloudflare/types/dns/__init__.py b/src/cloudflare/types/dns/__init__.py index 5966582d8bf..3b3aa6dfb0b 100644 --- a/src/cloudflare/types/dns/__init__.py +++ b/src/cloudflare/types/dns/__init__.py @@ -12,12 +12,14 @@ from .ttl_param import TTLParam as TTLParam from .caa_record import CAARecord as CAARecord from .loc_record import LOCRecord as LOCRecord +from .nameserver import Nameserver as Nameserver from .ptr_record import PTRRecord as PTRRecord from .srv_record import SRVRecord as SRVRecord from .txt_record import TXTRecord as TXTRecord from .uri_record import URIRecord as URIRecord from .aaaa_record import AAAARecord as AAAARecord from .cert_record import CERTRecord as CERTRecord +from .dns_setting import DNSSetting as DNSSetting from .record_tags import RecordTags as RecordTags from .svcb_record import SVCBRecord as SVCBRecord from .tlsa_record import TLSARecord as TLSARecord @@ -30,20 +32,25 @@ from .dnskey_record import DNSKEYRecord as DNSKEYRecord from .smimea_record import SMIMEARecord as SMIMEARecord from .record_metadata import RecordMetadata as RecordMetadata +from .nameserver_param import NameserverParam as NameserverParam from .attack_mitigation import AttackMitigation as AttackMitigation +from .dns_setting_param import DNSSettingParam as DNSSettingParam from .firewall_ips_param import FirewallIPsParam as FirewallIPsParam from .record_edit_params import RecordEditParams as RecordEditParams from .record_list_params import RecordListParams as RecordListParams from .record_scan_params import RecordScanParams as RecordScanParams from .upstream_ips_param import UpstreamIPsParam as UpstreamIPsParam from .dns_analytics_query import DNSAnalyticsQuery as DNSAnalyticsQuery +from .setting_edit_params import SettingEditParams as SettingEditParams from .firewall_edit_params import FirewallEditParams as FirewallEditParams from .firewall_list_params import FirewallListParams as FirewallListParams from .record_create_params import RecordCreateParams as RecordCreateParams from .record_import_params import RecordImportParams as RecordImportParams from .record_scan_response import RecordScanResponse as RecordScanResponse from .record_update_params import RecordUpdateParams as RecordUpdateParams +from .setting_get_response import SettingGetResponse as SettingGetResponse from .record_process_timing import RecordProcessTiming as RecordProcessTiming +from .setting_edit_response import SettingEditResponse as SettingEditResponse from .firewall_create_params import FirewallCreateParams as FirewallCreateParams from .record_delete_response import RecordDeleteResponse as RecordDeleteResponse from .record_export_response import RecordExportResponse as RecordExportResponse diff --git a/src/cloudflare/types/dns/dns_setting.py b/src/cloudflare/types/dns/dns_setting.py new file mode 100644 index 00000000000..c96b14afb67 --- /dev/null +++ b/src/cloudflare/types/dns/dns_setting.py @@ -0,0 +1,76 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .nameserver import Nameserver + +__all__ = ["DNSSetting", "SOA"] + + +class SOA(BaseModel): + expire: float + """ + Time in seconds of being unable to query the primary server after which + secondary servers should stop serving the zone. + """ + + min_ttl: float + """The time to live (TTL) for negative caching of records within the zone.""" + + mname: str + """The primary nameserver, which may be used for outbound zone transfers.""" + + refresh: float + """ + Time in seconds after which secondary servers should re-check the SOA record to + see if the zone has been updated. + """ + + retry: float + """ + Time in seconds after which secondary servers should retry queries after the + primary server was unresponsive. + """ + + rname: str + """ + The email address of the zone administrator, with the first label representing + the local part of the email address. + """ + + ttl: float + """The time to live (TTL) of the SOA record itself.""" + + +class DNSSetting(BaseModel): + foundation_dns: Optional[bool] = None + """Whether to enable Foundation DNS Advanced Nameservers on the zone.""" + + multi_provider: Optional[bool] = None + """ + Whether to enable multi-provider DNS, which causes Cloudflare to activate the + zone even when non-Cloudflare NS records exist, and to respect NS records at the + zone apex during outbound zone transfers. + """ + + nameservers: Optional[Nameserver] = None + """ + Settings determining the nameservers through which the zone should be available. + """ + + ns_ttl: Optional[float] = None + """The time to live (TTL) of the zone's nameserver (NS) records.""" + + secondary_overrides: Optional[bool] = None + """ + Allows a Secondary DNS zone to use (proxied) override records and CNAME + flattening at the zone apex. + """ + + soa: Optional[SOA] = None + """Components of the zone's SOA record.""" + + zone_mode: Optional[Literal["standard", "cdn_only", "dns_only"]] = None + """Whether the zone mode is a regular or CDN/DNS only zone.""" diff --git a/src/cloudflare/types/dns/dns_setting_param.py b/src/cloudflare/types/dns/dns_setting_param.py new file mode 100644 index 00000000000..127be3c6a83 --- /dev/null +++ b/src/cloudflare/types/dns/dns_setting_param.py @@ -0,0 +1,76 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +from .nameserver_param import NameserverParam + +__all__ = ["DNSSettingParam", "SOA"] + + +class SOA(TypedDict, total=False): + expire: Required[float] + """ + Time in seconds of being unable to query the primary server after which + secondary servers should stop serving the zone. + """ + + min_ttl: Required[float] + """The time to live (TTL) for negative caching of records within the zone.""" + + mname: Required[str] + """The primary nameserver, which may be used for outbound zone transfers.""" + + refresh: Required[float] + """ + Time in seconds after which secondary servers should re-check the SOA record to + see if the zone has been updated. + """ + + retry: Required[float] + """ + Time in seconds after which secondary servers should retry queries after the + primary server was unresponsive. + """ + + rname: Required[str] + """ + The email address of the zone administrator, with the first label representing + the local part of the email address. + """ + + ttl: Required[float] + """The time to live (TTL) of the SOA record itself.""" + + +class DNSSettingParam(TypedDict, total=False): + foundation_dns: bool + """Whether to enable Foundation DNS Advanced Nameservers on the zone.""" + + multi_provider: bool + """ + Whether to enable multi-provider DNS, which causes Cloudflare to activate the + zone even when non-Cloudflare NS records exist, and to respect NS records at the + zone apex during outbound zone transfers. + """ + + nameservers: NameserverParam + """ + Settings determining the nameservers through which the zone should be available. + """ + + ns_ttl: float + """The time to live (TTL) of the zone's nameserver (NS) records.""" + + secondary_overrides: bool + """ + Allows a Secondary DNS zone to use (proxied) override records and CNAME + flattening at the zone apex. + """ + + soa: SOA + """Components of the zone's SOA record.""" + + zone_mode: Literal["standard", "cdn_only", "dns_only"] + """Whether the zone mode is a regular or CDN/DNS only zone.""" diff --git a/src/cloudflare/types/dns/nameserver.py b/src/cloudflare/types/dns/nameserver.py new file mode 100644 index 00000000000..3076da16fbd --- /dev/null +++ b/src/cloudflare/types/dns/nameserver.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["Nameserver"] + + +class Nameserver(BaseModel): + type: Literal["cloudflare.standard"] + """Nameserver type""" diff --git a/src/cloudflare/types/dns/nameserver_param.py b/src/cloudflare/types/dns/nameserver_param.py new file mode 100644 index 00000000000..6d73075a2ae --- /dev/null +++ b/src/cloudflare/types/dns/nameserver_param.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["NameserverParam"] + + +class NameserverParam(TypedDict, total=False): + type: Required[Literal["cloudflare.standard"]] + """Nameserver type""" diff --git a/src/cloudflare/types/dns/setting_edit_params.py b/src/cloudflare/types/dns/setting_edit_params.py new file mode 100644 index 00000000000..1ac1ba3eeae --- /dev/null +++ b/src/cloudflare/types/dns/setting_edit_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +from .dns_setting_param import DNSSettingParam + +__all__ = ["SettingEditParams"] + + +class SettingEditParams(TypedDict, total=False): + account_id: str + """The Account ID to use for this endpoint. Mutually exclusive with the Zone ID.""" + + zone_id: str + """The Zone ID to use for this endpoint. Mutually exclusive with the Account ID.""" + + zone_defaults: DNSSettingParam diff --git a/src/cloudflare/types/dns/setting_edit_response.py b/src/cloudflare/types/dns/setting_edit_response.py new file mode 100644 index 00000000000..87a73a5356f --- /dev/null +++ b/src/cloudflare/types/dns/setting_edit_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel +from .dns_setting import DNSSetting + +__all__ = ["SettingEditResponse"] + + +class SettingEditResponse(BaseModel): + zone_defaults: Optional[DNSSetting] = None diff --git a/src/cloudflare/types/dns/setting_get_response.py b/src/cloudflare/types/dns/setting_get_response.py new file mode 100644 index 00000000000..42c33600842 --- /dev/null +++ b/src/cloudflare/types/dns/setting_get_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel +from .dns_setting import DNSSetting + +__all__ = ["SettingGetResponse"] + + +class SettingGetResponse(BaseModel): + zone_defaults: Optional[DNSSetting] = None diff --git a/src/cloudflare/types/zero_trust/access/__init__.py b/src/cloudflare/types/zero_trust/access/__init__.py index 8b8d5c829cf..16436e0e937 100644 --- a/src/cloudflare/types/zero_trust/access/__init__.py +++ b/src/cloudflare/types/zero_trust/access/__init__.py @@ -28,15 +28,22 @@ from .group_update_params import GroupUpdateParams as GroupUpdateParams from .key_rotate_response import KeyRotateResponse as KeyRotateResponse from .key_update_response import KeyUpdateResponse as KeyUpdateResponse +from .policy_get_response import PolicyGetResponse as PolicyGetResponse from .saml_saas_app_param import SAMLSaaSAppParam as SAMLSaaSAppParam from .self_hosted_domains import SelfHostedDomains as SelfHostedDomains from .tag_delete_response import TagDeleteResponse as TagDeleteResponse from .associated_hostnames import AssociatedHostnames as AssociatedHostnames +from .policy_create_params import PolicyCreateParams as PolicyCreateParams +from .policy_list_response import PolicyListResponse as PolicyListResponse +from .policy_update_params import PolicyUpdateParams as PolicyUpdateParams from .saas_app_name_format import SaaSAppNameFormat as SaaSAppNameFormat from .group_delete_response import GroupDeleteResponse as GroupDeleteResponse from .saas_app_source_param import SaaSAppSourceParam as SaaSAppSourceParam from .bookmark_create_params import BookmarkCreateParams as BookmarkCreateParams from .bookmark_update_params import BookmarkUpdateParams as BookmarkUpdateParams +from .policy_create_response import PolicyCreateResponse as PolicyCreateResponse +from .policy_delete_response import PolicyDeleteResponse as PolicyDeleteResponse +from .policy_update_response import PolicyUpdateResponse as PolicyUpdateResponse from .saas_app_name_id_format import SaaSAppNameIDFormat as SaaSAppNameIDFormat from .application_get_response import ApplicationGetResponse as ApplicationGetResponse from .bookmark_delete_response import BookmarkDeleteResponse as BookmarkDeleteResponse diff --git a/src/cloudflare/types/zero_trust/access/policy_create_params.py b/src/cloudflare/types/zero_trust/access/policy_create_params.py new file mode 100644 index 00000000000..a575b5e16a6 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_create_params.py @@ -0,0 +1,70 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Required, TypedDict + +from .decision import Decision +from ..access_rule_param import AccessRuleParam +from .applications.approval_group_param import ApprovalGroupParam + +__all__ = ["PolicyCreateParams"] + + +class PolicyCreateParams(TypedDict, total=False): + account_id: Required[str] + """Identifier""" + + decision: Required[Decision] + """The action Access will take if a user matches this policy.""" + + include: Required[Iterable[AccessRuleParam]] + """Rules evaluated with an OR logical operator. + + A user needs to meet only one of the Include rules. + """ + + name: Required[str] + """The name of the Access policy.""" + + approval_groups: Iterable[ApprovalGroupParam] + """Administrators who can approve a temporary authentication request.""" + + approval_required: bool + """ + Requires the user to request access from an administrator at the start of each + session. + """ + + exclude: Iterable[AccessRuleParam] + """Rules evaluated with a NOT logical operator. + + To match the policy, a user cannot meet any of the Exclude rules. + """ + + isolation_required: bool + """ + Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + """ + + purpose_justification_prompt: str + """A custom message that will appear on the purpose justification screen.""" + + purpose_justification_required: bool + """Require users to enter a justification when they log in to the application.""" + + require: Iterable[AccessRuleParam] + """Rules evaluated with an AND logical operator. + + To match the policy, a user must meet all of the Require rules. + """ + + session_duration: str + """The amount of time that tokens issued for the application will be valid. + + Must be in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), + ms, s, m, h. + """ diff --git a/src/cloudflare/types/zero_trust/access/policy_create_response.py b/src/cloudflare/types/zero_trust/access/policy_create_response.py new file mode 100644 index 00000000000..767b4f9bc18 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_create_response.py @@ -0,0 +1,79 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .decision import Decision +from ...._models import BaseModel +from ..access_rule import AccessRule +from .applications.approval_group import ApprovalGroup + +__all__ = ["PolicyCreateResponse"] + + +class PolicyCreateResponse(BaseModel): + id: Optional[str] = None + """The UUID of the policy""" + + app_count: Optional[int] = None + """Number of access applications currently using this policy.""" + + approval_groups: Optional[List[ApprovalGroup]] = None + """Administrators who can approve a temporary authentication request.""" + + approval_required: Optional[bool] = None + """ + Requires the user to request access from an administrator at the start of each + session. + """ + + created_at: Optional[datetime] = None + + decision: Optional[Decision] = None + """The action Access will take if a user matches this policy.""" + + exclude: Optional[List[AccessRule]] = None + """Rules evaluated with a NOT logical operator. + + To match the policy, a user cannot meet any of the Exclude rules. + """ + + include: Optional[List[AccessRule]] = None + """Rules evaluated with an OR logical operator. + + A user needs to meet only one of the Include rules. + """ + + isolation_required: Optional[bool] = None + """ + Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + """ + + name: Optional[str] = None + """The name of the Access policy.""" + + purpose_justification_prompt: Optional[str] = None + """A custom message that will appear on the purpose justification screen.""" + + purpose_justification_required: Optional[bool] = None + """Require users to enter a justification when they log in to the application.""" + + require: Optional[List[AccessRule]] = None + """Rules evaluated with an AND logical operator. + + To match the policy, a user must meet all of the Require rules. + """ + + reusable: Optional[Literal[True]] = None + + session_duration: Optional[str] = None + """The amount of time that tokens issued for the application will be valid. + + Must be in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), + ms, s, m, h. + """ + + updated_at: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/policy_delete_response.py b/src/cloudflare/types/zero_trust/access/policy_delete_response.py new file mode 100644 index 00000000000..638056e64fd --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_delete_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ...._models import BaseModel + +__all__ = ["PolicyDeleteResponse"] + + +class PolicyDeleteResponse(BaseModel): + id: Optional[str] = None + """The UUID of the policy""" diff --git a/src/cloudflare/types/zero_trust/access/policy_get_response.py b/src/cloudflare/types/zero_trust/access/policy_get_response.py new file mode 100644 index 00000000000..b4476baf1d0 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_get_response.py @@ -0,0 +1,79 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .decision import Decision +from ...._models import BaseModel +from ..access_rule import AccessRule +from .applications.approval_group import ApprovalGroup + +__all__ = ["PolicyGetResponse"] + + +class PolicyGetResponse(BaseModel): + id: Optional[str] = None + """The UUID of the policy""" + + app_count: Optional[int] = None + """Number of access applications currently using this policy.""" + + approval_groups: Optional[List[ApprovalGroup]] = None + """Administrators who can approve a temporary authentication request.""" + + approval_required: Optional[bool] = None + """ + Requires the user to request access from an administrator at the start of each + session. + """ + + created_at: Optional[datetime] = None + + decision: Optional[Decision] = None + """The action Access will take if a user matches this policy.""" + + exclude: Optional[List[AccessRule]] = None + """Rules evaluated with a NOT logical operator. + + To match the policy, a user cannot meet any of the Exclude rules. + """ + + include: Optional[List[AccessRule]] = None + """Rules evaluated with an OR logical operator. + + A user needs to meet only one of the Include rules. + """ + + isolation_required: Optional[bool] = None + """ + Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + """ + + name: Optional[str] = None + """The name of the Access policy.""" + + purpose_justification_prompt: Optional[str] = None + """A custom message that will appear on the purpose justification screen.""" + + purpose_justification_required: Optional[bool] = None + """Require users to enter a justification when they log in to the application.""" + + require: Optional[List[AccessRule]] = None + """Rules evaluated with an AND logical operator. + + To match the policy, a user must meet all of the Require rules. + """ + + reusable: Optional[Literal[True]] = None + + session_duration: Optional[str] = None + """The amount of time that tokens issued for the application will be valid. + + Must be in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), + ms, s, m, h. + """ + + updated_at: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/policy_list_response.py b/src/cloudflare/types/zero_trust/access/policy_list_response.py new file mode 100644 index 00000000000..2a2272663c7 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_list_response.py @@ -0,0 +1,79 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .decision import Decision +from ...._models import BaseModel +from ..access_rule import AccessRule +from .applications.approval_group import ApprovalGroup + +__all__ = ["PolicyListResponse"] + + +class PolicyListResponse(BaseModel): + id: Optional[str] = None + """The UUID of the policy""" + + app_count: Optional[int] = None + """Number of access applications currently using this policy.""" + + approval_groups: Optional[List[ApprovalGroup]] = None + """Administrators who can approve a temporary authentication request.""" + + approval_required: Optional[bool] = None + """ + Requires the user to request access from an administrator at the start of each + session. + """ + + created_at: Optional[datetime] = None + + decision: Optional[Decision] = None + """The action Access will take if a user matches this policy.""" + + exclude: Optional[List[AccessRule]] = None + """Rules evaluated with a NOT logical operator. + + To match the policy, a user cannot meet any of the Exclude rules. + """ + + include: Optional[List[AccessRule]] = None + """Rules evaluated with an OR logical operator. + + A user needs to meet only one of the Include rules. + """ + + isolation_required: Optional[bool] = None + """ + Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + """ + + name: Optional[str] = None + """The name of the Access policy.""" + + purpose_justification_prompt: Optional[str] = None + """A custom message that will appear on the purpose justification screen.""" + + purpose_justification_required: Optional[bool] = None + """Require users to enter a justification when they log in to the application.""" + + require: Optional[List[AccessRule]] = None + """Rules evaluated with an AND logical operator. + + To match the policy, a user must meet all of the Require rules. + """ + + reusable: Optional[Literal[True]] = None + + session_duration: Optional[str] = None + """The amount of time that tokens issued for the application will be valid. + + Must be in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), + ms, s, m, h. + """ + + updated_at: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/policy_update_params.py b/src/cloudflare/types/zero_trust/access/policy_update_params.py new file mode 100644 index 00000000000..7ac64eebe4c --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_update_params.py @@ -0,0 +1,70 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Required, TypedDict + +from .decision import Decision +from ..access_rule_param import AccessRuleParam +from .applications.approval_group_param import ApprovalGroupParam + +__all__ = ["PolicyUpdateParams"] + + +class PolicyUpdateParams(TypedDict, total=False): + account_id: Required[str] + """Identifier""" + + decision: Required[Decision] + """The action Access will take if a user matches this policy.""" + + include: Required[Iterable[AccessRuleParam]] + """Rules evaluated with an OR logical operator. + + A user needs to meet only one of the Include rules. + """ + + name: Required[str] + """The name of the Access policy.""" + + approval_groups: Iterable[ApprovalGroupParam] + """Administrators who can approve a temporary authentication request.""" + + approval_required: bool + """ + Requires the user to request access from an administrator at the start of each + session. + """ + + exclude: Iterable[AccessRuleParam] + """Rules evaluated with a NOT logical operator. + + To match the policy, a user cannot meet any of the Exclude rules. + """ + + isolation_required: bool + """ + Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + """ + + purpose_justification_prompt: str + """A custom message that will appear on the purpose justification screen.""" + + purpose_justification_required: bool + """Require users to enter a justification when they log in to the application.""" + + require: Iterable[AccessRuleParam] + """Rules evaluated with an AND logical operator. + + To match the policy, a user must meet all of the Require rules. + """ + + session_duration: str + """The amount of time that tokens issued for the application will be valid. + + Must be in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), + ms, s, m, h. + """ diff --git a/src/cloudflare/types/zero_trust/access/policy_update_response.py b/src/cloudflare/types/zero_trust/access/policy_update_response.py new file mode 100644 index 00000000000..8582785d404 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/policy_update_response.py @@ -0,0 +1,79 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .decision import Decision +from ...._models import BaseModel +from ..access_rule import AccessRule +from .applications.approval_group import ApprovalGroup + +__all__ = ["PolicyUpdateResponse"] + + +class PolicyUpdateResponse(BaseModel): + id: Optional[str] = None + """The UUID of the policy""" + + app_count: Optional[int] = None + """Number of access applications currently using this policy.""" + + approval_groups: Optional[List[ApprovalGroup]] = None + """Administrators who can approve a temporary authentication request.""" + + approval_required: Optional[bool] = None + """ + Requires the user to request access from an administrator at the start of each + session. + """ + + created_at: Optional[datetime] = None + + decision: Optional[Decision] = None + """The action Access will take if a user matches this policy.""" + + exclude: Optional[List[AccessRule]] = None + """Rules evaluated with a NOT logical operator. + + To match the policy, a user cannot meet any of the Exclude rules. + """ + + include: Optional[List[AccessRule]] = None + """Rules evaluated with an OR logical operator. + + A user needs to meet only one of the Include rules. + """ + + isolation_required: Optional[bool] = None + """ + Require this application to be served in an isolated browser for users matching + this policy. 'Client Web Isolation' must be on for the account in order to use + this feature. + """ + + name: Optional[str] = None + """The name of the Access policy.""" + + purpose_justification_prompt: Optional[str] = None + """A custom message that will appear on the purpose justification screen.""" + + purpose_justification_required: Optional[bool] = None + """Require users to enter a justification when they log in to the application.""" + + require: Optional[List[AccessRule]] = None + """Rules evaluated with an AND logical operator. + + To match the policy, a user must meet all of the Require rules. + """ + + reusable: Optional[Literal[True]] = None + + session_duration: Optional[str] = None + """The amount of time that tokens issued for the application will be valid. + + Must be in the format `300ms` or `2h45m`. Valid time units are: ns, us (or µs), + ms, s, m, h. + """ + + updated_at: Optional[datetime] = None diff --git a/tests/api_resources/dns/test_settings.py b/tests/api_resources/dns/test_settings.py new file mode 100644 index 00000000000..955b284427b --- /dev/null +++ b/tests/api_resources/dns/test_settings.py @@ -0,0 +1,256 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.types.dns import SettingGetResponse, SettingEditResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestSettings: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_edit(self, client: Cloudflare) -> None: + setting = client.dns.settings.edit( + account_id="string", + ) + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + @parametrize + def test_method_edit_with_all_params(self, client: Cloudflare) -> None: + setting = client.dns.settings.edit( + account_id="string", + zone_defaults={ + "foundation_dns": False, + "multi_provider": False, + "nameservers": {"type": "cloudflare.standard"}, + "ns_ttl": 86400, + "secondary_overrides": False, + "soa": { + "expire": 604800, + "min_ttl": 1800, + "mname": "kristina.ns.cloudflare.com", + "refresh": 10000, + "retry": 2400, + "rname": "admin.example.com", + "ttl": 3600, + }, + "zone_mode": "dns_only", + }, + ) + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + @parametrize + def test_raw_response_edit(self, client: Cloudflare) -> None: + response = client.dns.settings.with_raw_response.edit( + account_id="string", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + setting = response.parse() + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + @parametrize + def test_streaming_response_edit(self, client: Cloudflare) -> None: + with client.dns.settings.with_streaming_response.edit( + account_id="string", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + setting = response.parse() + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_edit(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.dns.settings.with_raw_response.edit( + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + client.dns.settings.with_raw_response.edit( + account_id="string", + ) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + setting = client.dns.settings.get( + account_id="string", + ) + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + @parametrize + def test_method_get_with_all_params(self, client: Cloudflare) -> None: + setting = client.dns.settings.get( + account_id="string", + ) + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.dns.settings.with_raw_response.get( + account_id="string", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + setting = response.parse() + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.dns.settings.with_streaming_response.get( + account_id="string", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + setting = response.parse() + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.dns.settings.with_raw_response.get( + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + client.dns.settings.with_raw_response.get( + account_id="string", + ) + + +class TestAsyncSettings: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_edit(self, async_client: AsyncCloudflare) -> None: + setting = await async_client.dns.settings.edit( + account_id="string", + ) + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + @parametrize + async def test_method_edit_with_all_params(self, async_client: AsyncCloudflare) -> None: + setting = await async_client.dns.settings.edit( + account_id="string", + zone_defaults={ + "foundation_dns": False, + "multi_provider": False, + "nameservers": {"type": "cloudflare.standard"}, + "ns_ttl": 86400, + "secondary_overrides": False, + "soa": { + "expire": 604800, + "min_ttl": 1800, + "mname": "kristina.ns.cloudflare.com", + "refresh": 10000, + "retry": 2400, + "rname": "admin.example.com", + "ttl": 3600, + }, + "zone_mode": "dns_only", + }, + ) + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + @parametrize + async def test_raw_response_edit(self, async_client: AsyncCloudflare) -> None: + response = await async_client.dns.settings.with_raw_response.edit( + account_id="string", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + setting = await response.parse() + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + @parametrize + async def test_streaming_response_edit(self, async_client: AsyncCloudflare) -> None: + async with async_client.dns.settings.with_streaming_response.edit( + account_id="string", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + setting = await response.parse() + assert_matches_type(Optional[SettingEditResponse], setting, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_edit(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.dns.settings.with_raw_response.edit( + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + await async_client.dns.settings.with_raw_response.edit( + account_id="string", + ) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + setting = await async_client.dns.settings.get( + account_id="string", + ) + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + @parametrize + async def test_method_get_with_all_params(self, async_client: AsyncCloudflare) -> None: + setting = await async_client.dns.settings.get( + account_id="string", + ) + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.dns.settings.with_raw_response.get( + account_id="string", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + setting = await response.parse() + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.dns.settings.with_streaming_response.get( + account_id="string", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + setting = await response.parse() + assert_matches_type(Optional[SettingGetResponse], setting, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.dns.settings.with_raw_response.get( + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + await async_client.dns.settings.with_raw_response.get( + account_id="string", + ) diff --git a/tests/api_resources/zero_trust/access/test_policies.py b/tests/api_resources/zero_trust/access/test_policies.py new file mode 100644 index 00000000000..dd11538c159 --- /dev/null +++ b/tests/api_resources/zero_trust/access/test_policies.py @@ -0,0 +1,761 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.pagination import SyncSinglePage, AsyncSinglePage +from cloudflare.types.zero_trust.access import ( + PolicyGetResponse, + PolicyListResponse, + PolicyCreateResponse, + PolicyDeleteResponse, + PolicyUpdateResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestPolicies: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + approval_groups=[ + { + "approvals_needed": 1, + "email_addresses": ["test1@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "string", + }, + { + "approvals_needed": 3, + "email_addresses": ["test@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "597147a1-976b-4ef2-9af0-81d5d007fc34", + }, + ], + approval_required=True, + exclude=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + isolation_required=False, + purpose_justification_prompt="Please enter a justification for entering this protected domain.", + purpose_justification_required=True, + require=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + session_duration="24h", + ) + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Cloudflare) -> None: + response = client.zero_trust.access.policies.with_raw_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = response.parse() + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Cloudflare) -> None: + with client.zero_trust.access.policies.with_streaming_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = response.parse() + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.create( + account_id="", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + @parametrize + def test_method_update(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + @parametrize + def test_method_update_with_all_params(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + approval_groups=[ + { + "approvals_needed": 1, + "email_addresses": ["test1@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "string", + }, + { + "approvals_needed": 3, + "email_addresses": ["test@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "597147a1-976b-4ef2-9af0-81d5d007fc34", + }, + ], + approval_required=True, + exclude=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + isolation_required=False, + purpose_justification_prompt="Please enter a justification for entering this protected domain.", + purpose_justification_required=True, + require=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + session_duration="24h", + ) + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: Cloudflare) -> None: + response = client.zero_trust.access.policies.with_raw_response.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = response.parse() + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: Cloudflare) -> None: + with client.zero_trust.access.policies.with_streaming_response.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = response.parse() + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `policy_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.update( + "", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + @parametrize + def test_method_list(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(SyncSinglePage[PolicyListResponse], policy, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Cloudflare) -> None: + response = client.zero_trust.access.policies.with_raw_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = response.parse() + assert_matches_type(SyncSinglePage[PolicyListResponse], policy, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Cloudflare) -> None: + with client.zero_trust.access.policies.with_streaming_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = response.parse() + assert_matches_type(SyncSinglePage[PolicyListResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.list( + account_id="", + ) + + @parametrize + def test_method_delete(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[PolicyDeleteResponse], policy, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: Cloudflare) -> None: + response = client.zero_trust.access.policies.with_raw_response.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = response.parse() + assert_matches_type(Optional[PolicyDeleteResponse], policy, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: Cloudflare) -> None: + with client.zero_trust.access.policies.with_streaming_response.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = response.parse() + assert_matches_type(Optional[PolicyDeleteResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `policy_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.delete( + "", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + policy = client.zero_trust.access.policies.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[PolicyGetResponse], policy, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.zero_trust.access.policies.with_raw_response.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = response.parse() + assert_matches_type(Optional[PolicyGetResponse], policy, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.zero_trust.access.policies.with_streaming_response.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = response.parse() + assert_matches_type(Optional[PolicyGetResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `policy_id` but received ''"): + client.zero_trust.access.policies.with_raw_response.get( + "", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + +class TestAsyncPolicies: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_create(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + approval_groups=[ + { + "approvals_needed": 1, + "email_addresses": ["test1@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "string", + }, + { + "approvals_needed": 3, + "email_addresses": ["test@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "597147a1-976b-4ef2-9af0-81d5d007fc34", + }, + ], + approval_required=True, + exclude=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + isolation_required=False, + purpose_justification_prompt="Please enter a justification for entering this protected domain.", + purpose_justification_required=True, + require=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + session_duration="24h", + ) + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.policies.with_raw_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = await response.parse() + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.policies.with_streaming_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = await response.parse() + assert_matches_type(Optional[PolicyCreateResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.create( + account_id="", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + @parametrize + async def test_method_update(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + approval_groups=[ + { + "approvals_needed": 1, + "email_addresses": ["test1@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "string", + }, + { + "approvals_needed": 3, + "email_addresses": ["test@cloudflare.com", "test2@cloudflare.com"], + "email_list_uuid": "597147a1-976b-4ef2-9af0-81d5d007fc34", + }, + ], + approval_required=True, + exclude=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + isolation_required=False, + purpose_justification_prompt="Please enter a justification for entering this protected domain.", + purpose_justification_required=True, + require=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + session_duration="24h", + ) + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.policies.with_raw_response.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = await response.parse() + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.policies.with_streaming_response.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = await response.parse() + assert_matches_type(Optional[PolicyUpdateResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.update( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `policy_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.update( + "", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + decision="allow", + include=[ + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + {"email": {"email": "test@example.com"}}, + ], + name="Allow devs", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(AsyncSinglePage[PolicyListResponse], policy, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.policies.with_raw_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = await response.parse() + assert_matches_type(AsyncSinglePage[PolicyListResponse], policy, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.policies.with_streaming_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = await response.parse() + assert_matches_type(AsyncSinglePage[PolicyListResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.list( + account_id="", + ) + + @parametrize + async def test_method_delete(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[PolicyDeleteResponse], policy, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.policies.with_raw_response.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = await response.parse() + assert_matches_type(Optional[PolicyDeleteResponse], policy, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.policies.with_streaming_response.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = await response.parse() + assert_matches_type(Optional[PolicyDeleteResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.delete( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `policy_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.delete( + "", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + policy = await async_client.zero_trust.access.policies.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[PolicyGetResponse], policy, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.policies.with_raw_response.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + policy = await response.parse() + assert_matches_type(Optional[PolicyGetResponse], policy, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.policies.with_streaming_response.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + policy = await response.parse() + assert_matches_type(Optional[PolicyGetResponse], policy, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.get( + "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `policy_id` but received ''"): + await async_client.zero_trust.access.policies.with_raw_response.get( + "", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + )