Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/Core/Services/OpenAPI/OpenApiDocumentor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1135,9 +1135,9 @@ private static bool IsRequestBodyRequired(SourceDefinition sourceDef, bool consi
StoredProcedureDefinition spDef = (StoredProcedureDefinition)sourceDef;
foreach (KeyValuePair<string, ParameterDefinition> parameterMetadata in spDef.Parameters)
{
// A parameter which does not have any of the following properties
// A parameter which is explicitly marked required or has no default value
// results in the body being required so that a value can be provided.
if (!parameterMetadata.Value.HasConfigDefault)
if (parameterMetadata.Value.Required ?? !parameterMetadata.Value.HasConfigDefault)
{
requestBodyRequired = true;
break;
Expand Down Expand Up @@ -1422,7 +1422,10 @@ private static OpenApiSchema CreateSpRequestComponentSchema(Dictionary<string, P
Default = def.Default is not null ? new OpenApiString(def.Default) : null
});

if (def.Required == true)
// A parameter is required when it is explicitly marked required in the runtime config,
// or when no default value is available, in which case a value must be provided in the
// request body. This mirrors the logic used by IsRequestBodyRequired.
if (def.Required ?? !def.HasConfigDefault)
{
Comment thread
souvikghosh04 marked this conversation as resolved.
required.Add(parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,51 @@ public static void CreateEntities()
Relationships: null,
Description: "Represents a stored procedure for books");

// Entity whose "title" parameter has a config-provided default value.
// Because a default is available, "title" must not be flagged as required, while
// "publisher_id" (no default) must remain required.
Entity entity2 = new(
Source: new(
Object: "insert_book",
EntitySourceType.StoredProcedure,
Parameters: new List<ParameterMetadata>
{
new() { Name = "title", Default = "Sample Title" }
},
KeyFields: null),
Fields: null,
GraphQL: new(Singular: null, Plural: null, Enabled: false),
Rest: new(Methods: EntityRestOptions.DEFAULT_SUPPORTED_VERBS),
Permissions: OpenApiTestBootstrap.CreateBasicPermissions(),
Mappings: null,
Relationships: null,
Description: "Stored procedure with a parameter default");

// Entity whose "title" parameter is explicitly marked required: false in config.
// Even though it has no default value, the explicit override must be honored so that only
// "id" (no default, no override) remains required.
Entity entity3 = new(
Source: new(
Object: "update_book_title",
EntitySourceType.StoredProcedure,
Parameters: new List<ParameterMetadata>
{
new() { Name = "title", Required = false }
},
KeyFields: null),
Fields: null,
GraphQL: new(Singular: null, Plural: null, Enabled: false),
Rest: new(Methods: EntityRestOptions.DEFAULT_SUPPORTED_VERBS),
Permissions: OpenApiTestBootstrap.CreateBasicPermissions(),
Mappings: null,
Relationships: null,
Description: "Stored procedure with an explicit required override");

Dictionary<string, Entity> entities = new()
{
{ "sp1", entity1 }
{ "sp1", entity1 },
{ "sp2", entity2 },
{ "sp3", entity3 }
};

_runtimeEntities = new(entities);
Expand All @@ -74,13 +116,19 @@ public static void CreateEntities()
/// <summary>
/// Validates that the generated request body references stored procedure parameters
/// and not result set columns.
/// Also validates that the request body schema component flags the expected parameters
/// as required: a parameter is required when it has no default value and is not explicitly
/// marked required: false in the runtime config.
/// </summary>
/// <param name="entityName">Entity name</param>
/// <param name="expectedParameters">Expected parameters in request body</param>
/// <param name="expectedParametersJsonTypes">Expected parameter value types in request body.</param>
[DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, DisplayName = "Validate request body parameters and parameter Json data types.")]
/// <param name="expectedRequiredParameters">Expected parameters flagged as required in the schema component.</param>
[DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, new string[] { "title", "publisher_name" }, DisplayName = "Parameters without defaults are all required.")]
[DataRow("sp2", new string[] { "title", "publisher_id" }, new string[] { "string", "integer" }, new string[] { "publisher_id" }, DisplayName = "Parameter with a config default is not required.")]
[DataRow("sp3", new string[] { "id", "title" }, new string[] { "integer", "string" }, new string[] { "id" }, DisplayName = "Parameter explicitly marked required: false is not required.")]
[DataTestMethod]
public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes)
public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes, string[] expectedRequiredParameters)
{
Dictionary<OperationType, bool> configuredOperations = ResolveConfiguredOperations(_runtimeEntities[entityName]);
foreach (OperationType opType in configuredOperations.Keys)
Expand All @@ -101,6 +149,13 @@ public void ValidateRequestBodyContents(string entityName, string[] expectedPara
string expectedSchemaReferenceId = $"{entityName}{OpenApiDocumentor.SP_REQUEST_SUFFIX}";

ValidateOpenApiReferenceContents(schemaComponentReference, expectedSchemaReferenceId, expectedParameters, expectedParametersJsonTypes);

// Validate that the expected parameters are marked as required in the schema component.
ISet<string> requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required ?? new HashSet<string>();
CollectionAssert.AreEquivalent(
expectedRequiredParameters,
requiredParameters.ToArray(),
message: "Unexpected required parameters in request body schema component.");
}
}

Expand Down