diff --git a/src/auth0/management/management_client.py b/src/auth0/management/management_client.py index 421f9bda..82c5cd1c 100644 --- a/src/auth0/management/management_client.py +++ b/src/auth0/management/management_client.py @@ -1,3 +1,7 @@ +# This file is hand-written and listed in .fernignore, so Fern does not overwrite it. +# Each resource that the generated Auth0 client exposes needs a matching property +# on ManagementClient and AsyncManagementClient, plus a TYPE_CHECKING import. +# tests/management/test_management_client.py fails and lists any missing resource. from __future__ import annotations import base64 @@ -61,19 +65,25 @@ def CustomDomainHeader(domain: str) -> RequestOptions: if TYPE_CHECKING: from .actions.client import ActionsClient, AsyncActionsClient + from .agents.client import AsyncAgentsClient, AgentsClient from .anomaly.client import AnomalyClient, AsyncAnomalyClient from .attack_protection.client import AsyncAttackProtectionClient, AttackProtectionClient from .branding.client import AsyncBrandingClient, BrandingClient from .client_grants.client import AsyncClientGrantsClient, ClientGrantsClient + from .client_profiles.client import AsyncClientProfilesClient, ClientProfilesClient from .clients.client import AsyncClientsClient, ClientsClient + from .connection_profiles.client import AsyncConnectionProfilesClient, ConnectionProfilesClient from .connections.client import AsyncConnectionsClient, ConnectionsClient from .custom_domains.client import AsyncCustomDomainsClient, CustomDomainsClient from .device_credentials.client import AsyncDeviceCredentialsClient, DeviceCredentialsClient from .email_templates.client import AsyncEmailTemplatesClient, EmailTemplatesClient from .emails.client import AsyncEmailsClient, EmailsClient from .event_streams.client import AsyncEventStreamsClient, EventStreamsClient + from .events.client import AsyncEventsClient, EventsClient + from .experimentation.client import AsyncExperimentationClient, ExperimentationClient from .flows.client import AsyncFlowsClient, FlowsClient from .forms.client import AsyncFormsClient, FormsClient + from .groups.client import AsyncGroupsClient, GroupsClient from .guardian.client import AsyncGuardianClient, GuardianClient from .hooks.client import AsyncHooksClient, HooksClient from .jobs.client import AsyncJobsClient, JobsClient @@ -83,8 +93,10 @@ def CustomDomainHeader(domain: str) -> RequestOptions: from .network_acls.client import AsyncNetworkAclsClient, NetworkAclsClient from .organizations.client import AsyncOrganizationsClient, OrganizationsClient from .prompts.client import AsyncPromptsClient, PromptsClient + from .rate_limit_policies.client import AsyncRateLimitPoliciesClient, RateLimitPoliciesClient from .refresh_tokens.client import AsyncRefreshTokensClient, RefreshTokensClient from .resource_servers.client import AsyncResourceServersClient, ResourceServersClient + from .risk_assessments.client import AsyncRiskAssessmentsClient, RiskAssessmentsClient from .roles.client import AsyncRolesClient, RolesClient from .rules.client import AsyncRulesClient, RulesClient from .rules_configs.client import AsyncRulesConfigsClient, RulesConfigsClient @@ -95,6 +107,7 @@ def CustomDomainHeader(domain: str) -> RequestOptions: from .tenants.client import AsyncTenantsClient, TenantsClient from .tickets.client import AsyncTicketsClient, TicketsClient from .token_exchange_profiles.client import AsyncTokenExchangeProfilesClient, TokenExchangeProfilesClient + from .user_attribute_profiles.client import AsyncUserAttributeProfilesClient, UserAttributeProfilesClient from .user_blocks.client import AsyncUserBlocksClient, UserBlocksClient from .user_grants.client import AsyncUserGrantsClient, UserGrantsClient from .users.client import AsyncUsersClient, UsersClient @@ -221,6 +234,10 @@ def __init__( def actions(self) -> "ActionsClient": return self._api.actions + @property + def agents(self) -> "AgentsClient": + return self._api.agents + @property def anomaly(self) -> "AnomalyClient": return self._api.anomaly @@ -237,10 +254,18 @@ def branding(self) -> "BrandingClient": def client_grants(self) -> "ClientGrantsClient": return self._api.client_grants + @property + def client_profiles(self) -> "ClientProfilesClient": + return self._api.client_profiles + @property def clients(self) -> "ClientsClient": return self._api.clients + @property + def connection_profiles(self) -> "ConnectionProfilesClient": + return self._api.connection_profiles + @property def connections(self) -> "ConnectionsClient": return self._api.connections @@ -265,6 +290,14 @@ def emails(self) -> "EmailsClient": def event_streams(self) -> "EventStreamsClient": return self._api.event_streams + @property + def events(self) -> "EventsClient": + return self._api.events + + @property + def experimentation(self) -> "ExperimentationClient": + return self._api.experimentation + @property def flows(self) -> "FlowsClient": return self._api.flows @@ -273,6 +306,10 @@ def flows(self) -> "FlowsClient": def forms(self) -> "FormsClient": return self._api.forms + @property + def groups(self) -> "GroupsClient": + return self._api.groups + @property def guardian(self) -> "GuardianClient": return self._api.guardian @@ -309,6 +346,10 @@ def organizations(self) -> "OrganizationsClient": def prompts(self) -> "PromptsClient": return self._api.prompts + @property + def rate_limit_policies(self) -> "RateLimitPoliciesClient": + return self._api.rate_limit_policies + @property def refresh_tokens(self) -> "RefreshTokensClient": return self._api.refresh_tokens @@ -317,6 +358,10 @@ def refresh_tokens(self) -> "RefreshTokensClient": def resource_servers(self) -> "ResourceServersClient": return self._api.resource_servers + @property + def risk_assessments(self) -> "RiskAssessmentsClient": + return self._api.risk_assessments + @property def roles(self) -> "RolesClient": return self._api.roles @@ -357,6 +402,10 @@ def tickets(self) -> "TicketsClient": def token_exchange_profiles(self) -> "TokenExchangeProfilesClient": return self._api.token_exchange_profiles + @property + def user_attribute_profiles(self) -> "UserAttributeProfilesClient": + return self._api.user_attribute_profiles + @property def user_blocks(self) -> "UserBlocksClient": return self._api.user_blocks @@ -497,6 +546,10 @@ def __init__( def actions(self) -> "AsyncActionsClient": return self._api.actions + @property + def agents(self) -> "AsyncAgentsClient": + return self._api.agents + @property def anomaly(self) -> "AsyncAnomalyClient": return self._api.anomaly @@ -513,10 +566,18 @@ def branding(self) -> "AsyncBrandingClient": def client_grants(self) -> "AsyncClientGrantsClient": return self._api.client_grants + @property + def client_profiles(self) -> "AsyncClientProfilesClient": + return self._api.client_profiles + @property def clients(self) -> "AsyncClientsClient": return self._api.clients + @property + def connection_profiles(self) -> "AsyncConnectionProfilesClient": + return self._api.connection_profiles + @property def connections(self) -> "AsyncConnectionsClient": return self._api.connections @@ -541,6 +602,14 @@ def emails(self) -> "AsyncEmailsClient": def event_streams(self) -> "AsyncEventStreamsClient": return self._api.event_streams + @property + def events(self) -> "AsyncEventsClient": + return self._api.events + + @property + def experimentation(self) -> "AsyncExperimentationClient": + return self._api.experimentation + @property def flows(self) -> "AsyncFlowsClient": return self._api.flows @@ -549,6 +618,10 @@ def flows(self) -> "AsyncFlowsClient": def forms(self) -> "AsyncFormsClient": return self._api.forms + @property + def groups(self) -> "AsyncGroupsClient": + return self._api.groups + @property def guardian(self) -> "AsyncGuardianClient": return self._api.guardian @@ -585,6 +658,10 @@ def organizations(self) -> "AsyncOrganizationsClient": def prompts(self) -> "AsyncPromptsClient": return self._api.prompts + @property + def rate_limit_policies(self) -> "AsyncRateLimitPoliciesClient": + return self._api.rate_limit_policies + @property def refresh_tokens(self) -> "AsyncRefreshTokensClient": return self._api.refresh_tokens @@ -593,6 +670,10 @@ def refresh_tokens(self) -> "AsyncRefreshTokensClient": def resource_servers(self) -> "AsyncResourceServersClient": return self._api.resource_servers + @property + def risk_assessments(self) -> "AsyncRiskAssessmentsClient": + return self._api.risk_assessments + @property def roles(self) -> "AsyncRolesClient": return self._api.roles @@ -633,6 +714,10 @@ def tickets(self) -> "AsyncTicketsClient": def token_exchange_profiles(self) -> "AsyncTokenExchangeProfilesClient": return self._api.token_exchange_profiles + @property + def user_attribute_profiles(self) -> "AsyncUserAttributeProfilesClient": + return self._api.user_attribute_profiles + @property def user_blocks(self) -> "AsyncUserBlocksClient": return self._api.user_blocks diff --git a/tests/management/test_management_client.py b/tests/management/test_management_client.py index 7901a4d5..766129eb 100644 --- a/tests/management/test_management_client.py +++ b/tests/management/test_management_client.py @@ -13,6 +13,7 @@ ManagementClient, TokenProvider, ) +from auth0.management.client import AsyncAuth0, Auth0 from auth0.management.management_client import ( CUSTOM_DOMAIN_HEADER as _CUSTOM_DOMAIN_HEADER, ) @@ -168,19 +169,25 @@ def test_has_all_expected_properties(self, client): """Should have all expected sub-client properties.""" expected_properties = [ "actions", + "agents", "anomaly", "attack_protection", "branding", "client_grants", + "client_profiles", "clients", + "connection_profiles", "connections", "custom_domains", "device_credentials", "email_templates", "emails", "event_streams", + "events", + "experimentation", "flows", "forms", + "groups", "guardian", "hooks", "jobs", @@ -190,8 +197,10 @@ def test_has_all_expected_properties(self, client): "network_acls", "organizations", "prompts", + "rate_limit_policies", "refresh_tokens", "resource_servers", + "risk_assessments", "roles", "rules", "rules_configs", @@ -202,6 +211,7 @@ def test_has_all_expected_properties(self, client): "tenants", "tickets", "token_exchange_profiles", + "user_attribute_profiles", "user_blocks", "user_grants", "users", @@ -256,6 +266,38 @@ def test_init_with_custom_client_info(self): assert decoded == custom_info +class TestManagementClientMatchesGeneratedClient: + """Keep the hand-written wrappers in step with the generated clients.""" + + @staticmethod + def _public_properties(cls): + return { + name + for name, value in vars(cls).items() + if isinstance(value, property) and not name.startswith("_") + } + + def test_management_client_exposes_every_generated_resource(self): + """Should expose every resource the generated Auth0 client has.""" + missing = self._public_properties(Auth0) - self._public_properties( + ManagementClient + ) + assert missing == set(), ( + f"ManagementClient is missing: {sorted(missing)}. Add a property and a " + "TYPE_CHECKING import for each one in management_client.py." + ) + + def test_async_management_client_exposes_every_generated_resource(self): + """Should expose every resource the generated AsyncAuth0 client has.""" + missing = self._public_properties(AsyncAuth0) - self._public_properties( + AsyncManagementClient + ) + assert missing == set(), ( + f"AsyncManagementClient is missing: {sorted(missing)}. Add a property and " + "a TYPE_CHECKING import for each one in management_client.py." + ) + + class TestTokenProvider: """Tests for TokenProvider."""