Skip to content

Commit 6ab3739

Browse files
Merge pull request #110 from abdelrahman-zaki/main
fix: correct users get/update/delete to `/api/v1/user?id=...`
2 parents 721663f + 4f5def6 commit 6ab3739

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

kinde_sdk/management/management_client.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ class ManagementClient:
2828
# Users API
2929
'users': {
3030
'list': ('GET', '/api/v1/users'),
31-
'get': ('GET', '/api/v1/users/{user_id}'),
31+
'get': ('GET', '/api/v1/user'),
3232
'create': ('POST', '/api/v1/user'),
33-
'update': ('PATCH', '/api/v1/users/{user_id}'),
34-
'delete': ('DELETE', '/api/v1/users/{user_id}'),
33+
'update': ('PATCH', '/api/v1/user', ['id']),
34+
'delete': ('DELETE', '/api/v1/user'),
3535
},
3636

3737
# Organizations API
@@ -393,7 +393,13 @@ def _generate_methods(self):
393393
else:
394394
resource_singular = resource[:-1] if resource.endswith('s') else resource
395395

396-
for action, (method, path) in endpoints.items():
396+
for action, endpoint in endpoints.items():
397+
if len(endpoint) == 3:
398+
method, path, query_keys = endpoint
399+
else:
400+
method, path = endpoint
401+
query_keys = ()
402+
397403
# Create method name based on action and resource
398404
if action == 'list':
399405
method_name = f"get_{resource}"
@@ -403,12 +409,12 @@ def _generate_methods(self):
403409
method_name = f"{action}_{resource_singular}"
404410

405411
# Create the method
406-
api_method = self._create_api_method(method, path, resource, action)
412+
api_method = self._create_api_method(method, path, resource, action, query_keys)
407413

408414
# Set the method on the class
409415
setattr(self, method_name, api_method)
410416

411-
def _create_api_method(self, http_method: str, path: str, resource: str, action: str) -> Callable:
417+
def _create_api_method(self, http_method: str, path: str, resource: str, action: str, query_keys=()) -> Callable:
412418
"""
413419
Create a dynamic method for an API endpoint.
414420
@@ -438,15 +444,17 @@ def api_method(*args, **kwargs) -> Dict[str, Any]:
438444
if start_idx >= 0 and end_idx >= 0:
439445
formatted_path = formatted_path[:start_idx] + str(param_values.pop(0)) + formatted_path[end_idx + 1:]
440446

441-
# Handle query params or body data based on HTTP method
442-
query_params = None
443-
body = None
444-
447+
# Handle query/body split
445448
if http_method in ('GET', 'DELETE'):
446449
query_params = {k: v for k, v in kwargs.items() if v is not None}
450+
payload = None
447451
else:
448-
body = {k: v for k, v in kwargs.items() if v is not None}
449-
452+
# Lift ONLY declared query_keys into the query string
453+
qset = set(query_keys or ())
454+
query_params = {k: kwargs.pop(k) for k in list(kwargs) if k in qset and kwargs[k] is not None}
455+
# Remaining kwargs go to JSON body
456+
payload = {k: v for k, v in kwargs.items() if v is not None}
457+
450458
# FIXED: Use param_serialize to properly construct the full URL with host
451459
# Handle query parameters by appending them to the path
452460
final_path = formatted_path
@@ -460,28 +468,33 @@ def api_method(*args, **kwargs) -> Dict[str, Any]:
460468
# Remove /api/v1 prefix from resource_path since host already includes it
461469
resource_path_for_serialize = formatted_path.replace('/api/v1', '', 1)
462470

463-
method, url, header_params, body, post_params = self.api_client.param_serialize(
471+
method, url, header_params, serialized_body, post_params = self.api_client.param_serialize(
464472
method=http_method,
465473
resource_path=resource_path_for_serialize, # Use path without /api/v1 prefix
466-
query_params=query_params if http_method in ('GET', 'DELETE') else None,
474+
query_params=query_params or None,
467475
header_params={},
468-
body=body if http_method not in ('GET', 'DELETE') else None
476+
body=payload if http_method not in ('GET', 'DELETE') else None
469477
)
470-
478+
479+
# Ensure required headers for PATCH/POST/PUT
480+
if http_method not in ('GET', 'DELETE'):
481+
header_params.setdefault('Content-Type', 'application/json')
482+
header_params.setdefault('Accept', 'application/json')
483+
471484
# Add the authorization token to headers
472485
token = self.token_manager.get_access_token()
473486
header_params['Authorization'] = f"Bearer {token}"
474-
487+
475488
# Call the REST client directly with the constructed URL
476489
response = self.api_client.rest_client.request(
477490
method=http_method,
478491
url=url,
479492
headers=header_params,
480-
body=body if http_method not in ('GET', 'DELETE') else None,
493+
body=serialized_body if http_method not in ('GET', 'DELETE') else None,
481494
post_params=post_params,
482495
_request_timeout=None
483496
)
484-
497+
485498
# Use the API client's response_deserialize to properly handle the response
486499
# First read the response data
487500
response.read()

0 commit comments

Comments
 (0)