From 4d90bf2f6db5b2969ba49e26bdc9bc6e48df7420 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Mon, 12 Feb 2024 14:43:21 +0530 Subject: [PATCH 01/13] add querytest --- config-generators/cosmosdb_nosql-commands.txt | 6 ++- .../CosmosTests/MutationTests.cs | 5 +- .../CosmosTests/QueryFilterTests.cs | 36 +++++++++++-- src/Service.Tests/CosmosTests/TestBase.cs | 3 +- .../dab-config.CosmosDb_NoSql.json | 51 ++++++++++++++++++- 5 files changed, 93 insertions(+), 8 deletions(-) diff --git a/config-generators/cosmosdb_nosql-commands.txt b/config-generators/cosmosdb_nosql-commands.txt index e790d5c5f7..a3dbfc3dd2 100644 --- a/config-generators/cosmosdb_nosql-commands.txt +++ b/config-generators/cosmosdb_nosql-commands.txt @@ -17,4 +17,8 @@ add Sun --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.sun" --per update Sun --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "*" --fields.exclude "name" add AdditionalAttribute --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.additionalAttribute" --permissions "anonymous:*" --graphql "AdditionalAttribute:AdditionalAttributes" add MoonAdditionalAttribute --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moonAdditionalAttributes" --permissions "anonymous:*" --graphql "MoonAdditionalAttribute:MoonAdditionalAttributes" -add MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moreAttribute" --permissions "anonymous:*" --graphql "MoreAttribute:MoreAttributes" +add MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moreAttribute" --permissions "anonymous:delete" --graphql "MoreAttribute:MoreAttributes" +update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:create" --fields.include "id" --fields.exclude "name" +update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "id,type" --fields.exclude "name" +update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:update" --fields.exclude "*" +update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "authenticated:create,read,update,delete" diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index f8c8d90667..4a1a3e2a5f 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -13,10 +13,12 @@ using Azure.DataApiBuilder.Core.Configurations; using Azure.DataApiBuilder.Core.Resolvers; using Azure.DataApiBuilder.Service.Exceptions; +using Azure.DataApiBuilder.Service.GraphQLBuilder.Queries; using Azure.DataApiBuilder.Service.Tests.Configuration; using Microsoft.AspNetCore.TestHost; using Microsoft.Azure.Cosmos; using Microsoft.Extensions.DependencyInjection; +using Microsoft.OData.UriParser; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.CosmosTests @@ -31,6 +33,7 @@ public class MutationTests : TestBase name } }"; + private static readonly string _deletePlanetMutation = @" mutation ($id: ID!, $partitionKeyValue: String!) { deletePlanet (id: $id, _partitionKeyValue: $partitionKeyValue) { @@ -646,7 +649,7 @@ public void TestFixtureTearDown() { CosmosClientProvider cosmosClientProvider = _application.Services.GetService(); CosmosClient cosmosClient = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().GetDefaultDataSourceName()]; - cosmosClient.GetDatabase(DATABASE_NAME).GetContainer(_containerName).DeleteContainerAsync().Wait(); + // cosmosClient.GetDatabase(DATABASE_NAME).GetContainer(_containerName).DeleteContainerAsync().Wait(); } } } diff --git a/src/Service.Tests/CosmosTests/QueryFilterTests.cs b/src/Service.Tests/CosmosTests/QueryFilterTests.cs index c3d2cf65ca..7bdd7e85b9 100644 --- a/src/Service.Tests/CosmosTests/QueryFilterTests.cs +++ b/src/Service.Tests/CosmosTests/QueryFilterTests.cs @@ -176,7 +176,11 @@ public async Task TestStringFiltersOnTwoLevelNestedArrayType() "JOIN d IN b.moreAttributes " + "WHERE d.name = \"moonattr0\""; - await ExecuteAndValidateResult(_graphQLQueryName, gqlQuery, dbQueryWithJoin); + await ExecuteAndValidateResult( + _graphQLQueryName, + gqlQuery, + dbQueryWithJoin, + authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString())); } /// @@ -262,9 +266,9 @@ public async Task TestStringMultiFiltersOnArrayTypeWithOrCondition() await ExecuteAndValidateResult(_graphQLQueryName, gqlQuery, dbQueryWithJoin); } - private async Task ExecuteAndValidateResult(string graphQLQueryName, string gqlQuery, string dbQuery) + private async Task ExecuteAndValidateResult(string graphQLQueryName, string gqlQuery, string dbQuery, string authToken = null) { - JsonElement actual = await ExecuteGraphQLRequestAsync(graphQLQueryName, query: gqlQuery); + JsonElement actual = await ExecuteGraphQLRequestAsync(graphQLQueryName, query: gqlQuery, authToken: authToken); JsonDocument expected = await ExecuteCosmosRequestAsync(dbQuery, _pageSize, null, _containerName); ValidateResults(actual.GetProperty("items"), expected.RootElement); } @@ -1009,6 +1013,32 @@ public async Task TestQueryFilterNestedFieldAuth_UnauthorizedNestedField() Assert.IsTrue(errorMessage.Contains(DataApiBuilderException.GRAPHQL_FILTER_FIELD_AUTHZ_FAILURE)); } + [TestMethod] + public async Task TestQueryFilterNestedArrayFieldAuth_UnauthorizedNestedField() + { + // Run query + string gqlQuery = @"{ + planets(first: 10, " + QueryBuilder.FILTER_FIELD_NAME + + @" : {moons: {moonAdditionalAttributes: {moreAttributes: {name: {eq: ""moonattr0""}}}}}) + { + items { + name + } + } + }"; + + string clientRoleHeader = AuthorizationType.Anonymous.ToString(); + JsonElement response = await ExecuteGraphQLRequestAsync( + queryName: _graphQLQueryName, + query: gqlQuery, + authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader), + clientRoleHeader: clientRoleHeader); + + // Validate the result contains the GraphQL authorization error code. + string errorMessage = response.ToString(); + Assert.IsTrue(errorMessage.Contains(DataApiBuilderException.GRAPHQL_FILTER_FIELD_AUTHZ_FAILURE)); + } + /// /// This is for testing the scenario when the filter field is authorized, but the query field is unauthorized. /// For "type" field in "Earth" GraphQL type, it has @authorize(policy: "authenticated") directive in the test schema, diff --git a/src/Service.Tests/CosmosTests/TestBase.cs b/src/Service.Tests/CosmosTests/TestBase.cs index 06c4af0b5d..5d92acd5be 100644 --- a/src/Service.Tests/CosmosTests/TestBase.cs +++ b/src/Service.Tests/CosmosTests/TestBase.cs @@ -97,7 +97,8 @@ type MoonAdditionalAttribute @model(name:""MoonAdditionalAttribute"") { type MoreAttribute @model(name:""MoreAttrAlias"") { id : ID, - name : String + name : String, + type: String @authorize(roles: [""authenticated""]) }"; private static string[] _planets = { "Earth", "Mars", "Jupiter", "Tatooine", "Endor", "Dagobah", "Hoth", "Bespin", "Spec%ial" }; diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json index c00081b626..fcf9455d36 100644 --- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json +++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json @@ -445,11 +445,58 @@ "role": "anonymous", "actions": [ { - "action": "*" + "action": "update", + "fields": { + "exclude": [ + "*" + ] + } + }, + { + "action": "read", + "fields": { + "exclude": [ + "name" + ], + "include": [ + "id" + ] + } + }, + { + "action": "create", + "fields": { + "exclude": [ + "name" + ], + "include": [ + "id" + ] + } + }, + { + "action": "delete" + } + ] + }, + { + "role": "authenticated", + "actions": [ + { + "action": "create" + }, + { + "action": "read" + }, + { + "action": "update" + }, + { + "action": "delete" } ] } ] } } -} \ No newline at end of file +} From 832446f81b8e4c0f1cb4fac940388dc89972ebc0 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 13 Feb 2024 17:21:28 +0530 Subject: [PATCH 02/13] add mutation auth tests --- .../CosmosTests/MutationTests.cs | 154 ++++++++++++++---- .../dab-config.CosmosDb_NoSql.json | 84 ++++++++-- 2 files changed, 190 insertions(+), 48 deletions(-) diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index 4a1a3e2a5f..ebaeac6ed5 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -13,12 +13,10 @@ using Azure.DataApiBuilder.Core.Configurations; using Azure.DataApiBuilder.Core.Resolvers; using Azure.DataApiBuilder.Service.Exceptions; -using Azure.DataApiBuilder.Service.GraphQLBuilder.Queries; using Azure.DataApiBuilder.Service.Tests.Configuration; using Microsoft.AspNetCore.TestHost; using Microsoft.Azure.Cosmos; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OData.UriParser; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.CosmosTests @@ -255,62 +253,76 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() } /// - /// Mutation can be performed on the authorized fields because the - /// field `id` is an included field for the create operation on the anonymous role defined - /// for entity 'earth' + /// Create Mutation performed on the fields with different auth permissions + /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - public async Task CanCreateItemWithAuthorizedFields() + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude and include fields + [DataRow("authenticated", null)] // full permission + [DataRow("only-create-role", "The mutation operation createEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // if only create permission is there + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude wildcard + [DataRow("only-update-role", "The current user is not authorized to access this resource" )] // if create permission is not there + public async Task CreateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Run mutation Add Earth; string id = Guid.NewGuid().ToString(); + const string name = "test_name"; string mutation = $@" mutation {{ - createEarth (item: {{ id: ""{id}"" }}) {{ + createEarth (item: {{ id: ""{id}"", name: ""{name}"" }}) {{ id + name }} }}"; - JsonElement response = await ExecuteGraphQLRequestAsync("createEarth", mutation, variables: new()); + string authtoken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName); + JsonElement response = await ExecuteGraphQLRequestAsync("createEarth", mutation, variables: new(), authToken: authtoken, clientRoleHeader: roleName); - // Validate results - Assert.AreEqual(id, response.GetProperty("id").GetString()); + // Validate the result contains the GraphQL authorization error code. + Console.WriteLine(response.ToString()); + if (string.IsNullOrEmpty(expectedErrorMessage)) + { + Assert.AreEqual(id, response.GetProperty("id").GetString()); + } + else + { + // Validate the result contains the GraphQL authorization error code. + string errorMessage = response.ToString(); + Assert.IsTrue(errorMessage.Contains(expectedErrorMessage)); + } } /// - /// Mutation performed on the unauthorized fields throws permission denied error because the - /// field `name` is an excluded field for the create operation on the anonymous role defined - /// for entity 'earth' + /// Update Mutation performed on the fields with different auth permissions + /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - public async Task CreateItemWithUnauthorizedFieldsReturnsError() + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude and include fields + [DataRow("authenticated", null)] // full permission + [DataRow("only-update-role", "The mutation operation updateEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // if only update permission is there + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude wildcard + [DataRow("only-create-role", "The current user is not authorized to access this resource")] // if update permission is not there + public async Task UpdateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { - // Run mutation Add Earth; + // Create an item with "Authenticated" role string id = Guid.NewGuid().ToString(); const string name = "test_name"; - string mutation = $@" + string createMutation = $@" mutation {{ createEarth (item: {{ id: ""{id}"", name: ""{name}"" }}) {{ id name }} }}"; - JsonElement response = await ExecuteGraphQLRequestAsync("createEarth", mutation, variables: new()); - // Validate the result contains the GraphQL authorization error code. - string errorMessage = response.ToString(); - Assert.IsTrue(errorMessage.Contains(DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)); - } + JsonElement createResponse = await ExecuteGraphQLRequestAsync("createEarth", createMutation, + variables: new(), + authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString()), + clientRoleHeader: AuthorizationType.Authenticated.ToString()); + + // Making sure item is created successfully + Assert.AreEqual(id, createResponse.GetProperty("id").GetString()); - /// - /// Mutation performed on the unauthorized fields throws permission denied error because the - /// wildcard is used in the excluded field for the update operation on the anonymous role defined - /// for entity 'earth' - /// - [TestMethod] - public async Task UpdateItemWithUnauthorizedWildCardReturnsError() - { // Run mutation Update Earth; - string id = Guid.NewGuid().ToString(); string mutation = @" mutation ($id: ID!, $partitionKeyValue: String!, $item: UpdateEarthInput!) { updateEarth (id: $id, _partitionKeyValue: $partitionKeyValue, item: $item) { @@ -324,11 +336,83 @@ public async Task UpdateItemWithUnauthorizedWildCardReturnsError() name = "new_name" }; - JsonElement response = await ExecuteGraphQLRequestAsync("updateEarth", mutation, variables: new() { { "id", id }, { "partitionKeyValue", id }, { "item", update } }); + string authtoken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName); + JsonElement response = await ExecuteGraphQLRequestAsync( + queryName: "updateEarth", + query: mutation, + variables: new() { { "id", id }, { "partitionKeyValue", id }, { "item", update } }, + authToken: authtoken, + clientRoleHeader: roleName); - // Validate the result contains the GraphQL authorization error code. - string errorMessage = response.ToString(); - Assert.IsTrue(errorMessage.Contains(DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)); + if (string.IsNullOrEmpty(expectedErrorMessage)) + { + Assert.AreEqual(id, response.GetProperty("id").GetString()); + } + else + { + // Validate the result contains the GraphQL authorization error code. + string errorMessage = response.ToString(); + Assert.IsTrue(errorMessage.Contains(expectedErrorMessage)); + } + } + + /// + /// Delete Mutation performed on the fields with different auth permissions + /// It throws permission denied error if role doesn't have permission to perform the operation + /// + [TestMethod] + [DataRow("field-mutation-with-read-permission", null)] // exclude and include fields. Response is BLANK. + [DataRow("authenticated", null)] // full permission. Response is BLANK + [DataRow("only-delete-role", "The mutation operation deleteEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // if only update permission is there + [DataRow("wildcard-exclude-fields-role", "The mutation operation deleteEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // exclude wildcard + [DataRow("only-create-role", "The current user is not authorized to access this resource")] // if update permission is not there + public async Task DeleteItemWithAuthPermissions(string roleName, string expectedErrorMessage) + { + // Create an item with "Authenticated" role + string id = Guid.NewGuid().ToString(); + const string name = "test_name"; + string createMutation = $@" +mutation {{ + createEarth (item: {{ id: ""{id}"", name: ""{name}"" }}) {{ + id + name + }} +}}"; + + JsonElement createResponse = await ExecuteGraphQLRequestAsync("createEarth", createMutation, + variables: new(), + authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString()), + clientRoleHeader: AuthorizationType.Authenticated.ToString()); + + // Making sure item is created successfully + Assert.AreEqual(id, createResponse.GetProperty("id").GetString()); + + // Run mutation Update Earth; + string mutation = @" +mutation ($id: ID!, $partitionKeyValue: String!) { + deleteEarth (id: $id, _partitionKeyValue: $partitionKeyValue) { + id + name + } +}"; + string authtoken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName); + JsonElement response = await ExecuteGraphQLRequestAsync( + queryName: "deleteEarth", + query: mutation, + variables: new() { { "id", id }, { "partitionKeyValue", id }}, + authToken: authtoken, + clientRoleHeader: roleName); + + if (string.IsNullOrEmpty(expectedErrorMessage)) + { + Assert.IsTrue(string.IsNullOrEmpty(response.ToString())); + } + else + { + // Validate the result contains the GraphQL authorization error code. + string errorMessage = response.ToString(); + Assert.IsTrue(errorMessage.Contains(expectedErrorMessage)); + } } /// @@ -649,7 +733,7 @@ public void TestFixtureTearDown() { CosmosClientProvider cosmosClientProvider = _application.Services.GetService(); CosmosClient cosmosClient = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().GetDefaultDataSourceName()]; - // cosmosClient.GetDatabase(DATABASE_NAME).GetContainer(_containerName).DeleteContainerAsync().Wait(); + cosmosClient.GetDatabase(DATABASE_NAME).GetContainer(_containerName).DeleteContainerAsync().Wait(); } } } diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json index fcf9455d36..7075d12f0f 100644 --- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json +++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json @@ -277,18 +277,41 @@ }, "permissions": [ { - "role": "anonymous", + "role": "authenticated", "actions": [ { - "action": "update", + "action": "create" + }, + { + "action": "read" + }, + { + "action": "update" + }, + { + "action": "delete" + } + ] + }, + { + "role": "field-mutation-with-read-permission", + "actions": [ + { + "action": "read" + }, + { + "action": "create", "fields": { "exclude": [ - "*" + "name" + ], + "include": [ + "id" ] } }, { - "action": "read", + "action": "update", "fields": { "exclude": [ "name" @@ -300,33 +323,68 @@ } }, { - "action": "create", + "action": "delete", "fields": { "exclude": [ "name" ], "include": [ - "id" + "id", + "type" ] } - }, - { - "action": "delete" } ] }, { - "role": "authenticated", + "role": "wildcard-exclude-fields-role", "actions": [ { - "action": "create" + "action": "update", + "fields": { + "exclude": [ + "*" + ] + } }, { - "action": "read" + "action": "create", + "fields": { + "exclude": [ + "*" + ] + } }, + { + "action": "delete", + "fields": { + "exclude": [ + "*" + ] + } + } + + ] + }, + { + "role": "only-create-role", + "actions": [ + { + "action": "create" + } + ] + }, + { + "role": "only-update-role", + "actions": [ { "action": "update" - }, + } + ] + }, + { + "role": "only-delete-role", + "actions": [ { "action": "delete" } From a71232a654a41d832e0fcc86b5a05cdd7aa41cb1 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 11:23:33 +0530 Subject: [PATCH 03/13] fix tests --- .../CosmosTests/MutationTests.cs | 34 +++++++++++-------- .../CosmosTests/QueryFilterTests.cs | 16 ++++----- .../dab-config.CosmosDb_NoSql.json | 17 ++++++++++ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index ebaeac6ed5..c1ccc1f6d1 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -257,11 +257,12 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude and include fields - [DataRow("authenticated", null)] // full permission - [DataRow("only-create-role", "The mutation operation createEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // if only create permission is there - [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude wildcard - [DataRow("only-update-role", "The current user is not authorized to access this resource" )] // if create permission is not there + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = " exclude and include fields")] + [DataRow("authenticated", null, DisplayName = "full permission")] + [DataRow("only-create-role", "The mutation operation createEarth was successful " + + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "if only create permission is there")] + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "exclude wildcard")] + [DataRow("only-update-role", "The current user is not authorized to access this resource", DisplayName = "if create permission is not there")] public async Task CreateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Run mutation Add Earth; @@ -296,11 +297,12 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude and include fields - [DataRow("authenticated", null)] // full permission - [DataRow("only-update-role", "The mutation operation updateEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // if only update permission is there - [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE)] // exclude wildcard - [DataRow("only-create-role", "The current user is not authorized to access this resource")] // if update permission is not there + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "exclude and include fields")] + [DataRow("authenticated", null, DisplayName = "full permission")] + [DataRow("only-update-role", "The mutation operation updateEarth was successful " + + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "if only update permission is there")] + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "exclude wildcard")] + [DataRow("only-create-role", "The current user is not authorized to access this resource", DisplayName = "if update permission is not there")] public async Task UpdateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role @@ -361,11 +363,13 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", null)] // exclude and include fields. Response is BLANK. - [DataRow("authenticated", null)] // full permission. Response is BLANK - [DataRow("only-delete-role", "The mutation operation deleteEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // if only update permission is there - [DataRow("wildcard-exclude-fields-role", "The mutation operation deleteEarth was successful but the current user is unauthorized to view the response due to lack of read permissions")] // exclude wildcard - [DataRow("only-create-role", "The current user is not authorized to access this resource")] // if update permission is not there + [DataRow("field-mutation-with-read-permission", null, DisplayName = " exclude and include fields. Response is BLANK")] + [DataRow("authenticated", null, DisplayName = "full permission. Response is BLANK")] + [DataRow("only-delete-role", "The mutation operation deleteEarth was successful " + + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "if only update permission is there")] + [DataRow("wildcard-exclude-fields-role", "The mutation operation deleteEarth was successful " + + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "exclude wildcard")] + [DataRow("only-create-role", "The current user is not authorized to access this resource", DisplayName = "if update permission is not there")] public async Task DeleteItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role diff --git a/src/Service.Tests/CosmosTests/QueryFilterTests.cs b/src/Service.Tests/CosmosTests/QueryFilterTests.cs index 7bdd7e85b9..e6e86ba6b4 100644 --- a/src/Service.Tests/CosmosTests/QueryFilterTests.cs +++ b/src/Service.Tests/CosmosTests/QueryFilterTests.cs @@ -176,11 +176,7 @@ public async Task TestStringFiltersOnTwoLevelNestedArrayType() "JOIN d IN b.moreAttributes " + "WHERE d.name = \"moonattr0\""; - await ExecuteAndValidateResult( - _graphQLQueryName, - gqlQuery, - dbQueryWithJoin, - authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString())); + await ExecuteAndValidateResult(_graphQLQueryName, gqlQuery, dbQueryWithJoin); } /// @@ -266,8 +262,9 @@ public async Task TestStringMultiFiltersOnArrayTypeWithOrCondition() await ExecuteAndValidateResult(_graphQLQueryName, gqlQuery, dbQueryWithJoin); } - private async Task ExecuteAndValidateResult(string graphQLQueryName, string gqlQuery, string dbQuery, string authToken = null) + private async Task ExecuteAndValidateResult(string graphQLQueryName, string gqlQuery, string dbQuery) { + string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString()); JsonElement actual = await ExecuteGraphQLRequestAsync(graphQLQueryName, query: gqlQuery, authToken: authToken); JsonDocument expected = await ExecuteCosmosRequestAsync(dbQuery, _pageSize, null, _containerName); ValidateResults(actual.GetProperty("items"), expected.RootElement); @@ -916,7 +913,7 @@ public async Task TestQueryFilterFieldAuth_UnauthorizedField() } } }"; - string clientRoleHeader = AuthorizationType.Anonymous.ToString(); + string clientRoleHeader = "limited-read-role"; JsonElement response = await ExecuteGraphQLRequestAsync( queryName: "earths", query: gqlQuery, @@ -974,7 +971,8 @@ public async Task TestQueryFilterNestedFieldAuth_AuthorizedNestedField() } }"; - JsonElement actual = await ExecuteGraphQLRequestAsync(_graphQLQueryName, query: gqlQuery); + string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString()); + JsonElement actual = await ExecuteGraphQLRequestAsync(_graphQLQueryName, query: gqlQuery, authToken: authToken); Assert.AreEqual(actual.GetProperty("items")[0].GetProperty("earth").GetProperty("id").ToString(), _idList[0]); } @@ -1000,7 +998,7 @@ public async Task TestQueryFilterNestedFieldAuth_UnauthorizedNestedField() } }"; - string clientRoleHeader = AuthorizationType.Anonymous.ToString(); + string clientRoleHeader = "limited-read-role"; JsonElement response = await ExecuteGraphQLRequestAsync( queryName: _graphQLQueryName, query: gqlQuery, diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json index 7075d12f0f..e22798cada 100644 --- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json +++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json @@ -293,6 +293,23 @@ } ] }, + { + "role": "limited-read-role", + "actions": [ + { + "action": "read", + "fields": { + "exclude": [ + "name" + ], + "include": [ + "id", + "type" + ] + } + } + ] + }, { "role": "field-mutation-with-read-permission", "actions": [ From aee662ec58fdfe58e85252b82920bdf9daf47fad Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 11:37:17 +0530 Subject: [PATCH 04/13] config generator text --- config-generators/cosmosdb_nosql-commands.txt | 18 ++-- .../dab-config.CosmosDb_NoSql.json | 83 ++++++++++--------- 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/config-generators/cosmosdb_nosql-commands.txt b/config-generators/cosmosdb_nosql-commands.txt index a3dbfc3dd2..52a1198abf 100644 --- a/config-generators/cosmosdb_nosql-commands.txt +++ b/config-generators/cosmosdb_nosql-commands.txt @@ -8,17 +8,25 @@ update StarAlias --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.s add TagAlias --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.tag" --permissions "anonymous:create,read,update,delete" --graphql "Tag:Tags" add Moon --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moon" --permissions "anonymous:create,read,update,delete" --graphql true update Moon --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moon" --permissions "authenticated:create,read,update,delete" -add Earth --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.earth" --permissions "anonymous:delete" --graphql "Earth:Earths" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:create" --fields.include "id" --fields.exclude "name" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "id,type" --fields.exclude "name" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:update" --fields.exclude "*" +add Earth --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.earth" --permissions "field-mutation-with-read-permission:read" --graphql "Earth:Earths" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "field-mutation-with-read-permission:create" --fields.include "id" --fields.exclude "name" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "field-mutation-with-read-permission:delete" --fields.include "id,type" --fields.exclude "name" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "field-mutation-with-read-permission:update" --fields.include "id,type" --fields.exclude "name" update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "authenticated:create,read,update,delete" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "limited-read-role:read" --fields.include "id,type" --fields.exclude "name" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-exclude-fields-role:create" --fields.exclude "*" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-exclude-fields-role:update" --fields.exclude "*" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-exclude-fields-role:delete" --fields.exclude "*" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-exclude-fields-role:read" --fields.exclude "*" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-create-role:create" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-update-role:update" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-delete-role:delete" add Sun --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.sun" --permissions "anonymous:create,update,delete" --graphql true update Sun --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "*" --fields.exclude "name" add AdditionalAttribute --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.additionalAttribute" --permissions "anonymous:*" --graphql "AdditionalAttribute:AdditionalAttributes" add MoonAdditionalAttribute --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moonAdditionalAttributes" --permissions "anonymous:*" --graphql "MoonAdditionalAttribute:MoonAdditionalAttributes" add MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.moreAttribute" --permissions "anonymous:delete" --graphql "MoreAttribute:MoreAttributes" update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:create" --fields.include "id" --fields.exclude "name" -update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "id,type" --fields.exclude "name" +update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "id" --fields.exclude "name" update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:update" --fields.exclude "*" update MoreAttrAlias --config "dab-config.CosmosDb_NoSql.json" --permissions "authenticated:create,read,update,delete" diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json index e22798cada..d079cb6bbc 100644 --- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json +++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json @@ -277,27 +277,10 @@ }, "permissions": [ { - "role": "authenticated", - "actions": [ - { - "action": "create" - }, - { - "action": "read" - }, - { - "action": "update" - }, - { - "action": "delete" - } - ] - }, - { - "role": "limited-read-role", + "role": "field-mutation-with-read-permission", "actions": [ { - "action": "read", + "action": "update", "fields": { "exclude": [ "name" @@ -307,40 +290,57 @@ "type" ] } - } - ] - }, - { - "role": "field-mutation-with-read-permission", - "actions": [ - { - "action": "read" }, { - "action": "create", + "action": "delete", "fields": { "exclude": [ "name" ], "include": [ - "id" + "id", + "type" ] } }, { - "action": "update", + "action": "create", "fields": { "exclude": [ "name" ], "include": [ - "id", - "type" + "id" ] } }, { - "action": "delete", + "action": "read" + } + ] + }, + { + "role": "authenticated", + "actions": [ + { + "action": "create" + }, + { + "action": "read" + }, + { + "action": "update" + }, + { + "action": "delete" + } + ] + }, + { + "role": "limited-read-role", + "actions": [ + { + "action": "read", "fields": { "exclude": [ "name" @@ -357,7 +357,7 @@ "role": "wildcard-exclude-fields-role", "actions": [ { - "action": "update", + "action": "read", "fields": { "exclude": [ "*" @@ -365,7 +365,7 @@ } }, { - "action": "create", + "action": "delete", "fields": { "exclude": [ "*" @@ -373,14 +373,21 @@ } }, { - "action": "delete", + "action": "update", + "fields": { + "exclude": [ + "*" + ] + } + }, + { + "action": "create", "fields": { "exclude": [ "*" ] } } - ] }, { @@ -574,4 +581,4 @@ ] } } -} +} \ No newline at end of file From bcb5bbd28a01ce90b6b0ee9d2581f015516f1a4a Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 12:37:03 +0530 Subject: [PATCH 05/13] updated display names --- .../CosmosTests/MutationTests.cs | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index c1ccc1f6d1..a3d181f8ba 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -39,6 +39,8 @@ public class MutationTests : TestBase name } }"; + private const string USER_NOT_AUTHORIZED = "The current user is not authorized to access this resource"; + private const string NO_ERROR_MESSAGE = null; /// /// Executes once for the test. @@ -257,12 +259,12 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = " exclude and include fields")] - [DataRow("authenticated", null, DisplayName = "full permission")] + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] + [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] [DataRow("only-create-role", "The mutation operation createEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "if only create permission is there")] - [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "exclude wildcard")] - [DataRow("only-update-role", "The current user is not authorized to access this resource", DisplayName = "if create permission is not there")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY create permission is there")] + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When create permission is there at entity level but all the fields are excluded using wildcard")] + [DataRow("only-update-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When create permission is NOT there")] public async Task CreateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Run mutation Add Earth; @@ -297,12 +299,12 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "exclude and include fields")] - [DataRow("authenticated", null, DisplayName = "full permission")] + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] + [DataRow("authenticated", NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] [DataRow("only-update-role", "The mutation operation updateEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "if only update permission is there")] - [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "exclude wildcard")] - [DataRow("only-create-role", "The current user is not authorized to access this resource", DisplayName = "if update permission is not there")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY update permission is there")] + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When update permission is there at entity level but all the fields are excluded using wildcard")] + [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When update permission is NOT there")] public async Task UpdateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role @@ -363,13 +365,12 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", null, DisplayName = " exclude and include fields. Response is BLANK")] - [DataRow("authenticated", null, DisplayName = "full permission. Response is BLANK")] + [DataRow("field-mutation-with-read-permission", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When there is limited permission at field level but have full read permission, Response is EMPTY string.")] + [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction, Response is EMPTY string.")] [DataRow("only-delete-role", "The mutation operation deleteEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "if only update permission is there")] - [DataRow("wildcard-exclude-fields-role", "The mutation operation deleteEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "exclude wildcard")] - [DataRow("only-create-role", "The current user is not authorized to access this resource", DisplayName = "if update permission is not there")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY delete permission is there")] + [DataRow("wildcard-exclude-fields-role", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When delete permission is there at entity level but all the fields are excluded using wildcard")] + [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When delete permission is NOT there")] public async Task DeleteItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role @@ -407,6 +408,8 @@ public async Task DeleteItemWithAuthPermissions(string roleName, string expected authToken: authtoken, clientRoleHeader: roleName); + Console.WriteLine(response.ToString()); + if (string.IsNullOrEmpty(expectedErrorMessage)) { Assert.IsTrue(string.IsNullOrEmpty(response.ToString())); From 42369bc4482a72a5f8dd1503319caa206bc92e23 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 17:02:23 +0530 Subject: [PATCH 06/13] adding tests for item level authorization --- config-generators/cosmosdb_nosql-commands.txt | 6 +++- .../CosmosTests/MutationTests.cs | 3 ++ .../dab-config.CosmosDb_NoSql.json | 28 ++++++++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/config-generators/cosmosdb_nosql-commands.txt b/config-generators/cosmosdb_nosql-commands.txt index 52a1198abf..b58e4b5f3b 100644 --- a/config-generators/cosmosdb_nosql-commands.txt +++ b/config-generators/cosmosdb_nosql-commands.txt @@ -20,7 +20,11 @@ update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-e update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-exclude-fields-role:read" --fields.exclude "*" update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-create-role:create" update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-update-role:update" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-delete-role:delete" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-delete-role:delete" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:create" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:update" --policy-database "@item.name contains 'test_name'" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:read" --policy-database "@item.name contains 'test_name'" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:delete" --policy-database "@claims.UserId eq @item.createdby" add Sun --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.sun" --permissions "anonymous:create,update,delete" --graphql true update Sun --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "*" --fields.exclude "name" add AdditionalAttribute --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.additionalAttribute" --permissions "anonymous:*" --graphql "AdditionalAttribute:AdditionalAttributes" diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index a3d181f8ba..dc5d40eab1 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -257,6 +257,7 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() /// /// Create Mutation performed on the fields with different auth permissions /// It throws permission denied error if role doesn't have permission to perform the operation + /// 'item-level-permission-role' is not applicable for create operation /// [TestMethod] [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] @@ -305,6 +306,7 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY update permission is there")] [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When update permission is there at entity level but all the fields are excluded using wildcard")] [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When update permission is NOT there")] + [DataRow("item-level-permission-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When item level permission is NOT there")] public async Task UpdateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role @@ -348,6 +350,7 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected authToken: authtoken, clientRoleHeader: roleName); + Console.WriteLine(response.ToString()); if (string.IsNullOrEmpty(expectedErrorMessage)) { Assert.AreEqual(id, response.GetProperty("id").GetString()); diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json index d079cb6bbc..99d697068c 100644 --- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json +++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json @@ -413,6 +413,32 @@ "action": "delete" } ] + }, + { + "role": "item-level-permission-role", + "actions": [ + { + "action": "create" + }, + { + "action": "read", + "policy": { + "database": "@item.name contains 'test_name'" + } + }, + { + "action": "update", + "policy": { + "database": "@item.name eq 'sourabh'" + } + }, + { + "action": "delete", + "policy": { + "database": "@claims.UserId eq @item.createdby" + } + } + ] } ] }, @@ -581,4 +607,4 @@ ] } } -} \ No newline at end of file +} From 733879f9903f83681acb31a3d3cd83e3a6a9030a Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 22:20:31 +0530 Subject: [PATCH 07/13] remove item level permission tests --- config-generators/cosmosdb_nosql-commands.txt | 6 +--- .../CosmosTests/MutationTests.cs | 1 - .../dab-config.CosmosDb_NoSql.json | 28 +------------------ 3 files changed, 2 insertions(+), 33 deletions(-) diff --git a/config-generators/cosmosdb_nosql-commands.txt b/config-generators/cosmosdb_nosql-commands.txt index b58e4b5f3b..52a1198abf 100644 --- a/config-generators/cosmosdb_nosql-commands.txt +++ b/config-generators/cosmosdb_nosql-commands.txt @@ -20,11 +20,7 @@ update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-e update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "wildcard-exclude-fields-role:read" --fields.exclude "*" update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-create-role:create" update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-update-role:update" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-delete-role:delete" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:create" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:update" --policy-database "@item.name contains 'test_name'" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:read" --policy-database "@item.name contains 'test_name'" -update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "item-level-permission-role:delete" --policy-database "@claims.UserId eq @item.createdby" +update Earth --config "dab-config.CosmosDb_NoSql.json" --permissions "only-delete-role:delete" add Sun --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.sun" --permissions "anonymous:create,update,delete" --graphql true update Sun --config "dab-config.CosmosDb_NoSql.json" --permissions "anonymous:read" --fields.include "*" --fields.exclude "name" add AdditionalAttribute --config "dab-config.CosmosDb_NoSql.json" --source "graphqldb.additionalAttribute" --permissions "anonymous:*" --graphql "AdditionalAttribute:AdditionalAttributes" diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index dc5d40eab1..e16cef1a0e 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -306,7 +306,6 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY update permission is there")] [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When update permission is there at entity level but all the fields are excluded using wildcard")] [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When update permission is NOT there")] - [DataRow("item-level-permission-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When item level permission is NOT there")] public async Task UpdateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json index 99d697068c..d079cb6bbc 100644 --- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json +++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json @@ -413,32 +413,6 @@ "action": "delete" } ] - }, - { - "role": "item-level-permission-role", - "actions": [ - { - "action": "create" - }, - { - "action": "read", - "policy": { - "database": "@item.name contains 'test_name'" - } - }, - { - "action": "update", - "policy": { - "database": "@item.name eq 'sourabh'" - } - }, - { - "action": "delete", - "policy": { - "database": "@claims.UserId eq @item.createdby" - } - } - ] } ] }, @@ -607,4 +581,4 @@ ] } } -} +} \ No newline at end of file From 7a7f1d73cfe3419c9c2de10e47f1f8600f74d2a4 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 22:48:33 +0530 Subject: [PATCH 08/13] text file update --- ...ReadingRuntimeConfigForCosmos.verified.txt | 139 +++++++++++++++++- 1 file changed, 134 insertions(+), 5 deletions(-) diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt index 989b0a5310..b77019e6c8 100644 --- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt +++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt @@ -271,18 +271,22 @@ }, Permissions: [ { - Role: anonymous, + Role: field-mutation-with-read-permission, Actions: [ { Action: Update, Fields: { Exclude: [ - * + name + ], + Include: [ + id, + type ] } }, { - Action: Read, + Action: Delete, Fields: { Exclude: [ name @@ -305,7 +309,7 @@ } }, { - Action: Delete + Action: Read } ] }, @@ -325,6 +329,84 @@ Action: Delete } ] + }, + { + Role: limited-read-role, + Actions: [ + { + Action: Read, + Fields: { + Exclude: [ + name + ], + Include: [ + id, + type + ] + } + } + ] + }, + { + Role: wildcard-exclude-fields-role, + Actions: [ + { + Action: Read, + Fields: { + Exclude: [ + * + ] + } + }, + { + Action: Delete, + Fields: { + Exclude: [ + * + ] + } + }, + { + Action: Update, + Fields: { + Exclude: [ + * + ] + } + }, + { + Action: Create, + Fields: { + Exclude: [ + * + ] + } + } + ] + }, + { + Role: only-create-role, + Actions: [ + { + Action: Create + } + ] + }, + { + Role: only-update-role, + Actions: [ + { + Action: Update + } + ] + }, + { + Role: only-delete-role, + Actions: [ + { + Action: Delete + } + ] } ] } @@ -439,7 +521,54 @@ Role: anonymous, Actions: [ { - Action: * + Action: Update, + Fields: { + Exclude: [ + * + ] + } + }, + { + Action: Read, + Fields: { + Exclude: [ + name + ], + Include: [ + id + ] + } + }, + { + Action: Create, + Fields: { + Exclude: [ + name + ], + Include: [ + id + ] + } + }, + { + Action: Delete + } + ] + }, + { + Role: authenticated, + Actions: [ + { + Action: Create + }, + { + Action: Read + }, + { + Action: Update + }, + { + Action: Delete } ] } From 260e016f75a857db864d3e6a7812c9401c523177 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 14 Feb 2024 22:58:56 +0530 Subject: [PATCH 09/13] fix formatting --- src/Service.Tests/CosmosTests/MutationTests.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index e16cef1a0e..5dafc1c108 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -261,7 +261,7 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() /// [TestMethod] [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] - [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] + [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] [DataRow("only-create-role", "The mutation operation createEarth was successful " + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY create permission is there")] [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When create permission is there at entity level but all the fields are excluded using wildcard")] @@ -300,7 +300,7 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] [DataRow("authenticated", NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] [DataRow("only-update-role", "The mutation operation updateEarth was successful " + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY update permission is there")] @@ -349,7 +349,7 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected authToken: authtoken, clientRoleHeader: roleName); - Console.WriteLine(response.ToString()); + Console.WriteLine(response.ToString()); if (string.IsNullOrEmpty(expectedErrorMessage)) { Assert.AreEqual(id, response.GetProperty("id").GetString()); @@ -372,7 +372,7 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected [DataRow("only-delete-role", "The mutation operation deleteEarth was successful " + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY delete permission is there")] [DataRow("wildcard-exclude-fields-role", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When delete permission is there at entity level but all the fields are excluded using wildcard")] - [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When delete permission is NOT there")] + [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When delete permission is NOT there")] public async Task DeleteItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role @@ -406,7 +406,7 @@ public async Task DeleteItemWithAuthPermissions(string roleName, string expected JsonElement response = await ExecuteGraphQLRequestAsync( queryName: "deleteEarth", query: mutation, - variables: new() { { "id", id }, { "partitionKeyValue", id }}, + variables: new() { { "id", id }, { "partitionKeyValue", id } }, authToken: authtoken, clientRoleHeader: roleName); From 8e18b2a2ace9238a255d0637854fb12e816ddfbd Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 15 Feb 2024 09:00:53 +0530 Subject: [PATCH 10/13] changed display nake --- .../CosmosTests/MutationTests.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index 5dafc1c108..c366f2d3ee 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -257,15 +257,14 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() /// /// Create Mutation performed on the fields with different auth permissions /// It throws permission denied error if role doesn't have permission to perform the operation - /// 'item-level-permission-role' is not applicable for create operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] - [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "AuthZ failure for create mutation because of reference to excluded/disallowed fields.")] + [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "AuthZ success when role has no create/read operation restrictions.")] [DataRow("only-create-role", "The mutation operation createEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY create permission is there")] - [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When create permission is there at entity level but all the fields are excluded using wildcard")] - [DataRow("only-update-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When create permission is NOT there")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "AuthZ failure but sucessful operation where role has ONLY create permission and NO read permission.")] + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "AuthZ failure for create mutation because of reference to excluded/disallowed field using wildcard.")] + [DataRow("only-update-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "AuthZ failure when create permission is NOT there.")] public async Task CreateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Run mutation Add Earth; @@ -300,12 +299,12 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When there is limited permission at field level but have full read permission")] - [DataRow("authenticated", NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction")] + [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "AuthZ failure for update mutation because of reference to excluded/disallowed fields.")] + [DataRow("authenticated", NO_ERROR_MESSAGE, DisplayName = "AuthZ success when role has no update/read operation restrictions.")] [DataRow("only-update-role", "The mutation operation updateEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY update permission is there")] - [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "When update permission is there at entity level but all the fields are excluded using wildcard")] - [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When update permission is NOT there")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "AuthZ failure but sucessful operation where role has ONLY update permission and NO read permission.")] + [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "AuthZ failure for update mutation because of reference to excluded/disallowed field using wildcard.")] + [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "AuthZ failure when update permission is NOT there.")] public async Task UpdateItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role @@ -367,12 +366,12 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected /// It throws permission denied error if role doesn't have permission to perform the operation /// [TestMethod] - [DataRow("field-mutation-with-read-permission", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When there is limited permission at field level but have full read permission, Response is EMPTY string.")] - [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When CRUD permission is there without any restriction, Response is EMPTY string.")] + [DataRow("field-mutation-with-read-permission", MutationTests.NO_ERROR_MESSAGE, DisplayName = "AuthZ success and blank response for delete mutation because of reference to excluded/disallowed fields.")] + [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "AuthZ success and blank response when role has no delete operation restrictions.")] [DataRow("only-delete-role", "The mutation operation deleteEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "When ONLY delete permission is there")] - [DataRow("wildcard-exclude-fields-role", MutationTests.NO_ERROR_MESSAGE, DisplayName = "When delete permission is there at entity level but all the fields are excluded using wildcard")] - [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "When delete permission is NOT there")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "AuthZ failure but sucessful operation where role has ONLY delete permission and NO read permission.")] + [DataRow("wildcard-exclude-fields-role", MutationTests.NO_ERROR_MESSAGE, DisplayName = "AuthZ success and blank response for delete mutation because of reference to excluded/disallowed fields using wildcard")] + [DataRow("only-create-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "AuthZ failure when delete permission is NOT there.")] public async Task DeleteItemWithAuthPermissions(string roleName, string expectedErrorMessage) { // Create an item with "Authenticated" role From fcdcadfac0f3266c83cc945ffd2da6419050acf8 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 15 Feb 2024 11:09:17 +0530 Subject: [PATCH 11/13] fix test doc --- src/Service.Tests/CosmosTests/QueryFilterTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service.Tests/CosmosTests/QueryFilterTests.cs b/src/Service.Tests/CosmosTests/QueryFilterTests.cs index e6e86ba6b4..48867ad0dc 100644 --- a/src/Service.Tests/CosmosTests/QueryFilterTests.cs +++ b/src/Service.Tests/CosmosTests/QueryFilterTests.cs @@ -899,7 +899,7 @@ public async Task TestQueryFilterFieldAuth_AuthorizedField() /// /// Tests that the field level query filter fails authorization when filter fields are /// unauthorized because the field 'name' on object type 'earth' is an excluded field of the read - /// operation permissions defined for the anonymous role. + /// operation permissions defined for a role. /// [TestMethod] public async Task TestQueryFilterFieldAuth_UnauthorizedField() From 06089c44cf8bd4f837d89928758d066fd0cf222e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 15 Feb 2024 22:50:10 +0530 Subject: [PATCH 12/13] Update src/Service.Tests/CosmosTests/MutationTests.cs Co-authored-by: Sean Leonard --- src/Service.Tests/CosmosTests/MutationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs index c366f2d3ee..a5dd6bad2b 100644 --- a/src/Service.Tests/CosmosTests/MutationTests.cs +++ b/src/Service.Tests/CosmosTests/MutationTests.cs @@ -262,7 +262,7 @@ public async Task MutationMissingRequiredPartitionKeyValueReturnError() [DataRow("field-mutation-with-read-permission", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "AuthZ failure for create mutation because of reference to excluded/disallowed fields.")] [DataRow("authenticated", MutationTests.NO_ERROR_MESSAGE, DisplayName = "AuthZ success when role has no create/read operation restrictions.")] [DataRow("only-create-role", "The mutation operation createEarth was successful " + - "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "AuthZ failure but sucessful operation where role has ONLY create permission and NO read permission.")] + "but the current user is unauthorized to view the response due to lack of read permissions", DisplayName = "Successful create operation but AuthZ failure for read when role has ONLY create permission and NO read permission.")] [DataRow("wildcard-exclude-fields-role", DataApiBuilderException.GRAPHQL_MUTATION_FIELD_AUTHZ_FAILURE, DisplayName = "AuthZ failure for create mutation because of reference to excluded/disallowed field using wildcard.")] [DataRow("only-update-role", MutationTests.USER_NOT_AUTHORIZED, DisplayName = "AuthZ failure when create permission is NOT there.")] public async Task CreateItemWithAuthPermissions(string roleName, string expectedErrorMessage) From bf448fa55aeea7f07a3a152f516485d4956dd467 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 16 Feb 2024 07:19:44 +0530 Subject: [PATCH 13/13] updated comment --- src/Service.Tests/CosmosTests/QueryFilterTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Service.Tests/CosmosTests/QueryFilterTests.cs b/src/Service.Tests/CosmosTests/QueryFilterTests.cs index 48867ad0dc..e5a247a58d 100644 --- a/src/Service.Tests/CosmosTests/QueryFilterTests.cs +++ b/src/Service.Tests/CosmosTests/QueryFilterTests.cs @@ -1011,6 +1011,11 @@ public async Task TestQueryFilterNestedFieldAuth_UnauthorizedNestedField() Assert.IsTrue(errorMessage.Contains(DataApiBuilderException.GRAPHQL_FILTER_FIELD_AUTHZ_FAILURE)); } + /// + /// Tests that the nested field level query filter fails authorization when nested object is + /// unauthorized. Here, Nested array type 'moreAttributes' is avaliable for 'Authenticated' role only and + /// we are trying to access it with 'anonymous' role. + /// [TestMethod] public async Task TestQueryFilterNestedArrayFieldAuth_UnauthorizedNestedField() {