diff --git a/kinde_sdk/management/management_client.py b/kinde_sdk/management/management_client.py index 96a50ab4..5d27e3f3 100644 --- a/kinde_sdk/management/management_client.py +++ b/kinde_sdk/management/management_client.py @@ -38,7 +38,7 @@ class ManagementClient: 'organizations': { 'list': ('GET', '/api/v1/organizations'), 'get': ('GET', '/api/v1/organizations/{org_code}'), - 'create': ('POST', '/api/v1/organization'), + 'create': ('POST', '/api/v1/organizations'), 'update': ('PATCH', '/api/v1/organizations/{org_code}'), 'delete': ('DELETE', '/api/v1/organizations/{org_code}'), }, @@ -69,7 +69,7 @@ class ManagementClient: 'roles': { 'list': ('GET', '/api/v1/roles'), 'get': ('GET', '/api/v1/roles/{role_id}'), - 'create': ('POST', '/api/v1/role'), + 'create': ('POST', '/api/v1/roles'), 'update': ('PATCH', '/api/v1/roles/{role_id}'), 'delete': ('DELETE', '/api/v1/roles/{role_id}'), }, @@ -77,8 +77,7 @@ class ManagementClient: # Permissions API 'permissions': { 'list': ('GET', '/api/v1/permissions'), - 'get': ('GET', '/api/v1/permissions/{permission_id}'), - 'create': ('POST', '/api/v1/permission'), + 'create': ('POST', '/api/v1/permissions'), 'update': ('PATCH', '/api/v1/permissions/{permission_id}'), 'delete': ('DELETE', '/api/v1/permissions/{permission_id}'), }, @@ -86,9 +85,8 @@ class ManagementClient: # Feature Flags API 'feature_flags': { 'list': ('GET', '/api/v1/feature_flags'), - 'get': ('GET', '/api/v1/feature_flags/{feature_flag_key}'), - 'create': ('POST', '/api/v1/feature_flag'), - 'update': ('PATCH', '/api/v1/feature_flags/{feature_flag_key}'), + 'create': ('POST', '/api/v1/feature_flags'), + 'update': ('PUT', '/api/v1/feature_flags/{feature_flag_key}'), 'delete': ('DELETE', '/api/v1/feature_flags/{feature_flag_key}'), }, @@ -96,7 +94,7 @@ class ManagementClient: 'connected_apps': { 'list': ('GET', '/api/v1/applications'), 'get': ('GET', '/api/v1/applications/{application_id}'), - 'create': ('POST', '/api/v1/application'), + 'create': ('POST', '/api/v1/applications'), 'update': ('PATCH', '/api/v1/applications/{application_id}'), 'delete': ('DELETE', '/api/v1/applications/{application_id}'), }, @@ -105,8 +103,7 @@ class ManagementClient: 'api_applications': { 'list': ('GET', '/api/v1/apis'), 'get': ('GET', '/api/v1/apis/{api_id}'), - 'create': ('POST', '/api/v1/api'), - 'update': ('PATCH', '/api/v1/apis/{api_id}'), + 'create': ('POST', '/api/v1/apis'), 'delete': ('DELETE', '/api/v1/apis/{api_id}'), }, @@ -114,6 +111,7 @@ class ManagementClient: 'subscribers': { 'list': ('GET', '/api/v1/subscribers'), 'get': ('GET', '/api/v1/subscribers/{subscriber_id}'), + 'create': ('POST', '/api/v1/subscribers'), }, # Timezones API @@ -129,30 +127,26 @@ class ManagementClient: # Properties API 'properties': { 'list': ('GET', '/api/v1/properties'), - 'get': ('GET', '/api/v1/properties/{property_id}'), 'create': ('POST', '/api/v1/properties'), - 'update': ('PATCH', '/api/v1/properties/{property_id}'), + 'update': ('PUT', '/api/v1/properties/{property_id}'), 'delete': ('DELETE', '/api/v1/properties/{property_id}'), }, # User Properties API 'user_properties': { 'list': ('GET', '/api/v1/users/{user_id}/properties'), - 'get': ('GET', '/api/v1/users/{user_id}/properties/{property_key}'), 'update': ('PUT', '/api/v1/users/{user_id}/properties/{property_key}'), }, # Organization Properties API 'organization_properties': { 'list': ('GET', '/api/v1/organizations/{org_code}/properties'), - 'get': ('GET', '/api/v1/organizations/{org_code}/properties/{property_key}'), 'update': ('PUT', '/api/v1/organizations/{org_code}/properties/{property_key}'), }, # Webhooks API 'webhooks': { 'list': ('GET', '/api/v1/webhooks'), - 'get': ('GET', '/api/v1/webhooks/{webhook_id}'), 'create': ('POST', '/api/v1/webhooks'), 'update': ('PATCH', '/api/v1/webhooks/{webhook_id}'), 'delete': ('DELETE', '/api/v1/webhooks/{webhook_id}'), @@ -180,12 +174,12 @@ class ManagementClient: # Business API 'business': { 'get': ('GET', '/api/v1/business'), + 'update': ('PATCH', '/api/v1/business'), }, # Environment Feature Flags API 'environment_feature_flags': { 'list': ('GET', '/api/v1/environment/feature_flags'), - 'get': ('GET', '/api/v1/environment/feature_flags/{feature_flag_key}'), 'update': ('PATCH', '/api/v1/environment/feature_flags/{feature_flag_key}'), 'delete': ('DELETE', '/api/v1/environment/feature_flags/{feature_flag_key}'), }, @@ -193,14 +187,12 @@ class ManagementClient: # Organization Feature Flags API 'organization_feature_flags': { 'list': ('GET', '/api/v1/organizations/{org_code}/feature_flags'), - 'get': ('GET', '/api/v1/organizations/{org_code}/feature_flags/{feature_flag_key}'), 'update': ('PATCH', '/api/v1/organizations/{org_code}/feature_flags/{feature_flag_key}'), 'delete': ('DELETE', '/api/v1/organizations/{org_code}/feature_flags/{feature_flag_key}'), }, # User Feature Flags API 'user_feature_flags': { - 'get': ('GET', '/api/v1/users/{user_id}/feature_flags/{feature_flag_key}'), 'update': ('PATCH', '/api/v1/users/{user_id}/feature_flags/{feature_flag_key}'), }, @@ -213,6 +205,15 @@ class ManagementClient: 'user_refresh_claims': { 'refresh': ('POST', '/api/v1/users/{user_id}/refresh_claims'), }, + 'user_identities': { + 'list': ('GET', '/api/v1/users/{user_id}/identities'), + 'create': ('POST', '/api/v1/users/{user_id}/identities'), + }, + 'identities': { + 'get': ('GET', '/api/v1/identities/{identity_id}'), + 'update': ('PATCH', '/api/v1/identities/{identity_id}'), + 'delete': ('DELETE', '/api/v1/identities/{identity_id}'), + }, } # Define response types for each endpoint @@ -220,7 +221,7 @@ class ManagementClient: 'users': { 'list': {'200': 'UsersResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'get': {'200': 'User', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, - 'create': {'201': 'CreateUserResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'create': {'200': 'CreateUserResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'UpdateUserResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, @@ -233,37 +234,35 @@ class ManagementClient: }, 'organization_users': { 'list': {'200': 'GetOrganizationUsersResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'add': {'201': 'AddOrganizationUsersResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'add': {'200': 'AddOrganizationUsersResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'UpdateOrganizationUsersResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'remove': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'organization_user_roles': { 'list': {'200': 'GetOrganizationsUserRolesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'add': {'201': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'add': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'remove': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'organization_user_permissions': { 'list': {'200': 'GetOrganizationsUserPermissionsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'add': {'201': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'add': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'remove': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'roles': { 'list': {'200': 'GetRolesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'get': {'200': 'GetRoleResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, - 'create': {'201': 'CreateRoleResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'update': {'200': 'UpdateRoleResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'create': {'201': 'CreateRolesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'update': {'201': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'permissions': { 'list': {'200': 'GetPermissionsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'Permissions', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'create': {'201': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'feature_flags': { 'list': {'200': 'GetFeatureFlagsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetFeatureFlagsResponseDataFeatureFlagsInner', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'create': {'201': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, @@ -271,19 +270,19 @@ class ManagementClient: 'subscribers': { 'list': {'200': 'GetSubscribersResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'get': {'200': 'GetSubscriberResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'create': {'201': 'CreateSubscriberSuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'api_applications': { 'list': {'200': 'GetApisResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'get': {'200': 'GetApiResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, - 'create': {'201': 'CreateApiResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'update': {'200': 'UpdateApiResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'create': {'201': 'CreateApisResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'connected_apps': { 'list': {'200': 'GetApplicationsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'get': {'200': 'GetApplicationResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'create': {'201': 'CreateApplicationResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'update': {'200': 'UpdateApplicationResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'timezones': { @@ -294,26 +293,22 @@ class ManagementClient: }, 'properties': { 'list': {'200': 'GetPropertiesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetPropertyResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'create': {'201': 'CreatePropertyResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'user_properties': { - 'list': {'200': 'GetUserPropertiesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetUserPropertyResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'list': {'200': 'GetPropertyValuesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'organization_properties': { - 'list': {'200': 'GetOrganizationPropertiesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetOrganizationPropertyResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'list': {'200': 'GetPropertyValuesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'webhooks': { 'list': {'200': 'GetWebhooksResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetWebhookResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, - 'create': {'201': 'CreateWebhookResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, + 'create': {'200': 'CreateWebhookResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'update': {'200': 'UpdateWebhookResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'events': { @@ -331,21 +326,19 @@ class ManagementClient: }, 'business': { 'get': {'200': 'GetBusinessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'environment_feature_flags': { 'list': {'200': 'GetEnvironmentFeatureFlagsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetEnvironmentFeatureFlagsResponseDataFeatureFlagsInner', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'organization_feature_flags': { 'list': {'200': 'GetOrganizationFeatureFlagsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, - 'get': {'200': 'GetOrganizationFeatureFlagsResponseDataFeatureFlagsInner', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'user_feature_flags': { - 'get': {'200': 'GetUserFeatureFlagsResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, 'user_password': { @@ -354,6 +347,15 @@ class ManagementClient: 'user_refresh_claims': { 'refresh': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '404': 'ErrorResponse', '429': 'ErrorResponse'}, }, + 'user_identities': { + 'list': {'200': 'GetIdentitiesResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'create': {'201': 'CreateIdentityResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + }, + 'identities': { + 'get': {'200': 'Identity', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'update': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + 'delete': {'200': 'SuccessResponse', '400': 'ErrorResponse', '403': 'ErrorResponse', '429': 'ErrorResponse'}, + }, } def __init__(self, domain: str, client_id: str, client_secret: str): @@ -384,14 +386,33 @@ def _setup_token_handling(self): # Token will be added directly in the API method since we're calling REST client directly pass + def _singularize_resource(self, resource: str) -> str: + """ + Convert a plural resource name to its singular form. + + Args: + resource: Plural resource name (e.g., 'users', 'user_identities', 'identities') + + Returns: + Singular form of the resource name (e.g., 'user', 'user_identity', 'identity') + """ + # Handle special cases + if resource == 'business': + return 'business' # Don't remove 's' from 'business' + elif resource == 'user_identities': + return 'user_identity' # Replace 'identities' with 'identity' + elif resource == 'identities': + return 'identity' # Replace 'identities' with 'identity' + # Default: remove trailing 's' if present + elif resource.endswith('s'): + return resource[:-1] + else: + return resource + def _generate_methods(self): """Generate dynamic methods for each API endpoint.""" for resource, endpoints in self.API_ENDPOINTS.items(): - # Handle special cases for singularization - if resource == 'business': - resource_singular = 'business' # Don't remove 's' from 'business' - else: - resource_singular = resource[:-1] if resource.endswith('s') else resource + resource_singular = self._singularize_resource(resource) for action, endpoint in endpoints.items(): if len(endpoint) == 3: @@ -427,11 +448,7 @@ def _create_api_method(self, http_method: str, path: str, resource: str, action: Returns: A callable method that makes the API request """ - # Handle special cases for singularization - if resource == 'business': - resource_singular = 'business' # Don't remove 's' from 'business' - else: - resource_singular = resource[:-1] if resource.endswith('s') else resource + resource_singular = self._singularize_resource(resource) def api_method(*args, **kwargs) -> Dict[str, Any]: # Format path with any path parameters from args diff --git a/testv2/testv2_management/test_management_client.py b/testv2/testv2_management/test_management_client.py index 9373e88e..68eed6b3 100644 --- a/testv2/testv2_management/test_management_client.py +++ b/testv2/testv2_management/test_management_client.py @@ -97,14 +97,12 @@ def test_dynamic_method_generation(self, mock_token_manager_class, mock_api_clie # Test permission methods assert hasattr(client, 'get_permissions') - assert hasattr(client, 'get_permission') assert hasattr(client, 'create_permission') assert hasattr(client, 'update_permission') assert hasattr(client, 'delete_permission') # Test feature flag methods assert hasattr(client, 'get_feature_flags') - assert hasattr(client, 'get_feature_flag') assert hasattr(client, 'create_feature_flag') assert hasattr(client, 'update_feature_flag') assert hasattr(client, 'delete_feature_flag') @@ -117,7 +115,6 @@ def test_dynamic_method_generation(self, mock_token_manager_class, mock_api_clie assert hasattr(client, 'get_api_applications') assert hasattr(client, 'get_api_application') assert hasattr(client, 'create_api_application') - assert hasattr(client, 'update_api_application') assert hasattr(client, 'delete_api_application') # Test subscriber methods @@ -499,20 +496,21 @@ def test_feature_flags_api_calls(self, mock_token_manager_class, mock_api_client # Mock param_serialize to return expected values mock_api_client_instance.param_serialize.return_value = ( - 'GET', 'https://test.kinde.com/api/v1/feature-flags', {}, None, None + 'POST', 'https://test.kinde.com/api/v1/feature_flags', {}, + {"key": "test_flag", "type": "str", "value": "test_value"}, None ) # Mock REST client response mock_rest_response = Mock() mock_rest_response.read.return_value = None mock_rest_response.status = 200 - mock_rest_response.data = b'{"feature_flags": [{"key": "test_flag"}]}' + mock_rest_response.data = b'{"key": "test_flag", "type": "str", "value": "test_value"}' mock_rest_response.getheader.return_value = 'application/json' mock_api_client_instance.rest_client.request.return_value = mock_rest_response # Mock response_deserialize - expected_response = {"feature_flags": [{"key": "test_flag"}]} + expected_response = {"key": "test_flag", "type": "str", "value": "test_value"} mock_api_response = Mock() mock_api_response.data = expected_response mock_api_client_instance.response_deserialize.return_value = mock_api_response @@ -523,8 +521,8 @@ def test_feature_flags_api_calls(self, mock_token_manager_class, mock_api_client # Create client client = ManagementClient(self.domain, self.client_id, self.client_secret) - # Test feature flag API call - result = client.get_feature_flags() + # Test feature flag create API call + result = client.create_feature_flag(key="test_flag", type="str", value="test_value") # Verify param_serialize was called mock_api_client_instance.param_serialize.assert_called_once()