diff --git a/sdk/storage/azure-storage-files-datalake/CHANGELOG.md b/sdk/storage/azure-storage-files-datalake/CHANGELOG.md index 0ca668984..cd3cd0410 100644 --- a/sdk/storage/azure-storage-files-datalake/CHANGELOG.md +++ b/sdk/storage/azure-storage-files-datalake/CHANGELOG.md @@ -15,6 +15,8 @@ - Added `Metadata`, `AccessType`, `HasImmutabilityPolicy`, `HasLegalHold`, `LeaseDuration`, `LeaseState` and `LeaseStatus` to `FileSystemItem`. - Added new type `LeaseDurationType` to indicate if a lease duration is fixed or infinite. - Added `RequestId` in each return type for REST API calls, except for concurrent APIs. +- Added `UpdateAccessControlListRecursiveSinglePage` to update the access control recursively for a datalake path. +- Added `RemoveAccessControlListRecursiveSinglePage` to remove the access control recursively for a datalake path. ### Breaking Changes @@ -32,6 +34,9 @@ - Changed all previous `LeaseDuration` members to a new type named `LeaseDurationType`. - `startsOn` parameter for `GetUserDelegationKey` was changed to optional. - Removed `PreviousContinuationToken` from `ListFileSystemsSinglePageResult`. +- Changed `SetAccessControlRecursive` to `SetAccessControlRecursiveListSinglePage`, to mark that it is a single page operation, and removed the `mode` parameter, separated the modify/delete functionality to two new APIs. +- Moved `SetAccessControlRecursiveListSinglePage` to `DataLakePathClient`. +- Changed `MaxRecord` to `MaxEntries`, `ForceFlag` to `ContinueOnFailure` to be more accurate names. ### Other Changes and Improvements diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_directory_client.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_directory_client.hpp index b8f78f6cc..204d0acc3 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_directory_client.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_directory_client.hpp @@ -157,28 +157,6 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { bool recursive, const DeleteDataLakeDirectoryOptions& options = DeleteDataLakeDirectoryOptions()) const; - /** - * @brief Sets POSIX access control rights on files and directories under given directory - * recursively. - * @param mode Mode PathSetAccessControlRecursiveMode::Set sets POSIX access control rights on - * files and directories, PathSetAccessControlRecursiveMode::Modify modifies one or more POSIX - * access control rights that pre-exist on files and directories, - * PathSetAccessControlRecursiveMode::Remove removes one or more POSIX access control rights - * that were present earlier on files and directories - * @param acls Sets POSIX access control rights on files and directories. Each access control - * entry (ACE) consists of a scope, a type, a user or group identifier, and permissions. - * @param options Optional parameters to set an access control recursively to the resource the - * directory points to. - * @return Azure::Core::Response - * @remark This request is sent to dfs endpoint. - */ - Azure::Core::Response - SetAccessControlRecursive( - Models::PathSetAccessControlRecursiveMode mode, - std::vector acls, - const SetDataLakeDirectoryAccessControlRecursiveOptions& options - = SetDataLakeDirectoryAccessControlRecursiveOptions()) const; - /** * @brief List the paths in this file system. * @param recursive If "true", all paths are listed; otherwise, the list will only @@ -200,6 +178,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { : DataLakePathClient(std::move(dfsUrl), std::move(blobClient), pipeline) { } + friend class DataLakeFileSystemClient; }; }}}} // namespace Azure::Storage::Files::DataLake diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_options.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_options.hpp index 01820a353..5e005bb6b 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_options.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_options.hpp @@ -697,9 +697,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { }; /** - * @brief Optional parameters for PathClient::SetAccessControlRecursive + * @brief Optional parameters for DirectoryClient::SetAccessControlRecursiveListSinglePage */ - struct SetDataLakeDirectoryAccessControlRecursiveOptions + struct SetDataLakePathAccessControlRecursiveListSinglePageOptions { /** * @brief Context for cancelling long running operations. @@ -721,18 +721,24 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { * be applied. If omitted or greater than 2,000, the request will process up to 2,000 * items. */ - Azure::Core::Nullable MaxRecords; + Azure::Core::Nullable MaxEntries; /** - * @brief Optional. Valid for "SetAccessControlRecursive" operation. If set to false, the - * operation will terminate quickly on encountering user errors (4XX). If true, the operation - * will ignore user errors and proceed with the operation on other sub-entities of the - * directory. Continuation token will only be returned when forceFlag is true in case of user - * errors. If not set the default value is false for this. + * @brief Optional. If set to false, the operation will terminate quickly on encountering user + * errors (4XX). If true, the operation will ignore user errors and proceed with the operation + * on other sub-entities of the directory. Continuation token will only be returned when + * ContinueOnFailure is true in case of user errors. If not set the default value is false for + * this. */ - Azure::Core::Nullable ForceFlag; + Azure::Core::Nullable ContinueOnFailure; }; + using UpdateDataLakePathAccessControlRecursiveListSinglePageOptions + = SetDataLakePathAccessControlRecursiveListSinglePageOptions; + + using RemoveDataLakePathAccessControlRecursiveListSinglePageOptions + = SetDataLakePathAccessControlRecursiveListSinglePageOptions; + using CreateDataLakeFileOptions = CreateDataLakePathOptions; using CreateDataLakeDirectoryOptions = CreateDataLakePathOptions; diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_path_client.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_path_client.hpp index 769628f7f..5ff8b173b 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_path_client.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_path_client.hpp @@ -204,6 +204,69 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Metadata metadata, const SetDataLakePathMetadataOptions& options = SetDataLakePathMetadataOptions()) const; + /** + * @brief Sets POSIX access control rights on files and directories under given directory + * recursively. + * @param acls Sets POSIX access control rights on files and directories. Each access control + * entry (ACE) consists of a scope, a type, a user or group identifier, and permissions. + * @param options Optional parameters to set an access control recursively to the resource the + * directory points to. + * @return + * Azure::Core::Response + * @remark This request is sent to dfs endpoint. + */ + Azure::Core::Response + SetAccessControlRecursiveListSinglePage( + std::vector acls, + const SetDataLakePathAccessControlRecursiveListSinglePageOptions& options + = SetDataLakePathAccessControlRecursiveListSinglePageOptions()) const + { + return SetAccessControlRecursiveListSinglePageInternal( + Models::PathSetAccessControlRecursiveMode::Set, acls, options); + } + + /** + * @brief Updates POSIX access control rights on files and directories under given directory + * recursively. + * @param acls Updates POSIX access control rights on files and directories. Each access control + * entry (ACE) consists of a scope, a type, a user or group identifier, and permissions. + * @param options Optional parameters to set an access control recursively to the resource the + * directory points to. + * @return + * Azure::Core::Response + * @remark This request is sent to dfs endpoint. + */ + Azure::Core::Response + UpdateAccessControlRecursiveListSinglePage( + std::vector acls, + const UpdateDataLakePathAccessControlRecursiveListSinglePageOptions& options + = UpdateDataLakePathAccessControlRecursiveListSinglePageOptions()) const + { + return SetAccessControlRecursiveListSinglePageInternal( + Models::PathSetAccessControlRecursiveMode::Modify, acls, options); + } + + /** + * @brief Removes POSIX access control rights on files and directories under given directory + * recursively. + * @param acls Removes POSIX access control rights on files and directories. Each access control + * entry (ACE) consists of a scope, a type, a user or group identifier, and permissions. + * @param options Optional parameters to set an access control recursively to the resource the + * directory points to. + * @return + * Azure::Core::Response + * @remark This request is sent to dfs endpoint. + */ + Azure::Core::Response + RemoveAccessControlRecursiveListSinglePage( + std::vector acls, + const RemoveDataLakePathAccessControlRecursiveListSinglePageOptions& options + = RemoveDataLakePathAccessControlRecursiveListSinglePageOptions()) const + { + return SetAccessControlRecursiveListSinglePageInternal( + Models::PathSetAccessControlRecursiveMode::Remove, acls, options); + } + protected: Azure::Core::Http::Url m_dfsUrl; Blobs::BlobClient m_blobClient; @@ -218,6 +281,13 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { } + Azure::Core::Response + SetAccessControlRecursiveListSinglePageInternal( + Models::PathSetAccessControlRecursiveMode mode, + std::vector acls, + const SetDataLakePathAccessControlRecursiveListSinglePageOptions& options + = SetDataLakePathAccessControlRecursiveListSinglePageOptions()) const; + friend class DataLakeFileSystemClient; friend class DataLakeLeaseClient; }; diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp index d00a55c5e..a8ddf9ddf 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp @@ -260,8 +260,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam std::string RequestId; }; - using SetDataLakeDirectoryAccessControlRecursiveResult + using SetDataLakePathAccessControlRecursiveListSinglePageResult = Details::PathSetAccessControlRecursiveResult; + using UpdateDataLakePathAccessControlRecursiveListSinglePageResult + = SetDataLakePathAccessControlRecursiveListSinglePageResult; + using RemoveDataLakePathAccessControlRecursiveListSinglePageResult + = SetDataLakePathAccessControlRecursiveListSinglePageResult; using CreateDataLakeDirectoryResult = CreateDataLakePathResult; using DeleteDataLakeDirectoryResult = DeleteDataLakePathResult; diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_directory_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_directory_client.cpp index a1e1100ee..824b08046 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_directory_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_directory_client.cpp @@ -208,22 +208,6 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { return DataLakePathClient::DeleteIfExists(deleteOptions); } - Azure::Core::Response - DataLakeDirectoryClient::SetAccessControlRecursive( - Models::PathSetAccessControlRecursiveMode mode, - std::vector acls, - const SetDataLakeDirectoryAccessControlRecursiveOptions& options) const - { - Details::DataLakeRestClient::Path::SetAccessControlRecursiveOptions protocolLayerOptions; - protocolLayerOptions.Mode = mode; - protocolLayerOptions.ContinuationToken = options.ContinuationToken; - protocolLayerOptions.MaxRecords = options.MaxRecords; - protocolLayerOptions.ForceFlag = options.ForceFlag; - protocolLayerOptions.Acl = Models::Acl::SerializeAcls(acls); - return Details::DataLakeRestClient::Path::SetAccessControlRecursive( - m_dfsUrl, *m_pipeline, options.Context, protocolLayerOptions); - } - Azure::Core::Response DataLakeDirectoryClient:: ListPathsSinglePage(bool recursive, const ListPathsSinglePageOptions& options) const { diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp index 9e450dd17..369a6b6ca 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_path_client.cpp @@ -457,4 +457,21 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { return Azure::Core::Response( std::move(ret), result.ExtractRawResponse()); } + + Azure::Core::Response + DataLakePathClient::SetAccessControlRecursiveListSinglePageInternal( + Models::PathSetAccessControlRecursiveMode mode, + std::vector acls, + const SetDataLakePathAccessControlRecursiveListSinglePageOptions& options) const + { + Details::DataLakeRestClient::Path::SetAccessControlRecursiveOptions protocolLayerOptions; + protocolLayerOptions.Mode = mode; + protocolLayerOptions.ContinuationToken = options.ContinuationToken; + protocolLayerOptions.MaxRecords = options.MaxEntries; + protocolLayerOptions.ForceFlag = options.ContinueOnFailure; + protocolLayerOptions.Acl = Models::Acl::SerializeAcls(acls); + return Details::DataLakeRestClient::Path::SetAccessControlRecursive( + m_dfsUrl, *m_pipeline, options.Context, protocolLayerOptions); + } + }}}} // namespace Azure::Storage::Files::DataLake diff --git a/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp b/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp index eb2c7f2d4..0d2e22c53 100644 --- a/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/datalake_directory_client_test.cpp @@ -326,7 +326,7 @@ namespace Azure { namespace Storage { namespace Test { } } - TEST_F(DataLakeDirectoryClientTest, DirectorySetAccessControlRecursive) + TEST_F(DataLakeDirectoryClientTest, DirectoryAccessControlRecursive) { // Setup directories. auto rootDirectoryName = RandomString(); @@ -342,11 +342,9 @@ namespace Azure { namespace Storage { namespace Test { directoryClient2.Create(); { - // Set/Get Acls recursive works. + // Set Acls recursive. std::vector acls = GetValidAcls(); - EXPECT_NO_THROW(directoryClient1.SetAccessControlList(acls)); - EXPECT_NO_THROW(rootDirectoryClient.SetAccessControlRecursive( - Files::DataLake::Models::PathSetAccessControlRecursiveMode::Modify, acls)); + EXPECT_NO_THROW(rootDirectoryClient.SetAccessControlRecursiveListSinglePage(acls)); std::vector resultAcls1; std::vector resultAcls2; EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls); @@ -364,12 +362,243 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ(iter->Permissions, acl.Permissions); } } + { + // Update Acls recursive. + std::vector originalAcls = GetValidAcls(); + Files::DataLake::Models::Acl newAcl; + newAcl.Type = "group"; + newAcl.Id = ""; + newAcl.Permissions = "rw-"; + std::vector acls; + acls.emplace_back(std::move(newAcl)); + EXPECT_NO_THROW(rootDirectoryClient.UpdateAccessControlRecursiveListSinglePage(acls)); + std::vector resultAcls1; + std::vector resultAcls2; + EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls); + EXPECT_NO_THROW(resultAcls2 = directoryClient2.GetAccessControlList()->Acls); + for (const auto& acl : resultAcls2) + { + auto iter = std::find_if( + resultAcls1.begin(), + resultAcls1.end(), + [&acl](const Files::DataLake::Models::Acl& targetAcl) { + return (targetAcl.Type == acl.Type) && (targetAcl.Id == acl.Id) + && (targetAcl.Scope == acl.Scope); + }); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ(iter->Permissions, acl.Permissions); + } + { + // verify group has changed + auto groupFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "group"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), groupFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ("rw-", iter->Permissions); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), groupFinder); + EXPECT_TRUE(iter != resultAcls2.end()); + EXPECT_EQ("rw-", iter->Permissions); + } + { + // verify other has not changed + { + auto otherFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "other"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), otherFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), otherFinder); + EXPECT_TRUE(iter != resultAcls2.end()); + EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions); + } + { + auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "user"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + if (iter->Id == originalAcls[0].Id) + { + EXPECT_EQ(originalAcls[0].Permissions, iter->Permissions); + } + else + { + EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions); + } + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder); + EXPECT_TRUE(iter != resultAcls2.end()); + if (iter->Id == originalAcls[0].Id) + { + EXPECT_EQ(originalAcls[0].Permissions, iter->Permissions); + } + else + { + EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions); + } + } + } + } + { + // Remove Acls recursive. + std::vector originalAcls = GetValidAcls(); + Files::DataLake::Models::Acl removeAcl; + removeAcl.Type = "user"; + removeAcl.Id = "72a3f86f-271f-439e-b031-25678907d381"; + std::vector acls; + acls.emplace_back(std::move(removeAcl)); + EXPECT_NO_THROW(rootDirectoryClient.RemoveAccessControlRecursiveListSinglePage(acls)); + std::vector resultAcls1; + std::vector resultAcls2; + EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls); + EXPECT_NO_THROW(resultAcls2 = directoryClient2.GetAccessControlList()->Acls); + for (const auto& acl : resultAcls2) + { + auto iter = std::find_if( + resultAcls1.begin(), + resultAcls1.end(), + [&acl](const Files::DataLake::Models::Acl& targetAcl) { + return (targetAcl.Type == acl.Type) && (targetAcl.Id == acl.Id) + && (targetAcl.Scope == acl.Scope); + }); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ(iter->Permissions, acl.Permissions); + } + { + // verify group policy has been removed. + auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "user" && targetAcl.Id == "72a3f86f-271f-439e-b031-25678907d381"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder); + EXPECT_TRUE(iter == resultAcls1.end()); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder); + EXPECT_TRUE(iter == resultAcls2.end()); + } + { + // verify other has not changed + { + auto otherFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "other"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), otherFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), otherFinder); + EXPECT_TRUE(iter != resultAcls2.end()); + EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions); + } + { + auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "user"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ(originalAcls[1].Id, iter->Id); + EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder); + EXPECT_TRUE(iter != resultAcls2.end()); + EXPECT_EQ(originalAcls[1].Id, iter->Id); + EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions); + } + } + } + { + // Set Acls recursive, with new set of acls + std::vector acls; + { + Files::DataLake::Models::Acl newAcl; + newAcl.Type = "user"; + newAcl.Permissions = "rw-"; + acls.emplace_back(std::move(newAcl)); + } + { + Files::DataLake::Models::Acl newAcl; + newAcl.Type = "group"; + newAcl.Permissions = "rw-"; + acls.emplace_back(std::move(newAcl)); + } + { + Files::DataLake::Models::Acl newAcl; + newAcl.Type = "other"; + newAcl.Permissions = "rw-"; + acls.emplace_back(std::move(newAcl)); + } + (rootDirectoryClient.SetAccessControlRecursiveListSinglePage(acls)); + std::vector resultAcls1; + std::vector resultAcls2; + EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls); + EXPECT_NO_THROW(resultAcls2 = directoryClient2.GetAccessControlList()->Acls); + for (const auto& acl : resultAcls2) + { + auto iter = std::find_if( + resultAcls1.begin(), + resultAcls1.end(), + [&acl](const Files::DataLake::Models::Acl& targetAcl) { + return (targetAcl.Type == acl.Type) && (targetAcl.Id == acl.Id) + && (targetAcl.Scope == acl.Scope); + }); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ(iter->Permissions, acl.Permissions); + } + { + // verify group has changed + auto groupFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "group"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), groupFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ("rw-", iter->Permissions); + EXPECT_EQ("", iter->Id); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), groupFinder); + EXPECT_EQ("rw-", iter->Permissions); + EXPECT_EQ("", iter->Id); + } + { + // verify other has changed + auto otherFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "other"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), otherFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ("rw-", iter->Permissions); + EXPECT_EQ("", iter->Id); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), otherFinder); + EXPECT_EQ("rw-", iter->Permissions); + EXPECT_EQ("", iter->Id); + } + { + // verify user has only one entry + std::vector originalAcls = GetValidAcls(); + auto userFinder = [&originalAcls](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "user" && targetAcl.Id == originalAcls[0].Id; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder); + EXPECT_TRUE(iter == resultAcls1.end()); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder); + EXPECT_TRUE(iter == resultAcls2.end()); + } + { + // verify user has changed + auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) { + return targetAcl.Type == "user"; + }; + auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder); + EXPECT_TRUE(iter != resultAcls1.end()); + EXPECT_EQ("rw-", iter->Permissions); + EXPECT_EQ("", iter->Id); + iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder); + EXPECT_EQ("rw-", iter->Permissions); + EXPECT_EQ("", iter->Id); + } + } } TEST_F(DataLakeDirectoryClientTest, ConstructorsWorks) { { - // Create from connection string validates static creator function and shared key constructor. + // Create from connection string validates static creator function and shared key + // constructor. auto directoryName = RandomString(10); auto connectionStringClient = Azure::Storage::Files::DataLake::DataLakeDirectoryClient::CreateFromConnectionString( @@ -415,5 +644,4 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_NO_THROW(anonymousClient.GetProperties()); } } - }}} // namespace Azure::Storage::Test