diff --git a/src/WorkOS.net/Client/Utilities/RequestUtilities.cs b/src/WorkOS.net/Client/Utilities/RequestUtilities.cs index 1ae3478f..fc17b598 100644 --- a/src/WorkOS.net/Client/Utilities/RequestUtilities.cs +++ b/src/WorkOS.net/Client/Utilities/RequestUtilities.cs @@ -14,6 +14,7 @@ namespace WorkOS using System.Reflection; using System.Text; using Newtonsoft.Json; + using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; /// @@ -67,6 +68,21 @@ public static HttpContent CreateHttpContent(WorkOSRequest request) if (request.IsJsonContentType) { var jsonOptions = ToJsonString(options); + + // Merge extra body params (from parameter-group dispatch) into + // the serialized JSON so that fields like password / password_hash + // appear as top-level body keys instead of query parameters. + if (request.ExtraBodyParams != null && request.ExtraBodyParams.Count > 0) + { + var jobj = JObject.Parse(jsonOptions); + foreach (var kvp in request.ExtraBodyParams) + { + jobj[kvp.Key] = JToken.FromObject(kvp.Value, JsonSerializer.Create(JsonSettings)); + } + + jsonOptions = jobj.ToString(Formatting.None); + } + var content = new StringContent(jsonOptions, Encoding.UTF8); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); return content; diff --git a/src/WorkOS.net/Client/WorkOSClient.cs b/src/WorkOS.net/Client/WorkOSClient.cs index fdb5f49a..65367bb5 100644 --- a/src/WorkOS.net/Client/WorkOSClient.cs +++ b/src/WorkOS.net/Client/WorkOSClient.cs @@ -291,6 +291,8 @@ public async IAsyncEnumerable ListAutoPagingAsync( AccessToken = request.AccessToken, Options = workingOptions, RequestOptions = request.RequestOptions, + ExtraQueryParams = request.ExtraQueryParams, + ExtraBodyParams = request.ExtraBodyParams, }; string? afterCursor = null; diff --git a/src/WorkOS.net/Client/_interfaces/WorkOSRequest.cs b/src/WorkOS.net/Client/_interfaces/WorkOSRequest.cs index e2d194c8..aeefd183 100644 --- a/src/WorkOS.net/Client/_interfaces/WorkOSRequest.cs +++ b/src/WorkOS.net/Client/_interfaces/WorkOSRequest.cs @@ -52,6 +52,13 @@ public class WorkOSRequest /// internal Dictionary? ExtraQueryParams { get; set; } + /// + /// Extra body parameters injected by parameter-group dispatch + /// (e.g. password variants for user creation). These are merged + /// into the JSON request body alongside the options-derived fields. + /// + internal Dictionary? ExtraBodyParams { get; set; } + /// /// Append an extra query parameter to the request. /// @@ -60,5 +67,16 @@ internal void AddQueryParam(string key, string value) this.ExtraQueryParams ??= new Dictionary(); this.ExtraQueryParams[key] = value; } + + /// + /// Append an extra body parameter to the request. The value is + /// merged into the serialized JSON body. Accepts strings, arrays, + /// or other objects that will be serialized as their native JSON type. + /// + internal void AddBodyParam(string key, object value) + { + this.ExtraBodyParams ??= new Dictionary(); + this.ExtraBodyParams[key] = value; + } } } diff --git a/src/WorkOS.net/Services/Authorization/AuthorizationService.cs b/src/WorkOS.net/Services/Authorization/AuthorizationService.cs index 4b8745c0..603bd14c 100644 --- a/src/WorkOS.net/Services/Authorization/AuthorizationService.cs +++ b/src/WorkOS.net/Services/Authorization/AuthorizationService.cs @@ -47,19 +47,19 @@ public virtual async Task CheckAsync(string organizationMemb { if (byId.ResourceId != null) { - request.AddQueryParam("resource_id", byId.ResourceId); + request.AddBodyParam("resource_id", byId.ResourceId); } } else if (options?.ResourceTarget is AuthorizationResourceTargetByExternalId byExternalId) { if (byExternalId.ResourceExternalId != null) { - request.AddQueryParam("resource_external_id", byExternalId.ResourceExternalId); + request.AddBodyParam("resource_external_id", byExternalId.ResourceExternalId); } if (byExternalId.ResourceTypeSlug != null) { - request.AddQueryParam("resource_type_slug", byExternalId.ResourceTypeSlug); + request.AddBodyParam("resource_type_slug", byExternalId.ResourceTypeSlug); } } @@ -254,19 +254,19 @@ public virtual async Task AssignRoleAsync(string organizationMem { if (byId.ResourceId != null) { - request.AddQueryParam("resource_id", byId.ResourceId); + request.AddBodyParam("resource_id", byId.ResourceId); } } else if (options?.ResourceTarget is AuthorizationResourceTargetByExternalId byExternalId) { if (byExternalId.ResourceExternalId != null) { - request.AddQueryParam("resource_external_id", byExternalId.ResourceExternalId); + request.AddBodyParam("resource_external_id", byExternalId.ResourceExternalId); } if (byExternalId.ResourceTypeSlug != null) { - request.AddQueryParam("resource_type_slug", byExternalId.ResourceTypeSlug); + request.AddBodyParam("resource_type_slug", byExternalId.ResourceTypeSlug); } } @@ -552,19 +552,19 @@ public virtual async Task UpdateOrganizationResourceAsync { if (byId.ParentResourceId != null) { - request.AddQueryParam("parent_resource_id", byId.ParentResourceId); + request.AddBodyParam("parent_resource_id", byId.ParentResourceId); } } else if (options?.ParentResource is AuthorizationParentResourceByExternalId byExternalId) { if (byExternalId.ParentResourceExternalId != null) { - request.AddQueryParam("parent_resource_external_id", byExternalId.ParentResourceExternalId); + request.AddBodyParam("parent_resource_external_id", byExternalId.ParentResourceExternalId); } if (byExternalId.ParentResourceTypeSlug != null) { - request.AddQueryParam("parent_resource_type_slug", byExternalId.ParentResourceTypeSlug); + request.AddBodyParam("parent_resource_type_slug", byExternalId.ParentResourceTypeSlug); } } @@ -712,19 +712,19 @@ public virtual async Task CreateResourceAsync(Authorizati { if (byId.ParentResourceId != null) { - request.AddQueryParam("parent_resource_id", byId.ParentResourceId); + request.AddBodyParam("parent_resource_id", byId.ParentResourceId); } } else if (options?.ParentResource is AuthorizationParentResourceByExternalId byExternalId) { if (byExternalId.ParentResourceExternalId != null) { - request.AddQueryParam("parent_resource_external_id", byExternalId.ParentResourceExternalId); + request.AddBodyParam("parent_resource_external_id", byExternalId.ParentResourceExternalId); } if (byExternalId.ParentResourceTypeSlug != null) { - request.AddQueryParam("parent_resource_type_slug", byExternalId.ParentResourceTypeSlug); + request.AddBodyParam("parent_resource_type_slug", byExternalId.ParentResourceTypeSlug); } } @@ -779,19 +779,19 @@ public virtual async Task UpdateResourceAsync(string reso { if (byId.ParentResourceId != null) { - request.AddQueryParam("parent_resource_id", byId.ParentResourceId); + request.AddBodyParam("parent_resource_id", byId.ParentResourceId); } } else if (options?.ParentResource is AuthorizationParentResourceByExternalId byExternalId) { if (byExternalId.ParentResourceExternalId != null) { - request.AddQueryParam("parent_resource_external_id", byExternalId.ParentResourceExternalId); + request.AddBodyParam("parent_resource_external_id", byExternalId.ParentResourceExternalId); } if (byExternalId.ParentResourceTypeSlug != null) { - request.AddQueryParam("parent_resource_type_slug", byExternalId.ParentResourceTypeSlug); + request.AddBodyParam("parent_resource_type_slug", byExternalId.ParentResourceTypeSlug); } } diff --git a/src/WorkOS.net/Services/UserManagement/UserManagementService.cs b/src/WorkOS.net/Services/UserManagement/UserManagementService.cs index 0744b56e..04ea9632 100644 --- a/src/WorkOS.net/Services/UserManagement/UserManagementService.cs +++ b/src/WorkOS.net/Services/UserManagement/UserManagementService.cs @@ -415,17 +415,17 @@ public virtual async Task CreateAsync(UserManagementCreateOptions options, { if (plaintext.Password != null) { - request.AddQueryParam("password", plaintext.Password); + request.AddBodyParam("password", plaintext.Password); } } else if (options?.Password is UserManagementPasswordHashed hashed) { if (hashed.PasswordHash != null) { - request.AddQueryParam("password_hash", hashed.PasswordHash); + request.AddBodyParam("password_hash", hashed.PasswordHash); } - request.AddQueryParam("password_hash_type", JsonConvert.SerializeObject(hashed.PasswordHashType).Trim('"')); + request.AddBodyParam("password_hash_type", JsonConvert.SerializeObject(hashed.PasswordHashType).Trim('"')); } return await this.Client.MakeAPIRequest(request, cancellationToken); @@ -498,17 +498,17 @@ public virtual async Task UpdateAsync(string id, UserManagementUpdateOptio { if (plaintext.Password != null) { - request.AddQueryParam("password", plaintext.Password); + request.AddBodyParam("password", plaintext.Password); } } else if (options?.Password is UserManagementPasswordHashed hashed) { if (hashed.PasswordHash != null) { - request.AddQueryParam("password_hash", hashed.PasswordHash); + request.AddBodyParam("password_hash", hashed.PasswordHash); } - request.AddQueryParam("password_hash_type", JsonConvert.SerializeObject(hashed.PasswordHashType).Trim('"')); + request.AddBodyParam("password_hash_type", JsonConvert.SerializeObject(hashed.PasswordHashType).Trim('"')); } return await this.Client.MakeAPIRequest(request, cancellationToken); @@ -920,14 +920,14 @@ public virtual async Task CreateOrganizationMembershipAs { if (single.RoleSlug != null) { - request.AddQueryParam("role_slug", single.RoleSlug); + request.AddBodyParam("role_slug", single.RoleSlug); } } else if (options?.Role is UserManagementRoleMultiple multiple) { if (multiple.RoleSlugs != null) { - request.AddQueryParam("role_slugs", string.Join(",", multiple.RoleSlugs)); + request.AddBodyParam("role_slugs", multiple.RoleSlugs); } } @@ -982,14 +982,14 @@ public virtual async Task UpdateOrganizationMembershipAs { if (single.RoleSlug != null) { - request.AddQueryParam("role_slug", single.RoleSlug); + request.AddBodyParam("role_slug", single.RoleSlug); } } else if (options?.Role is UserManagementRoleMultiple multiple) { if (multiple.RoleSlugs != null) { - request.AddQueryParam("role_slugs", string.Join(",", multiple.RoleSlugs)); + request.AddBodyParam("role_slugs", multiple.RoleSlugs); } }