Skip to content

Commit a30eb8b

Browse files
authored
feat(GCS+gRPC): implement DeleteDefaultObjectAcl() (#9473)
1 parent 2160d58 commit a30eb8b

3 files changed

Lines changed: 95 additions & 2 deletions

File tree

google/cloud/storage/internal/grpc_client.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -874,8 +874,27 @@ StatusOr<ObjectAccessControl> GrpcClient::CreateDefaultObjectAcl(
874874
}
875875

876876
StatusOr<EmptyResponse> GrpcClient::DeleteDefaultObjectAcl(
877-
DeleteDefaultObjectAclRequest const&) {
878-
return Status(StatusCode::kUnimplemented, __func__);
877+
DeleteDefaultObjectAclRequest const& request) {
878+
auto get_request = GetBucketMetadataRequest(request.bucket_name());
879+
request.ForEachOption(CopyCommonOptions(get_request));
880+
auto updater = [&request](std::vector<ObjectAccessControl> acl)
881+
-> StatusOr<std::vector<ObjectAccessControl>> {
882+
auto i = std::remove_if(acl.begin(), acl.end(),
883+
[&](ObjectAccessControl const& entry) {
884+
return entry.entity() == request.entity();
885+
});
886+
if (i == acl.end()) {
887+
return Status(StatusCode::kNotFound,
888+
"the entity <" + request.entity() +
889+
"> is not present in the ACL for bucket " +
890+
request.bucket_name());
891+
}
892+
acl.erase(i, acl.end());
893+
return acl;
894+
};
895+
auto response = ModifyDefaultAccessControl(get_request, updater);
896+
if (!response) return std::move(response).status();
897+
return EmptyResponse{};
879898
}
880899

881900
StatusOr<ObjectAccessControl> GrpcClient::GetDefaultObjectAcl(

google/cloud/storage/internal/grpc_client_test.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,72 @@ TEST_F(GrpcClientTest, CreateDefaultObjectAclPatchFails) {
15831583
EXPECT_THAT(response, StatusIs(StatusCode::kUnavailable));
15841584
}
15851585

1586+
TEST_F(GrpcClientTest, DeleteDefaultObjectAclFailure) {
1587+
auto mock = std::make_shared<testing::MockStorageStub>();
1588+
EXPECT_CALL(*mock, GetBucket)
1589+
.WillOnce([this](grpc::ClientContext& context,
1590+
v2::GetBucketRequest const& request) {
1591+
auto metadata = GetMetadata(context);
1592+
EXPECT_THAT(metadata, UnorderedElementsAre(
1593+
Pair("x-goog-quota-user", "test-quota-user"),
1594+
Pair("x-goog-fieldmask", "field1,field2")));
1595+
EXPECT_THAT(request.name(), "projects/_/buckets/test-bucket-name");
1596+
return PermanentError();
1597+
});
1598+
1599+
auto client = CreateTestClient(mock);
1600+
auto response = client->DeleteDefaultObjectAcl(
1601+
DeleteDefaultObjectAclRequest("test-bucket-name", "test-entity1")
1602+
.set_multiple_options(Fields("field1,field2"),
1603+
QuotaUser("test-quota-user"),
1604+
UserProject("test-user-project")));
1605+
EXPECT_EQ(response.status(), PermanentError());
1606+
}
1607+
1608+
TEST_F(GrpcClientTest, DeleteDefaultObjectAclPatchFails) {
1609+
auto mock = std::make_shared<testing::MockStorageStub>();
1610+
EXPECT_CALL(*mock, GetBucket)
1611+
.WillOnce([&](grpc::ClientContext&, v2::GetBucketRequest const&) {
1612+
v2::Bucket response;
1613+
EXPECT_TRUE(TextFormat::ParseFromString(kBucketProtoText, &response));
1614+
return response;
1615+
});
1616+
EXPECT_CALL(*mock, UpdateBucket)
1617+
.WillOnce([](grpc::ClientContext&,
1618+
v2::UpdateBucketRequest const& request) {
1619+
EXPECT_EQ(request.bucket().name(), "projects/_/buckets/test-bucket-id");
1620+
auto expected = v2::ObjectAccessControl();
1621+
expected.set_entity("test-entity4");
1622+
expected.set_role("test-role4");
1623+
EXPECT_THAT(request.bucket().default_object_acl(),
1624+
ElementsAre(IsProtoEqual(expected)));
1625+
EXPECT_THAT(request.update_mask().paths(),
1626+
ElementsAre("default_object_acl"));
1627+
return Status(StatusCode::kFailedPrecondition, "conflict");
1628+
});
1629+
1630+
auto client = CreateTestClient(mock);
1631+
auto response = client->DeleteDefaultObjectAcl(
1632+
DeleteDefaultObjectAclRequest("test-bucket-id", "test-entity3"));
1633+
EXPECT_THAT(response, StatusIs(StatusCode::kUnavailable));
1634+
}
1635+
1636+
TEST_F(GrpcClientTest, DeleteDefaultObjectAclNotFound) {
1637+
auto mock = std::make_shared<testing::MockStorageStub>();
1638+
EXPECT_CALL(*mock, GetBucket)
1639+
.WillOnce([&](grpc::ClientContext&, v2::GetBucketRequest const&) {
1640+
v2::Bucket response;
1641+
EXPECT_TRUE(TextFormat::ParseFromString(kBucketProtoText, &response));
1642+
return response;
1643+
});
1644+
EXPECT_CALL(*mock, UpdateBucket).Times(0);
1645+
1646+
auto client = CreateTestClient(mock);
1647+
auto response = client->DeleteDefaultObjectAcl(
1648+
DeleteDefaultObjectAclRequest("test-bucket-id", "test-not-found"));
1649+
EXPECT_THAT(response, StatusIs(StatusCode::kNotFound));
1650+
}
1651+
15861652
TEST_F(GrpcClientTest, GetServiceAccount) {
15871653
auto mock = std::make_shared<testing::MockStorageStub>();
15881654
EXPECT_CALL(*mock, GetServiceAccount)

google/cloud/storage/tests/grpc_default_object_acl_integration_test.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ TEST_F(GrpcDefaultObjectAclIntegrationTest, AclCRUD) {
105105
ASSERT_STATUS_OK(c2);
106106
EXPECT_EQ(*create_acl, *c2);
107107

108+
auto delete_acl = client->DeleteDefaultObjectAcl(bucket_name, viewers);
109+
ASSERT_STATUS_OK(delete_acl);
110+
111+
current_acl = client->ListDefaultObjectAcl(bucket_name);
112+
ASSERT_STATUS_OK(current_acl);
113+
EXPECT_THAT(AclEntityNames(*current_acl),
114+
Not(Contains(create_acl->entity())));
115+
108116
auto status = client->DeleteBucket(bucket_name);
109117
ASSERT_STATUS_OK(status);
110118
}

0 commit comments

Comments
 (0)