Skip to content

Commit 02985cd

Browse files
authored
Merge branch 'main' into dev/neeraj-sharma2592/fixNameAttributeInvalidExceptionBug1680
2 parents a241949 + 987df9e commit 02985cd

File tree

12 files changed

+936
-58
lines changed

12 files changed

+936
-58
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![Documentation](https://img.shields.io/badge/docs-website-%23fc0)](https://learn.microsoft.com/azure/data-api-builder/)
66
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
77

8-
Latest stable version of Data API builder is **0.8.50** [What's new?](https://learn.microsoft.com/azure/data-api-builder/whats-new)
8+
Latest stable version of Data API builder is **0.8.51** [What's new?](https://learn.microsoft.com/azure/data-api-builder/whats-new)
99

1010
## About
1111

src/Cli.Tests/ConfigGeneratorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ public void TestSpecialCharactersInConnectionString()
177177
}");
178178

179179
expectedRuntimeConfigJson = expectedRuntimeConfigJson.Replace(" ", string.Empty);
180-
expectedRuntimeConfigJson = expectedRuntimeConfigJson.Replace("\n", string.Empty);
181180
expectedRuntimeConfigJson = expectedRuntimeConfigJson.Replace("\r\n", string.Empty);
181+
expectedRuntimeConfigJson = expectedRuntimeConfigJson.Replace("\n", string.Empty);
182182

183183
Assert.IsTrue(TryGenerateConfig(options, _runtimeConfigLoader!, _fileSystem!));
184184

src/Cli.Tests/EndToEndTests.cs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public void TestInitForCosmosDBPostgreSql()
108108
[TestMethod]
109109
public void TestInitializingRestAndGraphQLGlobalSettings()
110110
{
111-
string[] args = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--connection-string", SAMPLE_TEST_CONN_STRING, "--database-type", "mssql", "--rest.path", "/rest-api", "--rest.disabled", "--graphql.path", "/graphql-api" };
111+
string[] args = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--connection-string", SAMPLE_TEST_CONN_STRING, "--database-type", "mssql", "--rest.path", "/rest-api", "--rest.enabled", "false", "--graphql.path", "/graphql-api" };
112112
Program.Execute(args, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
113113

114114
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(
@@ -768,4 +768,65 @@ public void TestBaseRouteIsConfigurableForSWA(string authProvider, bool isExcept
768768
Assert.AreEqual("/base-route", runtimeConfig.Runtime.BaseRoute);
769769
}
770770
}
771+
772+
[DataTestMethod]
773+
[DataRow(ApiType.REST, false, false, true, true, DisplayName = "Validate that REST endpoint is enabled when both enabled and disabled options are omitted from the init command.")]
774+
[DataRow(ApiType.REST, false, true, true, true, DisplayName = "Validate that REST endpoint is enabled when enabled option is set to true and disabled option is omitted from the init command.")]
775+
[DataRow(ApiType.REST, true, false, true, false, DisplayName = "Validate that REST endpoint is disabled when enabled option is omitted and disabled option is included in the init command.")]
776+
[DataRow(ApiType.REST, true, true, false, false, DisplayName = "Validate that REST endpoint is disabled when enabled option is set to false and disabled option is included in the init command.")]
777+
[DataRow(ApiType.REST, true, true, true, true, true, DisplayName = "Validate that config generation fails when enabled and disabled options provide conflicting values for REST endpoint.")]
778+
[DataRow(ApiType.GraphQL, false, false, true, true, DisplayName = "Validate that GraphQL endpoint is enabled when both enabled and disabled options are omitted from the init command.")]
779+
[DataRow(ApiType.GraphQL, false, true, true, true, DisplayName = "Validate that GraphQL endpoint is enabled when enabled option is set to true and disabled option is omitted from the init command.")]
780+
[DataRow(ApiType.GraphQL, true, false, true, false, DisplayName = "Validate that GraphQL endpoint is disabled when enabled option is omitted and disabled option is included in the init command.")]
781+
[DataRow(ApiType.GraphQL, true, true, false, false, DisplayName = "Validate that GraphQL endpoint is disabled when enabled option is set to false and disabled option is included in the init command.")]
782+
[DataRow(ApiType.GraphQL, true, true, true, true, true, DisplayName = "Validate that config generation fails when enabled and disabled options provide conflicting values for GraphQL endpoint.")]
783+
public void TestEnabledDisabledFlagsForApis(
784+
ApiType apiType,
785+
bool includeDisabledFlag,
786+
bool includeEnabledFlag,
787+
bool enabledFlagValue,
788+
bool expectedEnabledFlagValueInConfig,
789+
bool isExceptionExpected = false)
790+
{
791+
string apiName = apiType.ToString().ToLower();
792+
string disabledFlag = $"--{apiName}.disabled";
793+
string enabledFlag = $"--{apiName}.enabled";
794+
795+
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--database-type", "mssql", "--connection-string", SAMPLE_TEST_CONN_STRING };
796+
797+
string[] enabledDisabledArgs = { };
798+
799+
if (includeDisabledFlag)
800+
{
801+
enabledDisabledArgs = enabledDisabledArgs.Append(disabledFlag).ToArray();
802+
}
803+
804+
if (includeEnabledFlag)
805+
{
806+
enabledDisabledArgs = enabledDisabledArgs.Append(enabledFlag).ToArray();
807+
enabledDisabledArgs = enabledDisabledArgs.Append(enabledFlagValue.ToString()).ToArray();
808+
}
809+
810+
initArgs = initArgs.Concat(enabledDisabledArgs).ToArray();
811+
Program.Execute(initArgs, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
812+
if (isExceptionExpected)
813+
{
814+
Assert.IsFalse(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
815+
Assert.IsNull(runtimeConfig);
816+
}
817+
else
818+
{
819+
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
820+
Assert.IsNotNull(runtimeConfig);
821+
822+
if (apiType is ApiType.REST)
823+
{
824+
Assert.AreEqual(expectedEnabledFlagValueInConfig, runtimeConfig.Runtime.Rest.Enabled);
825+
}
826+
else
827+
{
828+
Assert.AreEqual(expectedEnabledFlagValueInConfig, runtimeConfig.Runtime.GraphQL.Enabled);
829+
}
830+
}
831+
}
771832
}

src/Cli.Tests/InitTests.cs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ bool expectSuccess
152152
hostMode: HostMode.Production,
153153
corsOrigin: null,
154154
authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
155+
restEnabled: CliBool.True,
156+
graphqlEnabled: CliBool.True,
155157
config: TEST_RUNTIME_CONFIG_FILE);
156158

157159
Assert.AreEqual(expectSuccess, TryCreateRuntimeConfig(options, _runtimeConfigLoader!, _fileSystem!, out RuntimeConfig? _));
@@ -196,16 +198,18 @@ public void VerifyRequiredOptionsForCosmosDbNoSqlDatabase(
196198
/// <summary>
197199
/// Verify that if both REST and GraphQL is disabled, we will get error.
198200
/// </summary>
199-
[DataRow(true, true, false, DisplayName = "Both REST and GraphQL disabled.")]
200-
[DataRow(true, false, true, DisplayName = "REST disabled, and GraphQL enabled.")]
201-
[DataRow(false, true, true, DisplayName = "REST enabled, and GraphQL disabled.")]
202-
[DataRow(false, false, true, DisplayName = "Both REST and GraphQL are enabled.")]
201+
[DataRow(CliBool.False, CliBool.False, false, DisplayName = "Both REST and GraphQL disabled.")]
202+
[DataRow(CliBool.False, CliBool.True, true, DisplayName = "REST disabled, and GraphQL enabled.")]
203+
[DataRow(CliBool.True, CliBool.False, true, DisplayName = "REST enabled, and GraphQL disabled.")]
204+
[DataRow(CliBool.True, CliBool.True, true, DisplayName = "Both REST and GraphQL are enabled.")]
203205
[DataTestMethod]
204206
public void EnsureFailureWhenBothRestAndGraphQLAreDisabled(
205-
bool RestDisabled,
206-
bool GraphQLDisabled,
207+
CliBool restEnabled,
208+
CliBool graphQLEnabled,
207209
bool expectedResult)
208210
{
211+
bool restDisabled = restEnabled is CliBool.False ? true : false;
212+
bool graphQLDisabled = graphQLEnabled is CliBool.False ? true : false;
209213
InitOptions options = new(
210214
databaseType: DatabaseType.MSSQL,
211215
connectionString: "testconnectionstring",
@@ -216,13 +220,37 @@ public void EnsureFailureWhenBothRestAndGraphQLAreDisabled(
216220
hostMode: HostMode.Production,
217221
corsOrigin: null,
218222
authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
219-
restDisabled: RestDisabled,
220-
graphqlDisabled: GraphQLDisabled,
223+
restEnabled: restEnabled,
224+
graphqlEnabled: graphQLEnabled,
225+
restDisabled: restDisabled,
226+
graphqlDisabled: graphQLDisabled,
221227
config: TEST_RUNTIME_CONFIG_FILE);
222228

223229
Assert.AreEqual(expectedResult, TryCreateRuntimeConfig(options, _runtimeConfigLoader!, _fileSystem!, out RuntimeConfig? _));
224230
}
225231

232+
/// <summary>
233+
/// Test to verify creation of initial config with special characters
234+
/// such as [!,@,#,$,%,^,&,*, ,(,)] in connection-string.
235+
/// </summary>
236+
[TestMethod]
237+
public Task TestSpecialCharactersInConnectionString()
238+
{
239+
InitOptions options = new(
240+
databaseType: DatabaseType.MSSQL,
241+
connectionString: "A!string@with#some$special%characters^to&check*proper(serialization)including space.",
242+
cosmosNoSqlDatabase: null,
243+
cosmosNoSqlContainer: null,
244+
graphQLSchemaPath: null,
245+
setSessionContext: false,
246+
hostMode: HostMode.Production,
247+
corsOrigin: null,
248+
authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
249+
config: TEST_RUNTIME_CONFIG_FILE);
250+
251+
return ExecuteVerifyTest(options);
252+
}
253+
226254
/// <summary>
227255
/// Test to verify that an error is thrown when user tries to
228256
/// initialize a config with a file name that already exists.

src/Cli/Commands/InitOptions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public InitOptions(
3434
bool restDisabled = false,
3535
string graphQLPath = GraphQLRuntimeOptions.DEFAULT_PATH,
3636
bool graphqlDisabled = false,
37+
CliBool restEnabled = CliBool.None,
38+
CliBool graphqlEnabled = CliBool.None,
3739
string? config = null)
3840
: base(config)
3941
{
@@ -53,6 +55,8 @@ public InitOptions(
5355
RestDisabled = restDisabled;
5456
GraphQLPath = graphQLPath;
5557
GraphQLDisabled = graphqlDisabled;
58+
RestEnabled = restEnabled;
59+
GraphQLEnabled = graphqlEnabled;
5660
}
5761

5862
[Option("database-type", Required = true, HelpText = "Type of database to connect. Supported values: mssql, cosmosdb_nosql, cosmosdb_postgresql, mysql, postgresql")]
@@ -103,6 +107,12 @@ public InitOptions(
103107
[Option("graphql.disabled", Default = false, Required = false, HelpText = "Disables GraphQL endpoint for all entities.")]
104108
public bool GraphQLDisabled { get; }
105109

110+
[Option("rest.enabled", Required = false, HelpText = "Enables REST endpoint for all entities. Supported values: true, false.")]
111+
public CliBool RestEnabled { get; }
112+
113+
[Option("graphql.enabled", Required = false, HelpText = "Enables GraphQL endpoint for all entities. Supported values: true, false.")]
114+
public CliBool GraphQLEnabled { get; }
115+
106116
public void Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem)
107117
{
108118
logger.LogInformation("{productName} {version}", PRODUCT_NAME, ProductInfo.GetProductVersion());

src/Cli/ConfigGenerator.cs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,33 @@ public static bool TryCreateRuntimeConfig(InitOptions options, FileSystemRuntime
9292
Dictionary<string, JsonElement> dbOptions = new();
9393

9494
HyphenatedNamingPolicy namingPolicy = new();
95-
bool restDisabled = options.RestDisabled;
95+
96+
// If --rest.disabled flag is included in the init command, we log a warning to not use this flag as it will be deprecated in future versions of DAB.
97+
if (options.RestDisabled is true)
98+
{
99+
_logger.LogWarning("The option --rest.disabled will be deprecated and support for the option will be removed in future versions of Data API builder." +
100+
" We recommend that you use the --rest.enabled option instead.");
101+
}
102+
103+
// If --graphql.disabled flag is included in the init command, we log a warning to not use this flag as it will be deprecated in future versions of DAB.
104+
if (options.GraphQLDisabled is true)
105+
{
106+
_logger.LogWarning("The option --graphql.disabled will be deprecated and support for the option will be removed in future versions of Data API builder." +
107+
" We recommend that you use the --graphql.enabled option instead.");
108+
}
109+
110+
bool restEnabled, graphQLEnabled;
111+
if (!TryDetermineIfApiIsEnabled(options.RestDisabled, options.RestEnabled, ApiType.REST, out restEnabled) ||
112+
!TryDetermineIfApiIsEnabled(options.GraphQLDisabled, options.GraphQLEnabled, ApiType.GraphQL, out graphQLEnabled))
113+
{
114+
return false;
115+
}
96116

97117
switch (dbType)
98118
{
99119
case DatabaseType.CosmosDB_NoSQL:
100120
// If cosmosdb_nosql is specified, rest is disabled.
101-
restDisabled = true;
121+
restEnabled = false;
102122

103123
string? cosmosDatabase = options.CosmosNoSqlDatabase;
104124
string? cosmosContainer = options.CosmosNoSqlContainer;
@@ -206,8 +226,8 @@ public static bool TryCreateRuntimeConfig(InitOptions options, FileSystemRuntime
206226
Schema: dabSchemaLink,
207227
DataSource: dataSource,
208228
Runtime: new(
209-
Rest: new(!restDisabled, restPath ?? RestRuntimeOptions.DEFAULT_PATH),
210-
GraphQL: new(!options.GraphQLDisabled, graphQLPath),
229+
Rest: new(restEnabled, restPath ?? RestRuntimeOptions.DEFAULT_PATH),
230+
GraphQL: new(graphQLEnabled, graphQLPath),
211231
Host: new(
212232
Cors: new(options.CorsOrigin?.ToArray() ?? Array.Empty<string>()),
213233
Authentication: new(
@@ -221,6 +241,45 @@ public static bool TryCreateRuntimeConfig(InitOptions options, FileSystemRuntime
221241
return true;
222242
}
223243

244+
/// <summary>
245+
/// Helper method to determine if the api is enabled or not based on the enabled/disabled options in the dab init command.
246+
/// The method also validates that there is no mismatch in semantics of enabling/disabling the REST/GraphQL API(s)
247+
/// based on the values supplied in the enabled/disabled options for the API in the init command.
248+
/// </summary>
249+
/// <param name="apiDisabledOptionValue">Value of disabled option as in the init command. If the option is omitted in the command, default value is assigned.</param>
250+
/// <param name="apiEnabledOptionValue">Value of enabled option as in the init command. If the option is omitted in the command, default value is assigned.</param>
251+
/// <param name="apiType">ApiType - REST/GraphQL.</param>
252+
/// <param name="isApiEnabled">Boolean value indicating whether the API endpoint is enabled or not.</param>
253+
private static bool TryDetermineIfApiIsEnabled(bool apiDisabledOptionValue, CliBool apiEnabledOptionValue, ApiType apiType, out bool isApiEnabled)
254+
{
255+
if (!apiDisabledOptionValue)
256+
{
257+
isApiEnabled = apiEnabledOptionValue == CliBool.False ? false : true;
258+
// This indicates that the --api.disabled option was not included in the init command.
259+
// In such a case, we honor the --api.enabled option.
260+
return true;
261+
}
262+
263+
if (apiEnabledOptionValue is CliBool.None)
264+
{
265+
// This means that the --api.enabled option was not included in the init command.
266+
isApiEnabled = !apiDisabledOptionValue;
267+
return true;
268+
}
269+
270+
// We hit this code only when both --api.enabled and --api.disabled flags are included in the init command.
271+
isApiEnabled = bool.Parse(apiEnabledOptionValue.ToString());
272+
if (apiDisabledOptionValue == isApiEnabled)
273+
{
274+
string apiName = apiType.ToString().ToLower();
275+
_logger.LogError($"Config generation failed due to mismatch in the semantics of enabling {apiType} API via " +
276+
$"--{apiName}.disabled and --{apiName}.enabled options");
277+
return false;
278+
}
279+
280+
return true;
281+
}
282+
224283
/// <summary>
225284
/// This method will add a new Entity with the given REST and GraphQL endpoints, source, and permissions.
226285
/// It also supports fields that needs to be included or excluded for a given role and operation.

src/Config/ObjectModel/CliBool.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
namespace Azure.DataApiBuilder.Config.ObjectModel
5+
{
6+
public enum CliBool
7+
{
8+
// The enum value None is required to determine whether a value was provided for a CLI option. In case the option is not included in the init command,
9+
// the enum gets assigned a value of an uninitialized enum i.e. 0 (here 'None').
10+
None,
11+
True,
12+
False
13+
}
14+
}

0 commit comments

Comments
 (0)