From 720a4789e6128b68fc648bd36833f7d0ea3c8953 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 7 Sep 2016 16:29:03 +0200 Subject: [PATCH 1/4] Add support for create/get/update/delete/list ACLs for blob and bucket --- .../storage/contrib/nio/FakeStorageRpc.java | 77 ++++++ google-cloud-storage/pom.xml | 2 +- .../java/com/google/cloud/storage/Acl.java | 152 +++++++++++- .../java/com/google/cloud/storage/Blob.java | 49 +++- .../java/com/google/cloud/storage/Bucket.java | 111 ++++++++- .../com/google/cloud/storage/Storage.java | 127 ++++++++++ .../com/google/cloud/storage/StorageImpl.java | 231 ++++++++++++++++++ .../cloud/storage/spi/DefaultStorageRpc.java | 212 ++++++++++++++++ .../google/cloud/storage/spi/StorageRpc.java | 114 +++++++++ .../com/google/cloud/storage/AclTest.java | 36 ++- .../com/google/cloud/storage/BlobTest.java | 68 +++++- .../com/google/cloud/storage/BucketTest.java | 121 ++++++++- .../google/cloud/storage/StorageImplTest.java | 200 +++++++++++++++ .../cloud/storage/it/ITStorageTest.java | 70 ++++++ 14 files changed, 1543 insertions(+), 27 deletions(-) diff --git a/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java b/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java index 93e4c14fb097..971b08a6b0eb 100644 --- a/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java +++ b/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java @@ -17,6 +17,8 @@ package com.google.cloud.storage.contrib.nio; import com.google.api.services.storage.model.Bucket; +import com.google.api.services.storage.model.BucketAccessControl; +import com.google.api.services.storage.model.ObjectAccessControl; import com.google.api.services.storage.model.StorageObject; import com.google.cloud.storage.Storage; import com.google.cloud.storage.StorageException; @@ -336,6 +338,81 @@ public RewriteResponse continueRewrite(RewriteResponse previousResponse) throws throw new UnsupportedOperationException(); } + @Override + public BucketAccessControl getAcl(String bucket, String entity) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean deleteAcl(String bucket, String entity) { + throw new UnsupportedOperationException(); + } + + @Override + public BucketAccessControl createAcl(BucketAccessControl acl) { + throw new UnsupportedOperationException(); + } + + @Override + public BucketAccessControl patchAcl(BucketAccessControl acl) { + throw new UnsupportedOperationException(); + } + + @Override + public List listAcls(String bucket) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectAccessControl getDefaultAcl(String bucket, String entity) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean deleteDefaultAcl(String bucket, String entity) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectAccessControl createDefaultAcl(ObjectAccessControl acl) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectAccessControl patchDefaultAcl(ObjectAccessControl acl) { + throw new UnsupportedOperationException(); + } + + @Override + public List listDefaultAcls(String bucket) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectAccessControl getAcl(String bucket, String object, Long generation, String entity) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean deleteAcl(String bucket, String object, Long generation, String entity) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectAccessControl createAcl(ObjectAccessControl acl) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectAccessControl patchAcl(ObjectAccessControl acl) { + throw new UnsupportedOperationException(); + } + + @Override + public List listAcls(String bucket, String object, Long generation) { + throw new UnsupportedOperationException(); + } + private String fullname(StorageObject so) { return (so.getBucket() + "/" + so.getName()); } diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index 9abb83cb1d63..f43e772d278d 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -25,7 +25,7 @@ com.google.apis google-api-services-storage - v1-rev62-1.21.0 + v1-rev82-1.22.0 compile diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java index 1063b24580b8..e3dd72f6460f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java @@ -16,8 +16,12 @@ package com.google.cloud.storage; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.api.services.storage.model.BucketAccessControl; import com.google.api.services.storage.model.ObjectAccessControl; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; import java.io.Serializable; import java.util.Objects; @@ -32,6 +36,23 @@ public final class Acl implements Serializable { private static final long serialVersionUID = 6435575339887912222L; + static final Function FROM_OBJECT_PB_FUNCTION = + new Function() { + @Override + public Acl apply(ObjectAccessControl aclPb) { + return Acl.fromPb(aclPb); + } + }; + static final Function FROM_BUCKET_PB_FUNCTION = + new Function() { + @Override + public Acl apply(BucketAccessControl aclPb) { + return Acl.fromPb(aclPb); + } + }; + + private final String id; + private final String etag; private final Entity entity; private final Role role; @@ -39,6 +60,62 @@ public enum Role { OWNER, READER, WRITER } + /** + * Builder for {@code Acl} objects. + */ + public static class Builder { + + private Entity entity; + private Role role; + private String id; + private String etag; + + private Builder(Entity entity, Role role) { + this.entity = entity; + this.role = role; + } + + private Builder(Acl acl) { + this.entity = acl.entity; + this.role = acl.role; + this.id = acl.id; + this.etag = acl.etag; + } + + /** + * Sets the entity for the ACL object. + */ + public Builder entity(Entity entity) { + this.entity = entity; + return this; + } + + /** + * Sets the role to associate to the {@code entity} object. + */ + public Builder role(Role role) { + this.role = role; + return this; + } + + Builder id(String id) { + this.id = id; + return this; + } + + Builder etag(String etag) { + this.etag = etag; + return this; + } + + /** + * Creates an {@code Acl} object from this builder. + */ + public Acl build() { + return new Acl(this); + } + } + /** * Base class for Access Control List entities. */ @@ -274,9 +351,27 @@ String toPb() { } } - private Acl(Entity entity, Role role) { - this.entity = entity; - this.role = role; + private Acl(Builder builder) { + this.entity = checkNotNull(builder.entity); + this.role = checkNotNull(builder.role); + this.id = builder.id; + this.etag = builder.etag; + } + + /** + * Returns the ID of the ACL entry. + */ + public String id() { + return id; + } + + /** + * Returns HTTP 1.1 Entity tag for the ACL entry. + * + * @see Entity Tags + */ + public String etag() { + return etag; } /** @@ -294,13 +389,40 @@ public Role role() { } /** - * Returns an Acl object. + * Returns a builder for this {@code Acl} object. + */ + public Builder toBuilder() { + return new Builder(this); + } + + /** + * Returns an {@code Acl} object. * * @param entity the entity for this ACL object * @param role the role to associate to the {@code entity} object */ public static Acl of(Entity entity, Role role) { - return new Acl(entity, role); + return builder(entity, role).build(); + } + + /** + * Returns a builder for {@code Acl} objects. + * + * @param entity the entity for this ACL object + * @param role the role to associate to the {@code entity} object + */ + public static Builder builder(Entity entity, Role role) { + return new Builder(entity, role); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("entity", entity) + .add("role", role) + .add("etag", etag) + .add("id", id) + .toString(); } @Override @@ -318,13 +440,17 @@ public boolean equals(Object obj) { } final Acl other = (Acl) obj; return Objects.equals(this.entity, other.entity) - && Objects.equals(this.role, other.role); + && Objects.equals(this.role, other.role) + && Objects.equals(this.etag, other.etag) + && Objects.equals(this.id, other.id); } BucketAccessControl toBucketPb() { BucketAccessControl bucketPb = new BucketAccessControl(); bucketPb.setRole(role().toString()); bucketPb.setEntity(entity().toString()); + bucketPb.setId(id()); + bucketPb.setEtag(etag()); return bucketPb; } @@ -332,16 +458,26 @@ ObjectAccessControl toObjectPb() { ObjectAccessControl objectPb = new ObjectAccessControl(); objectPb.setRole(role().name()); objectPb.setEntity(entity().toPb()); + objectPb.setId(id()); + objectPb.setEtag(etag()); return objectPb; } static Acl fromPb(ObjectAccessControl objectAccessControl) { Role role = Role.valueOf(objectAccessControl.getRole()); - return Acl.of(Entity.fromPb(objectAccessControl.getEntity()), role); + Entity entity = Entity.fromPb(objectAccessControl.getEntity()); + return builder(entity, role) + .etag(objectAccessControl.getEtag()) + .id(objectAccessControl.getId()) + .build(); } static Acl fromPb(BucketAccessControl bucketAccessControl) { Role role = Role.valueOf(bucketAccessControl.getRole()); - return Acl.of(Entity.fromPb(bucketAccessControl.getEntity()), role); + Entity entity = Entity.fromPb(bucketAccessControl.getEntity()); + return builder(entity, role) + .etag(bucketAccessControl.getEtag()) + .id(bucketAccessControl.getId()) + .build(); } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index 139313ad835e..53490cbf1bb7 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -28,6 +28,7 @@ import com.google.cloud.ServiceAccountSigner; import com.google.cloud.ServiceAccountSigner.SigningException; import com.google.cloud.WriteChannel; +import com.google.cloud.storage.Acl.Entity; import com.google.cloud.storage.Storage.BlobTargetOption; import com.google.cloud.storage.Storage.BlobWriteOption; import com.google.cloud.storage.Storage.CopyRequest; @@ -230,7 +231,7 @@ public Builder acl(List acl) { } @Override - Builder owner(Acl.Entity owner) { + Builder owner(Entity owner) { infoBuilder.owner(owner); return this; } @@ -602,6 +603,52 @@ public URL signUrl(long duration, TimeUnit unit, SignUrlOption... options) { return storage.signUrl(this, duration, unit, options); } + /** + * Returns the ACL entry for the specified entity on this blob or {@code null} if not found. + * + * @throws StorageException upon failure + */ + public Acl getAcl(Entity entity) { + return storage.getAcl(blobId(), entity); + } + + /** + * Deletes the ACL entry for the specified entity on this blob. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + public boolean deleteAcl(Entity entity) { + return storage.deleteAcl(blobId(), entity); + } + + /** + * Creates a new ACL entry on this blob. + * + * @throws StorageException upon failure + */ + public Acl createAcl(Acl acl) { + return storage.createAcl(blobId(), acl); + } + + /** + * Updates an ACL entry on this blob. + * + * @throws StorageException upon failure + */ + public Acl updateAcl(Acl acl) { + return storage.updateAcl(blobId(), acl); + } + + /** + * Lists the ACL entries for this blob. + * + * @throws StorageException upon failure + */ + public List listAcls() { + return storage.listAcls(blobId()); + } + /** * Returns the blob's {@code Storage} object used to issue requests. */ diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 4450f9689e72..b149955073f8 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.cloud.Page; +import com.google.cloud.storage.Acl.Entity; import com.google.cloud.storage.Storage.BlobGetOption; import com.google.cloud.storage.Storage.BlobListOption; import com.google.cloud.storage.Storage.BucketTargetOption; @@ -433,7 +434,7 @@ Builder generatedId(String generatedId) { } @Override - Builder owner(Acl.Entity owner) { + Builder owner(Entity owner) { infoBuilder.owner(owner); return this; } @@ -816,6 +817,114 @@ public Blob create(String blob, InputStream content, BlobWriteOption... options) return storage.create(write.x(), content, write.y()); } + /** + * Returns the ACL entry for the specified entity on this bucket or {@code null} if not found. + * + * @throws StorageException upon failure + */ + public Acl getAcl(Entity entity) { + return storage.getAcl(name(), entity); + } + + /** + * Deletes the ACL entry for the specified entity on this bucket. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + public boolean deleteAcl(Entity entity) { + return storage.deleteAcl(name(), entity); + } + + /** + * Creates a new ACL entry on this bucket. + * + * @throws StorageException upon failure + */ + public Acl createAcl(Acl acl) { + return storage.createAcl(name(), acl); + } + + /** + * Updates an ACL entry on this bucket. + * + * @throws StorageException upon failure + */ + public Acl updateAcl(Acl acl) { + return storage.updateAcl(name(), acl); + } + + /** + * Lists the ACL entries for this bucket. + * + * @throws StorageException upon failure + */ + public List listAcls() { + return storage.listAcls(name()); + } + + /** + * Returns the default object ACL entry for the specified entity on this bucket or {@code null} if + * not found. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + public Acl getDefaultAcl(Entity entity) { + return storage.getDefaultAcl(name(), entity); + } + + /** + * Deletes the default object ACL entry for the specified entity on this bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + public boolean deleteDefaultAcl(Entity entity) { + return storage.deleteDefaultAcl(name(), entity); + } + + /** + * Creates a new default blob ACL entry on this bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + public Acl createDefaultAcl(Acl acl) { + return storage.createDefaultAcl(name(), acl); + } + + /** + * Updates a default blob ACL entry on this bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + public Acl updateDefaultAcl(Acl acl) { + return storage.updateDefaultAcl(name(), acl); + } + + /** + * Lists the default blob ACL entries for this bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + public List listDefaultAcls() { + return storage.listDefaultAcls(name()); + } + /** * Returns the bucket's {@code Storage} object used to issue requests. */ diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 1e9dc392ce31..68c483aa35fd 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -30,6 +30,7 @@ import com.google.cloud.ServiceAccountSigner; import com.google.cloud.ServiceAccountSigner.SigningException; import com.google.cloud.WriteChannel; +import com.google.cloud.storage.Acl.Entity; import com.google.cloud.storage.spi.StorageRpc; import com.google.cloud.storage.spi.StorageRpc.Tuple; import com.google.common.collect.ImmutableList; @@ -1948,4 +1949,130 @@ public static Builder builder() { * @throws StorageException upon failure */ List delete(Iterable blobIds); + + /** + * Returns the ACL entry for the specified entity on the specified bucket or {@code null} if not + * found. + * + * @throws StorageException upon failure + */ + Acl getAcl(String bucket, Entity entity); + + /** + * Deletes the ACL entry for the specified entity on the specified bucket. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteAcl(String bucket, Entity entity); + + /** + * Creates a new ACL entry on the specified bucket. + * + * @throws StorageException upon failure + */ + Acl createAcl(String bucket, Acl acl); + + /** + * Updates an ACL entry on the specified bucket. + * + * @throws StorageException upon failure + */ + Acl updateAcl(String bucket, Acl acl); + + /** + * Lists the ACL entries for the provided bucket. + * + * @throws StorageException upon failure + */ + List listAcls(String bucket); + + /** + * Returns the default object ACL entry for the specified entity on the specified bucket or + * {@code null} if not found. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + Acl getDefaultAcl(String bucket, Entity entity); + + /** + * Deletes the default object ACL entry for the specified entity on the specified bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteDefaultAcl(String bucket, Entity entity); + + /** + * Creates a new default blob ACL entry on the specified bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + Acl createDefaultAcl(String bucket, Acl acl); + + /** + * Updates a default blob ACL entry on the specified bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + Acl updateDefaultAcl(String bucket, Acl acl); + + /** + * Lists the default blob ACL entries for the provided bucket. + * + *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that + * blob. + * + * @throws StorageException upon failure + */ + List listDefaultAcls(String bucket); + + /** + * Returns the ACL entry for the specified entity on the specified blob or {@code null} if not + * found. + * + * @throws StorageException upon failure + */ + Acl getAcl(BlobId blob, Entity entity); + + /** + * Deletes the ACL entry for the specified entity on the specified blob. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteAcl(BlobId blob, Entity entity); + + /** + * Creates a new ACL entry on the specified blob. + * + * @throws StorageException upon failure + */ + Acl createAcl(BlobId blob, Acl acl); + + /** + * Updates an ACL entry on the specified blob. + * + * @throws StorageException upon failure + */ + Acl updateAcl(BlobId blob, Acl acl); + + /** + * Lists the ACL entries for the provided blob. + * + * @throws StorageException upon failure + */ + List listAcls(BlobId blob); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 8d8ccb753d5f..c882ec6eb585 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -31,6 +31,8 @@ import static com.google.common.base.Preconditions.checkState; import static java.nio.charset.StandardCharsets.UTF_8; +import com.google.api.services.storage.model.BucketAccessControl; +import com.google.api.services.storage.model.ObjectAccessControl; import com.google.api.services.storage.model.StorageObject; import com.google.cloud.BaseService; import com.google.cloud.BatchResult; @@ -40,6 +42,7 @@ import com.google.cloud.ReadChannel; import com.google.cloud.RetryHelper.RetryHelperException; import com.google.cloud.ServiceAccountSigner; +import com.google.cloud.storage.Acl.Entity; import com.google.cloud.storage.spi.StorageRpc; import com.google.cloud.storage.spi.StorageRpc.RewriteResponse; import com.google.cloud.storage.spi.StorageRpc.Tuple; @@ -615,6 +618,234 @@ public void error(StorageException exception) { return Collections.unmodifiableList(results); } + @Override + public Acl getAcl(final String bucket, final Entity entity) { + try { + BucketAccessControl answer = runWithRetries(new Callable() { + @Override + public BucketAccessControl call() { + return storageRpc.getAcl(bucket, entity.toPb()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + return answer == null ? null : Acl.fromPb(answer); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public boolean deleteAcl(final String bucket, final Entity entity) { + try { + return runWithRetries(new Callable() { + @Override + public Boolean call() { + return storageRpc.deleteAcl(bucket, entity.toPb()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl createAcl(String bucket, Acl acl) { + final BucketAccessControl aclPb = acl.toBucketPb().setBucket(bucket); + try { + return Acl.fromPb(runWithRetries(new Callable() { + @Override + public BucketAccessControl call() { + return storageRpc.createAcl(aclPb); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl updateAcl(String bucket, Acl acl) { + final BucketAccessControl aclPb = acl.toBucketPb().setBucket(bucket); + try { + return Acl.fromPb(runWithRetries(new Callable() { + @Override + public BucketAccessControl call() { + return storageRpc.patchAcl(aclPb); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public List listAcls(final String bucket) { + try { + List answer = runWithRetries(new Callable>() { + @Override + public List call() { + return storageRpc.listAcls(bucket); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + return Lists.transform(answer, Acl.FROM_BUCKET_PB_FUNCTION); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl getDefaultAcl(final String bucket, final Entity entity) { + try { + ObjectAccessControl answer = runWithRetries(new Callable() { + @Override + public ObjectAccessControl call() { + return storageRpc.getDefaultAcl(bucket, entity.toPb()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + return answer == null ? null : Acl.fromPb(answer); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public boolean deleteDefaultAcl(final String bucket, final Entity entity) { + try { + return runWithRetries(new Callable() { + @Override + public Boolean call() { + return storageRpc.deleteDefaultAcl(bucket, entity.toPb()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl createDefaultAcl(String bucket, Acl acl) { + final ObjectAccessControl aclPb = acl.toObjectPb().setBucket(bucket); + try { + return Acl.fromPb(runWithRetries(new Callable() { + @Override + public ObjectAccessControl call() { + return storageRpc.createDefaultAcl(aclPb); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl updateDefaultAcl(String bucket, Acl acl) { + final ObjectAccessControl aclPb = acl.toObjectPb().setBucket(bucket); + try { + return Acl.fromPb(runWithRetries(new Callable() { + @Override + public ObjectAccessControl call() { + return storageRpc.patchDefaultAcl(aclPb); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public List listDefaultAcls(final String bucket) { + try { + List answer = runWithRetries(new Callable>() { + @Override + public List call() { + return storageRpc.listDefaultAcls(bucket); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + return Lists.transform(answer, Acl.FROM_OBJECT_PB_FUNCTION); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl getAcl(final BlobId blob, final Entity entity) { + try { + ObjectAccessControl answer = runWithRetries(new Callable() { + @Override + public ObjectAccessControl call() { + return storageRpc.getAcl(blob.bucket(), blob.name(), blob.generation(), entity.toPb()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + return answer == null ? null : Acl.fromPb(answer); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public boolean deleteAcl(final BlobId blob, final Entity entity) { + try { + return runWithRetries(new Callable() { + @Override + public Boolean call() { + return storageRpc.deleteAcl(blob.bucket(), blob.name(), blob.generation(), entity.toPb()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl createAcl(final BlobId blob, final Acl acl) { + final ObjectAccessControl aclPb = acl.toObjectPb() + .setBucket(blob.bucket()) + .setObject(blob.name()) + .setGeneration(blob.generation()); + try { + return Acl.fromPb(runWithRetries(new Callable() { + @Override + public ObjectAccessControl call() { + return storageRpc.createAcl(aclPb); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Acl updateAcl(BlobId blob, Acl acl) { + final ObjectAccessControl aclPb = acl.toObjectPb() + .setBucket(blob.bucket()) + .setObject(blob.name()) + .setGeneration(blob.generation()); + try { + return Acl.fromPb(runWithRetries(new Callable() { + @Override + public ObjectAccessControl call() { + return storageRpc.patchAcl(aclPb); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public List listAcls(final BlobId blob) { + try { + List answer = runWithRetries(new Callable>() { + @Override + public List call() { + return storageRpc.listAcls(blob.bucket(), blob.name(), blob.generation()); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + return Lists.transform(answer, Acl.FROM_OBJECT_PB_FUNCTION); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + private static void addToOptionMap(StorageRpc.Option option, T defaultValue, Map map) { addToOptionMap(option, option, defaultValue, map); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/DefaultStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/DefaultStorageRpc.java index ccfa0fe0b917..2e77b511d554 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/DefaultStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/DefaultStorageRpc.java @@ -57,9 +57,11 @@ import com.google.api.services.storage.Storage.Objects.Get; import com.google.api.services.storage.Storage.Objects.Insert; import com.google.api.services.storage.model.Bucket; +import com.google.api.services.storage.model.BucketAccessControl; import com.google.api.services.storage.model.Buckets; import com.google.api.services.storage.model.ComposeRequest; import com.google.api.services.storage.model.ComposeRequest.SourceObjects.ObjectPreconditions; +import com.google.api.services.storage.model.ObjectAccessControl; import com.google.api.services.storage.model.Objects; import com.google.api.services.storage.model.StorageObject; import com.google.cloud.storage.StorageException; @@ -85,6 +87,32 @@ public class DefaultStorageRpc implements StorageRpc { private final Storage storage; private static final long MEGABYTE = 1024L * 1024L; + private static final Function FROM_OBJECT_TO_ACL_FUNCTION = + new Function() { + @Override + @SuppressWarnings("unchecked") + public ObjectAccessControl apply(Object obj) { + ObjectAccessControl acl = new ObjectAccessControl(); + Map map = (Map) obj; + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + switch (key) { + case "projectTeam": + ObjectAccessControl.ProjectTeam projectTeam = new ObjectAccessControl.ProjectTeam(); + projectTeam.putAll((Map) entry.getValue()); + acl.set(key, projectTeam); + break; + case "generation": + acl.set(entry.getKey(), Long.parseLong((String) entry.getValue())); + break; + default: + acl.set(entry.getKey(), entry.getValue()); + break; + } + } + return acl; + } + }; public DefaultStorageRpc(StorageOptions options) { HttpTransport transport = options.httpTransportFactory().create(); @@ -615,4 +643,188 @@ private RewriteResponse rewrite(RewriteRequest req, String token) { throw translate(ex); } } + + @Override + public BucketAccessControl getAcl(String bucket, String entity) { + try { + return storage.bucketAccessControls().get(bucket, entity).execute(); + } catch (IOException ex) { + StorageException serviceException = translate(ex); + if (serviceException.code() == HTTP_NOT_FOUND) { + return null; + } + throw serviceException; + } + } + + @Override + public boolean deleteAcl(String bucket, String entity) { + try { + storage.bucketAccessControls().delete(bucket, entity).execute(); + return true; + } catch (IOException ex) { + StorageException serviceException = translate(ex); + if (serviceException.code() == HTTP_NOT_FOUND) { + return false; + } + throw serviceException; + } + } + + @Override + public BucketAccessControl createAcl(BucketAccessControl acl) { + try { + return storage.bucketAccessControls().insert(acl.getBucket(), acl).execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public BucketAccessControl patchAcl(BucketAccessControl acl) { + try { + return storage.bucketAccessControls() + .patch(acl.getBucket(), acl.getEntity(), acl).execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public List listAcls(String bucket) { + try { + return storage.bucketAccessControls().list(bucket).execute().getItems(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public ObjectAccessControl getDefaultAcl(String bucket, String entity) { + try { + return storage.defaultObjectAccessControls().get(bucket, entity).execute(); + } catch (IOException ex) { + StorageException serviceException = translate(ex); + if (serviceException.code() == HTTP_NOT_FOUND) { + return null; + } + throw serviceException; + } + } + + @Override + public boolean deleteDefaultAcl(String bucket, String entity) { + try { + storage.defaultObjectAccessControls().delete(bucket, entity).execute(); + return true; + } catch (IOException ex) { + StorageException serviceException = translate(ex); + if (serviceException.code() == HTTP_NOT_FOUND) { + return false; + } + throw serviceException; + } + } + + @Override + public ObjectAccessControl createDefaultAcl(ObjectAccessControl acl) { + try { + return storage.defaultObjectAccessControls().insert(acl.getBucket(), acl).execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public ObjectAccessControl patchDefaultAcl(ObjectAccessControl acl) { + try { + return storage.defaultObjectAccessControls() + .patch(acl.getBucket(), acl.getEntity(), acl) + .execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public List listDefaultAcls(String bucket) { + try { + // TODO(mziccard) remove when https://github.com/google/google-api-java-client/issues/1022 is + // fixed + return Lists.transform( + storage.defaultObjectAccessControls().list(bucket).execute().getItems(), + FROM_OBJECT_TO_ACL_FUNCTION); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public ObjectAccessControl getAcl(String bucket, String object, Long generation, String entity) { + try { + return storage.objectAccessControls().get(bucket, object, entity) + .setGeneration(generation) + .execute(); + } catch (IOException ex) { + StorageException serviceException = translate(ex); + if (serviceException.code() == HTTP_NOT_FOUND) { + return null; + } + throw serviceException; + } + } + + @Override + public boolean deleteAcl(String bucket, String object, Long generation, String entity) { + try { + storage.objectAccessControls().delete(bucket, object, entity) + .setGeneration(generation) + .execute(); + return true; + } catch (IOException ex) { + StorageException serviceException = translate(ex); + if (serviceException.code() == HTTP_NOT_FOUND) { + return false; + } + throw serviceException; + } + } + + @Override + public ObjectAccessControl createAcl(ObjectAccessControl acl) { + try { + return storage.objectAccessControls().insert(acl.getBucket(), acl.getObject(), acl) + .setGeneration(acl.getGeneration()) + .execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public ObjectAccessControl patchAcl(ObjectAccessControl acl) { + try { + return storage.objectAccessControls() + .patch(acl.getBucket(), acl.getObject(), acl.getEntity(), acl) + .setGeneration(acl.getGeneration()) + .execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public List listAcls(String bucket, String object, Long generation) { + try { + // TODO(mziccard) remove when https://github.com/google/google-api-java-client/issues/1022 is + // fixed + return Lists.transform( + storage.objectAccessControls().list(bucket, object) + .setGeneration(generation) + .execute().getItems(), + FROM_OBJECT_TO_ACL_FUNCTION); + } catch (IOException ex) { + throw translate(ex); + } + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/StorageRpc.java index 6beeeed11f9f..b2eab7eeca42 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/StorageRpc.java @@ -17,10 +17,13 @@ package com.google.cloud.storage.spi; import com.google.api.services.storage.model.Bucket; +import com.google.api.services.storage.model.BucketAccessControl; +import com.google.api.services.storage.model.ObjectAccessControl; import com.google.api.services.storage.model.StorageObject; import com.google.cloud.storage.StorageException; import java.io.InputStream; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -311,4 +314,115 @@ void write(String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, * @throws StorageException upon failure */ RewriteResponse continueRewrite(RewriteResponse previousResponse); + + /** + * Returns the ACL entry for the specified entity on the specified bucket or {@code null} if not + * found. + * + * @throws StorageException upon failure + */ + BucketAccessControl getAcl(String bucket, String entity); + + /** + * Deletes the ACL entry for the specified entity on the specified bucket. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteAcl(String bucket, String entity); + + /** + * Creates a new ACL entry on the specified bucket. + * + * @throws StorageException upon failure + */ + BucketAccessControl createAcl(BucketAccessControl acl); + + /** + * Updates an ACL entry on the specified bucket. + * + * @throws StorageException upon failure + */ + BucketAccessControl patchAcl(BucketAccessControl acl); + + /** + * Lists the ACL entries for the provided bucket. + * + * @throws StorageException upon failure + */ + List listAcls(String bucket); + + /** + * Returns the default object ACL entry for the specified entity on the specified bucket or + * {@code null} if not found. + * + * @throws StorageException upon failure + */ + ObjectAccessControl getDefaultAcl(String bucket, String entity); + + /** + * Deletes the default object ACL entry for the specified entity on the specified bucket. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteDefaultAcl(String bucket, String entity); + + /** + * Creates a new default object ACL entry on the specified bucket. + * + * @throws StorageException upon failure + */ + ObjectAccessControl createDefaultAcl(ObjectAccessControl acl); + + /** + * Updates a default object ACL entry on the specified bucket. + * + * @throws StorageException upon failure + */ + ObjectAccessControl patchDefaultAcl(ObjectAccessControl acl); + + /** + * Lists the default object ACL entries for the provided bucket. + * + * @throws StorageException upon failure + */ + List listDefaultAcls(String bucket); + + /** + * Returns the ACL entry for the specified entity on the specified object or {@code null} if not + * found. + * + * @throws StorageException upon failure + */ + ObjectAccessControl getAcl(String bucket, String object, Long generation, String entity); + + /** + * Deletes the ACL entry for the specified entity on the specified object. + * + * @return {@code true} if the ACL was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteAcl(String bucket, String object, Long generation, String entity); + + /** + * Creates a new ACL entry on the specified object. + * + * @throws StorageException upon failure + */ + ObjectAccessControl createAcl(ObjectAccessControl acl); + + /** + * Updates an ACL entry on the specified object. + * + * @throws StorageException upon failure + */ + ObjectAccessControl patchAcl(ObjectAccessControl acl); + + /** + * Lists the ACL entries for the provided object. + * + * @throws StorageException upon failure + */ + List listAcls(String bucket, String object, Long generation); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/AclTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/AclTest.java index 26c37f53ba48..99180359486a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/AclTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/AclTest.java @@ -34,6 +34,41 @@ public class AclTest { + private static final Role ROLE = Role.OWNER; + private static final Entity ENTITY = User.ofAllAuthenticatedUsers(); + private static final String ETAG = "etag"; + private static final String ID = "id"; + private static final Acl ACL = Acl.builder(ENTITY, ROLE).etag(ETAG).id(ID).build(); + + @Test + public void testBuilder() { + assertEquals(ROLE, ACL.role()); + assertEquals(ENTITY, ACL.entity()); + assertEquals(ETAG, ACL.etag()); + assertEquals(ID, ACL.id()); + } + + @Test + public void testToBuilder() { + assertEquals(ACL, ACL.toBuilder().build()); + Acl acl = ACL.toBuilder() + .etag("otherEtag") + .id("otherId") + .role(Role.READER) + .entity(User.ofAllUsers()) + .build(); + assertEquals(Role.READER, acl.role()); + assertEquals(User.ofAllUsers(), acl.entity()); + assertEquals("otherEtag", acl.etag()); + assertEquals("otherId", acl.id()); + } + + @Test + public void testToAndFromPb() { + assertEquals(ACL, Acl.fromPb(ACL.toBucketPb())); + assertEquals(ACL, Acl.fromPb(ACL.toObjectPb())); + } + @Test public void testDomainEntity() { Domain acl = new Domain("d1"); @@ -80,7 +115,6 @@ public void testRawEntity() { assertEquals(acl, Entity.fromPb(pb)); } - @Test public void testOf() { Acl acl = Acl.of(User.ofAllUsers(), Role.READER); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java index 440f932dd54d..07107f5abb4d 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java @@ -16,9 +16,6 @@ package com.google.cloud.storage; -import static com.google.cloud.storage.Acl.Project.ProjectRole.VIEWERS; -import static com.google.cloud.storage.Acl.Role.READER; -import static com.google.cloud.storage.Acl.Role.WRITER; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createStrictMock; @@ -35,6 +32,8 @@ import com.google.cloud.ReadChannel; import com.google.cloud.storage.Acl.Project; +import com.google.cloud.storage.Acl.Project.ProjectRole; +import com.google.cloud.storage.Acl.Role; import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.Storage.CopyRequest; import com.google.common.collect.ImmutableList; @@ -52,8 +51,9 @@ public class BlobTest { - private static final List ACL = ImmutableList.of( - Acl.of(User.ofAllAuthenticatedUsers(), READER), Acl.of(new Project(VIEWERS, "p1"), WRITER)); + private static final Acl ACL = Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER); + private static final Acl OTHER_ACL = Acl.of(new Project(ProjectRole.OWNERS, "p"), Role.READER); + private static final List ACLS = ImmutableList.of(ACL, OTHER_ACL); private static final Integer COMPONENT_COUNT = 2; private static final String CONTENT_TYPE = "text/html"; private static final String CACHE_CONTROL = "cache"; @@ -75,7 +75,7 @@ public class BlobTest { private static final Long UPDATE_TIME = DELETE_TIME - 1L; private static final Long CREATE_TIME = UPDATE_TIME - 1L; private static final BlobInfo FULL_BLOB_INFO = BlobInfo.builder("b", "n", GENERATION) - .acl(ACL) + .acl(ACLS) .componentCount(COMPONENT_COUNT) .contentType(CONTENT_TYPE) .cacheControl(CACHE_CONTROL) @@ -312,6 +312,58 @@ public void testSignUrl() throws Exception { assertEquals(url, blob.signUrl(100, TimeUnit.SECONDS)); } + @Test + public void testGetAcl() throws Exception { + initializeExpectedBlob(1); + expect(storage.options()).andReturn(mockOptions); + expect(storage.getAcl(BLOB_INFO.blobId(), User.ofAllAuthenticatedUsers())).andReturn(ACL); + replay(storage); + initializeBlob(); + assertEquals(ACL, blob.getAcl(User.ofAllAuthenticatedUsers())); + } + + @Test + public void testDeleteAcl() throws Exception { + initializeExpectedBlob(1); + expect(storage.options()).andReturn(mockOptions); + expect(storage.deleteAcl(BLOB_INFO.blobId(), User.ofAllAuthenticatedUsers())).andReturn(true); + replay(storage); + initializeBlob(); + assertTrue(blob.deleteAcl(User.ofAllAuthenticatedUsers())); + } + + @Test + public void testCreateAcl() throws Exception { + initializeExpectedBlob(1); + expect(storage.options()).andReturn(mockOptions); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + expect(storage.createAcl(BLOB_INFO.blobId(), ACL)).andReturn(returnedAcl); + replay(storage); + initializeBlob(); + assertEquals(returnedAcl, blob.createAcl(ACL)); + } + + @Test + public void testUpdateAcl() throws Exception { + initializeExpectedBlob(1); + expect(storage.options()).andReturn(mockOptions); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + expect(storage.updateAcl(BLOB_INFO.blobId(), ACL)).andReturn(returnedAcl); + replay(storage); + initializeBlob(); + assertEquals(returnedAcl, blob.updateAcl(ACL)); + } + + @Test + public void testListAcls() throws Exception { + initializeExpectedBlob(1); + expect(storage.options()).andReturn(mockOptions); + expect(storage.listAcls(BLOB_INFO.blobId())).andReturn(ACLS); + replay(storage); + initializeBlob(); + assertEquals(ACLS, blob.listAcls()); + } + @Test public void testToBuilder() { expect(storage.options()).andReturn(mockOptions).times(6); @@ -330,7 +382,7 @@ public void testBuilder() { expect(storage.options()).andReturn(mockOptions).times(4); replay(storage); Blob.Builder builder = new Blob.Builder(new Blob(storage, new BlobInfo.BuilderImpl(BLOB_INFO))); - Blob blob = builder.acl(ACL) + Blob blob = builder.acl(ACLS) .componentCount(COMPONENT_COUNT) .contentType(CONTENT_TYPE) .cacheControl(CACHE_CONTROL) @@ -353,7 +405,7 @@ public void testBuilder() { .build(); assertEquals("b", blob.bucket()); assertEquals("n", blob.name()); - assertEquals(ACL, blob.acl()); + assertEquals(ACLS, blob.acl()); assertEquals(COMPONENT_COUNT, blob.componentCount()); assertEquals(CONTENT_TYPE, blob.contentType()); assertEquals(CACHE_CONTROL, blob.cacheControl()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java index 1b9a29f03676..b7052cadfa9b 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java @@ -16,8 +16,6 @@ package com.google.cloud.storage; -import static com.google.cloud.storage.Acl.Project.ProjectRole.VIEWERS; -import static com.google.cloud.storage.Acl.Role.READER; import static com.google.cloud.storage.Acl.Role.WRITER; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createStrictMock; @@ -32,6 +30,8 @@ import com.google.cloud.Page; import com.google.cloud.PageImpl; import com.google.cloud.storage.Acl.Project; +import com.google.cloud.storage.Acl.Project.ProjectRole; +import com.google.cloud.storage.Acl.Role; import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.BucketInfo.AgeDeleteRule; import com.google.cloud.storage.BucketInfo.DeleteRule; @@ -53,8 +53,9 @@ public class BucketTest { - private static final List ACL = ImmutableList.of( - Acl.of(User.ofAllAuthenticatedUsers(), READER), Acl.of(new Project(VIEWERS, "p1"), WRITER)); + private static final Acl ACL = Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER); + private static final Acl OTHER_ACL = Acl.of(new Project(ProjectRole.OWNERS, "p"), Role.READER); + private static final List ACLS = ImmutableList.of(ACL, OTHER_ACL); private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final Long META_GENERATION = 10L; @@ -72,7 +73,7 @@ public class BucketTest { private static final String STORAGE_CLASS = "STANDARD"; private static final Boolean VERSIONING_ENABLED = true; private static final BucketInfo FULL_BUCKET_INFO = BucketInfo.builder("b") - .acl(ACL) + .acl(ACLS) .etag(ETAG) .generatedId(GENERATED_ID) .metageneration(META_GENERATION) @@ -475,6 +476,112 @@ public void testCreateFromStreamWithWrongMetagenerationOptions() throws Exceptio Bucket.BlobWriteOption.metagenerationNotMatch(24L)); } + @Test + public void testGetAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + expect(storage.getAcl(BUCKET_INFO.name(), User.ofAllAuthenticatedUsers())).andReturn(ACL); + replay(storage); + initializeBucket(); + assertEquals(ACL, bucket.getAcl(User.ofAllAuthenticatedUsers())); + } + + @Test + public void testDeleteAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + expect(storage.deleteAcl(BUCKET_INFO.name(), User.ofAllAuthenticatedUsers())).andReturn(true); + replay(storage); + initializeBucket(); + assertTrue(bucket.deleteAcl(User.ofAllAuthenticatedUsers())); + } + + @Test + public void testCreateAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + expect(storage.createAcl(BUCKET_INFO.name(), ACL)).andReturn(returnedAcl); + replay(storage); + initializeBucket(); + assertEquals(returnedAcl, bucket.createAcl(ACL)); + } + + @Test + public void testUpdateAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + expect(storage.updateAcl(BUCKET_INFO.name(), ACL)).andReturn(returnedAcl); + replay(storage); + initializeBucket(); + assertEquals(returnedAcl, bucket.updateAcl(ACL)); + } + + @Test + public void testListAcls() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + expect(storage.listAcls(BUCKET_INFO.name())).andReturn(ACLS); + replay(storage); + initializeBucket(); + assertEquals(ACLS, bucket.listAcls()); + } + + @Test + public void testGetDefaultAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + expect(storage.getDefaultAcl(BUCKET_INFO.name(), User.ofAllAuthenticatedUsers())) + .andReturn(ACL); + replay(storage); + initializeBucket(); + assertEquals(ACL, bucket.getDefaultAcl(User.ofAllAuthenticatedUsers())); + } + + @Test + public void testDeleteDefaultAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + expect(storage.deleteDefaultAcl(BUCKET_INFO.name(), User.ofAllAuthenticatedUsers())) + .andReturn(true); + replay(storage); + initializeBucket(); + assertTrue(bucket.deleteDefaultAcl(User.ofAllAuthenticatedUsers())); + } + + @Test + public void testCreateDefaultAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + expect(storage.createDefaultAcl(BUCKET_INFO.name(), ACL)).andReturn(returnedAcl); + replay(storage); + initializeBucket(); + assertEquals(returnedAcl, bucket.createDefaultAcl(ACL)); + } + + @Test + public void testUpdateDefaultAcl() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + expect(storage.updateDefaultAcl(BUCKET_INFO.name(), ACL)).andReturn(returnedAcl); + replay(storage); + initializeBucket(); + assertEquals(returnedAcl, bucket.updateDefaultAcl(ACL)); + } + + @Test + public void testListDefaultAcls() throws Exception { + initializeExpectedBucket(4); + expect(storage.options()).andReturn(mockOptions); + expect(storage.listDefaultAcls(BUCKET_INFO.name())).andReturn(ACLS); + replay(storage); + initializeBucket(); + assertEquals(ACLS, bucket.listDefaultAcls()); + } + @Test public void testToBuilder() { expect(storage.options()).andReturn(mockOptions).times(4); @@ -492,7 +599,7 @@ public void testBuilder() { replay(storage); Bucket.Builder builder = new Bucket.Builder(new Bucket(storage, new BucketInfo.BuilderImpl(BUCKET_INFO))); - Bucket bucket = builder.acl(ACL) + Bucket bucket = builder.acl(ACLS) .etag(ETAG) .generatedId(GENERATED_ID) .metageneration(META_GENERATION) @@ -509,7 +616,7 @@ public void testBuilder() { .versioningEnabled(VERSIONING_ENABLED) .build(); assertEquals("b", bucket.name()); - assertEquals(ACL, bucket.acl()); + assertEquals(ACLS, bucket.acl()); assertEquals(ETAG, bucket.etag()); assertEquals(GENERATED_ID, bucket.generatedId()); assertEquals(META_GENERATION, bucket.metageneration()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java index 332450bd4b28..16a386ccd630 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java @@ -33,6 +33,10 @@ import com.google.cloud.ReadChannel; import com.google.cloud.RetryParams; import com.google.cloud.WriteChannel; +import com.google.cloud.storage.Acl.Project; +import com.google.cloud.storage.Acl.Project.ProjectRole; +import com.google.cloud.storage.Acl.Role; +import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.Storage.CopyRequest; import com.google.cloud.storage.spi.RpcBatch; import com.google.cloud.storage.spi.StorageRpc; @@ -210,6 +214,10 @@ public class StorageImplTest { StorageRpc.Option.PREFIX, BLOB_LIST_PREFIX.value(), StorageRpc.Option.VERSIONS, BLOB_LIST_VERSIONS.value()); + // ACLs + private static final Acl ACL = Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER); + private static final Acl OTHER_ACL = Acl.of(new Project(ProjectRole.OWNERS, "p"), Role.READER); + private static final String PRIVATE_KEY_STRING = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoG" + "BAL2xolH1zrISQ8+GzOV29BNjjzq4/HIP8Psd1+cZb81vDklSF+95wB250MSE0BDc81pvIMwj5OmIfLg1NY6uB" + "1xavOPpVdx1z664AGc/BEJ1zInXGXaQ6s+SxGenVq40Yws57gikQGMZjttpf1Qbz4DjkxsbRoeaRHn06n9pH1e" @@ -1284,6 +1292,198 @@ public void testUpdateAllIterable() { EasyMock.verify(batchMock); } + @Test + public void testGetBucketAcl() { + EasyMock.expect(storageRpcMock.getAcl(BUCKET_NAME1, "allAuthenticatedUsers")) + .andReturn(ACL.toBucketPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.getAcl(BUCKET_NAME1, User.ofAllAuthenticatedUsers()); + assertEquals(ACL, acl); + } + + @Test + public void testGetBucketAclNull() { + EasyMock.expect(storageRpcMock.getAcl(BUCKET_NAME1, "allAuthenticatedUsers")).andReturn(null); + EasyMock.replay(storageRpcMock); + initializeService(); + assertNull(storage.getAcl(BUCKET_NAME1, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testDeleteBucketAcl() { + EasyMock.expect(storageRpcMock.deleteAcl(BUCKET_NAME1, "allAuthenticatedUsers")) + .andReturn(true); + EasyMock.replay(storageRpcMock); + initializeService(); + assertTrue(storage.deleteAcl(BUCKET_NAME1, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testCreateBucketAcl() { + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + EasyMock.expect(storageRpcMock.createAcl(ACL.toBucketPb().setBucket(BUCKET_NAME1))) + .andReturn(returnedAcl.toBucketPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.createAcl(BUCKET_NAME1, ACL); + assertEquals(returnedAcl, acl); + } + + @Test + public void testUpdateBucketAcl() { + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + EasyMock.expect(storageRpcMock.patchAcl(ACL.toBucketPb().setBucket(BUCKET_NAME1))) + .andReturn(returnedAcl.toBucketPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.updateAcl(BUCKET_NAME1, ACL); + assertEquals(returnedAcl, acl); + } + + @Test + public void testListBucketAcl() { + EasyMock.expect(storageRpcMock.listAcls(BUCKET_NAME1)) + .andReturn(ImmutableList.of(ACL.toBucketPb(), OTHER_ACL.toBucketPb())); + EasyMock.replay(storageRpcMock); + initializeService(); + List acls = storage.listAcls(BUCKET_NAME1); + assertEquals(ImmutableList.of(ACL, OTHER_ACL), acls); + } + + @Test + public void testGetDefaultBucketAcl() { + EasyMock.expect(storageRpcMock.getDefaultAcl(BUCKET_NAME1, "allAuthenticatedUsers")) + .andReturn(ACL.toObjectPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.getDefaultAcl(BUCKET_NAME1, User.ofAllAuthenticatedUsers()); + assertEquals(ACL, acl); + } + + @Test + public void testGetDefaultBucketAclNull() { + EasyMock.expect(storageRpcMock.getDefaultAcl(BUCKET_NAME1, "allAuthenticatedUsers")) + .andReturn(null); + EasyMock.replay(storageRpcMock); + initializeService(); + assertNull(storage.getDefaultAcl(BUCKET_NAME1, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testDeleteDefaultBucketAcl() { + EasyMock.expect(storageRpcMock.deleteDefaultAcl(BUCKET_NAME1, "allAuthenticatedUsers")) + .andReturn(true); + EasyMock.replay(storageRpcMock); + initializeService(); + assertTrue(storage.deleteDefaultAcl(BUCKET_NAME1, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testCreateDefaultBucketAcl() { + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + EasyMock.expect(storageRpcMock.createDefaultAcl(ACL.toObjectPb().setBucket(BUCKET_NAME1))) + .andReturn(returnedAcl.toObjectPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.createDefaultAcl(BUCKET_NAME1, ACL); + assertEquals(returnedAcl, acl); + } + + @Test + public void testUpdateDefaultBucketAcl() { + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + EasyMock.expect(storageRpcMock.patchDefaultAcl(ACL.toObjectPb().setBucket(BUCKET_NAME1))) + .andReturn(returnedAcl.toObjectPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.updateDefaultAcl(BUCKET_NAME1, ACL); + assertEquals(returnedAcl, acl); + } + + @Test + public void testListDefaultBucketAcl() { + EasyMock.expect(storageRpcMock.listDefaultAcls(BUCKET_NAME1)) + .andReturn(ImmutableList.of(ACL.toObjectPb(), OTHER_ACL.toObjectPb())); + EasyMock.replay(storageRpcMock); + initializeService(); + List acls = storage.listDefaultAcls(BUCKET_NAME1); + assertEquals(ImmutableList.of(ACL, OTHER_ACL), acls); + } + + @Test + public void testGetBlobAcl() { + BlobId blobId = BlobId.of(BUCKET_NAME1, BLOB_NAME1, 42L); + EasyMock.expect(storageRpcMock.getAcl(BUCKET_NAME1, BLOB_NAME1, 42L, "allAuthenticatedUsers")) + .andReturn(ACL.toObjectPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.getAcl(blobId, User.ofAllAuthenticatedUsers()); + assertEquals(ACL, acl); + } + + @Test + public void testGetBlobAclNull() { + BlobId blobId = BlobId.of(BUCKET_NAME1, BLOB_NAME1, 42L); + EasyMock.expect(storageRpcMock.getAcl(BUCKET_NAME1, BLOB_NAME1, 42L, "allAuthenticatedUsers")) + .andReturn(null); + EasyMock.replay(storageRpcMock); + initializeService(); + assertNull(storage.getAcl(blobId, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testDeleteBlobAcl() { + BlobId blobId = BlobId.of(BUCKET_NAME1, BLOB_NAME1, 42L); + EasyMock.expect( + storageRpcMock.deleteAcl(BUCKET_NAME1, BLOB_NAME1, 42L, "allAuthenticatedUsers")) + .andReturn(true); + EasyMock.replay(storageRpcMock); + initializeService(); + assertTrue(storage.deleteAcl(blobId, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testCreateBlobAcl() { + BlobId blobId = BlobId.of(BUCKET_NAME1, BLOB_NAME1, 42L); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + EasyMock.expect(storageRpcMock.createAcl(ACL.toObjectPb() + .setBucket(BUCKET_NAME1) + .setObject(BLOB_NAME1) + .setGeneration(42L))) + .andReturn(returnedAcl.toObjectPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.createAcl(blobId, ACL); + assertEquals(returnedAcl, acl); + } + + @Test + public void testUpdateBlobAcl() { + BlobId blobId = BlobId.of(BUCKET_NAME1, BLOB_NAME1, 42L); + Acl returnedAcl = ACL.toBuilder().etag("ETAG").id("ID").build(); + EasyMock.expect(storageRpcMock.patchAcl(ACL.toObjectPb() + .setBucket(BUCKET_NAME1) + .setObject(BLOB_NAME1) + .setGeneration(42L))) + .andReturn(returnedAcl.toObjectPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Acl acl = storage.updateAcl(blobId, ACL); + assertEquals(returnedAcl, acl); + } + + @Test + public void testListBlobAcl() { + BlobId blobId = BlobId.of(BUCKET_NAME1, BLOB_NAME1, 42L); + EasyMock.expect(storageRpcMock.listAcls(BUCKET_NAME1, BLOB_NAME1, 42L)) + .andReturn(ImmutableList.of(ACL.toObjectPb(), OTHER_ACL.toObjectPb())); + EasyMock.replay(storageRpcMock); + initializeService(); + List acls = storage.listAcls(blobId); + assertEquals(ImmutableList.of(ACL, OTHER_ACL), acls); + } + @Test public void testRetryableException() { BlobId blob = BlobId.of(BUCKET_NAME1, BLOB_NAME1); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 5b7fa3a84e63..e91486944bd7 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -29,6 +29,9 @@ import com.google.cloud.ReadChannel; import com.google.cloud.RestorableState; import com.google.cloud.WriteChannel; +import com.google.cloud.storage.Acl; +import com.google.cloud.storage.Acl.Role; +import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.Blob; import com.google.cloud.storage.BlobId; import com.google.cloud.storage.BlobInfo; @@ -48,6 +51,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -1219,4 +1223,70 @@ public void testUpdateBlobsFail() { assertNull(updatedBlobs.get(1)); assertTrue(updatedBlobs.get(0).delete()); } + + @Test + public void testBucketAcl() { + assertNull(storage.getAcl(BUCKET, User.ofAllAuthenticatedUsers())); + assertFalse(storage.deleteAcl(BUCKET, User.ofAllAuthenticatedUsers())); + Acl acl = Acl.of(User.ofAllAuthenticatedUsers(), Role.READER); + assertNotNull(storage.createAcl(BUCKET, acl)); + Acl updatedAcl = storage.updateAcl(BUCKET, acl.toBuilder().role(Role.WRITER).build()); + assertEquals(Role.WRITER, updatedAcl.role()); + Set acls = Sets.newHashSet(storage.listAcls(BUCKET)); + assertTrue(acls.contains(updatedAcl)); + assertTrue(storage.deleteAcl(BUCKET, User.ofAllAuthenticatedUsers())); + assertNull(storage.getAcl(BUCKET, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testBucketDefaultAcl() { + assertNull(storage.getDefaultAcl(BUCKET, User.ofAllAuthenticatedUsers())); + assertFalse(storage.deleteDefaultAcl(BUCKET, User.ofAllAuthenticatedUsers())); + Acl acl = Acl.of(User.ofAllAuthenticatedUsers(), Role.READER); + assertNotNull(storage.createDefaultAcl(BUCKET, acl)); + Acl updatedAcl = storage.updateDefaultAcl(BUCKET, acl.toBuilder().role(Role.OWNER).build()); + assertEquals(Role.OWNER, updatedAcl.role()); + Set acls = Sets.newHashSet(storage.listDefaultAcls(BUCKET)); + assertTrue(acls.contains(updatedAcl)); + assertTrue(storage.deleteDefaultAcl(BUCKET, User.ofAllAuthenticatedUsers())); + assertNull(storage.getDefaultAcl(BUCKET, User.ofAllAuthenticatedUsers())); + } + + @Test + public void testBlobAcl() { + BlobId blobId = BlobId.of(BUCKET, "test-blob-acl"); + BlobInfo blob = BlobInfo.builder(blobId).build(); + storage.create(blob); + assertNull(storage.getAcl(blobId, User.ofAllAuthenticatedUsers())); + Acl acl = Acl.of(User.ofAllAuthenticatedUsers(), Role.READER); + assertNotNull(storage.createAcl(blobId, acl)); + Acl updatedAcl = storage.updateAcl(blobId, acl.toBuilder().role(Role.OWNER).build()); + assertEquals(Role.OWNER, updatedAcl.role()); + Set acls = Sets.newHashSet(storage.listAcls(blobId)); + assertTrue(acls.contains(updatedAcl)); + assertTrue(storage.deleteAcl(blobId, User.ofAllAuthenticatedUsers())); + assertNull(storage.getAcl(blobId, User.ofAllAuthenticatedUsers())); + // test non-existing blob + BlobId otherBlobId = BlobId.of(BUCKET, "test-blob-acl", -1L); + assertNull(storage.getAcl(otherBlobId, User.ofAllAuthenticatedUsers())); + assertFalse(storage.deleteAcl(otherBlobId, User.ofAllAuthenticatedUsers())); + try { + storage.createAcl(otherBlobId, acl); + fail("Expected StorageException"); + } catch (StorageException ex) { + // expected + } + try { + storage.updateAcl(otherBlobId, acl); + fail("Expected StorageException"); + } catch (StorageException ex) { + // expected + } + try { + storage.listAcls(otherBlobId); + fail("Expected StorageException"); + } catch (StorageException ex) { + // expected + } + } } From 9451e1d3d9d5c401d8fdd7e304795e91287be0f8 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 7 Sep 2016 16:31:14 +0200 Subject: [PATCH 2/4] Add snippets for ACL-related methods to Storage --- .../storage/snippets/BlobSnippets.java | 66 +++++ .../storage/snippets/BucketSnippets.java | 132 +++++++++- .../storage/snippets/StorageSnippets.java | 236 +++++++++++++++++- .../storage/snippets/ITBlobSnippets.java | 14 ++ .../storage/snippets/ITBucketSnippets.java | 21 ++ .../storage/snippets/ITStorageSnippets.java | 69 +++++ .../java/com/google/cloud/storage/Blob.java | 33 +++ .../java/com/google/cloud/storage/Bucket.java | 70 +++++- .../com/google/cloud/storage/Storage.java | 143 ++++++++++- 9 files changed, 768 insertions(+), 16 deletions(-) diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BlobSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BlobSnippets.java index 2ffcd4dd5a38..d382f9c8f09a 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BlobSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BlobSnippets.java @@ -28,6 +28,8 @@ import com.google.cloud.ReadChannel; import com.google.cloud.ServiceAccountSigner; import com.google.cloud.WriteChannel; +import com.google.cloud.storage.Acl; +import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.Blob; import com.google.cloud.storage.Blob.BlobSourceOption; import com.google.cloud.storage.BlobId; @@ -40,6 +42,7 @@ import java.net.URL; import java.nio.ByteBuffer; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -228,4 +231,67 @@ public URL signUrlWithSigner(String keyPath) throws IOException { // [END signUrlWithSigner] return signedUrl; } + + /** + * Example of getting the ACL entry for an entity. + */ + // [TARGET getAcl(Entity)] + public Acl getAcl() { + // [START getAcl] + Acl acl = blob.getAcl(User.ofAllAuthenticatedUsers()); + // [END getAcl] + return acl; + } + + /** + * Example of deleting the ACL entry for an entity. + */ + // [TARGET deleteAcl(Entity)] + public boolean deleteAcl() { + // [START deleteAcl] + boolean deleted = blob.deleteAcl(User.ofAllAuthenticatedUsers()); + if (deleted) { + // the acl entry was deleted + } else { + // the acl entry was not found + } + // [END deleteAcl] + return deleted; + } + + /** + * Example of creating a new ACL entry. + */ + // [TARGET createAcl(Acl)] + public Acl createAcl() { + // [START createAcl] + Acl acl = blob.createAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.READER)); + // [END createAcl] + return acl; + } + + /** + * Example of updating a new ACL entry. + */ + // [TARGET updateAcl(Acl)] + public Acl updateAcl() { + // [START updateAcl] + Acl acl = blob.updateAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.OWNER)); + // [END updateAcl] + return acl; + } + + /** + * Example of listing the ACL entries. + */ + // [TARGET listAcls()] + public List listAcls() { + // [START listAcls] + List acls = blob.listAcls(); + for (Acl acl : acls) { + // do something with ACL entry + } + // [END listAcls] + return acls; + } } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BucketSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BucketSnippets.java index f9ef51941f26..c560c53af652 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BucketSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/BucketSnippets.java @@ -25,6 +25,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.cloud.Page; +import com.google.cloud.storage.Acl; +import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.Blob; import com.google.cloud.storage.Bucket; import com.google.cloud.storage.Bucket.BucketSourceOption; @@ -124,8 +126,8 @@ public Page listBlobs() { } /** - * Example of getting a blob in the bucket, only if its metageneration matches a value, otherwise - * a {@link StorageException} is thrown. + * Example of getting a blob in the bucket, only if its metageneration matches a value, + * otherwise a {@link StorageException} is thrown. */ // [TARGET get(String, BlobGetOption...)] // [VARIABLE "my_blob_name"] @@ -226,4 +228,130 @@ public Blob createBlobFromInputStreamWithContentType(String blobName) { // [END createBlobFromInputStreamWithContentType] return blob; } + + /** + * Example of getting the ACL entry for an entity. + */ + // [TARGET getAcl(Entity)] + public Acl getAcl() { + // [START getAcl] + Acl acl = bucket.getAcl(User.ofAllAuthenticatedUsers()); + // [END getAcl] + return acl; + } + + /** + * Example of deleting the ACL entry for an entity. + */ + // [TARGET deleteAcl(Entity)] + public boolean deleteAcl() { + // [START deleteAcl] + boolean deleted = bucket.deleteAcl(User.ofAllAuthenticatedUsers()); + if (deleted) { + // the acl entry was deleted + } else { + // the acl entry was not found + } + // [END deleteAcl] + return deleted; + } + + /** + * Example of creating a new ACL entry. + */ + // [TARGET createAcl(Acl)] + public Acl createAcl() { + // [START createAcl] + Acl acl = bucket.createAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.READER)); + // [END createAcl] + return acl; + } + + /** + * Example of updating a new ACL entry. + */ + // [TARGET updateAcl(Acl)] + public Acl updateAcl() { + // [START updateAcl] + Acl acl = bucket.updateAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.OWNER)); + // [END updateAcl] + return acl; + } + + /** + * Example of listing the ACL entries. + */ + // [TARGET listAcls()] + public List listAcls() { + // [START listAcls] + List acls = bucket.listAcls(); + for (Acl acl : acls) { + // do something with ACL entry + } + // [END listAcls] + return acls; + } + + /** + * Example of getting the default ACL entry for an entity. + */ + // [TARGET getDefaultAcl(Entity)] + public Acl getDefaultAcl() { + // [START getDefaultAcl] + Acl acl = bucket.getDefaultAcl(User.ofAllAuthenticatedUsers()); + // [END getDefaultAcl] + return acl; + } + + /** + * Example of deleting the default ACL entry for an entity. + */ + // [TARGET deleteDefaultAcl(Entity)] + public boolean deleteDefaultAcl() { + // [START deleteDefaultAcl] + boolean deleted = bucket.deleteDefaultAcl(User.ofAllAuthenticatedUsers()); + if (deleted) { + // the acl entry was deleted + } else { + // the acl entry was not found + } + // [END deleteDefaultAcl] + return deleted; + } + + /** + * Example of creating a new default ACL entry. + */ + // [TARGET createDefaultAcl(Acl)] + public Acl createDefaultAcl() { + // [START createDefaultAcl] + Acl acl = bucket.createDefaultAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.READER)); + // [END createDefaultAcl] + return acl; + } + + /** + * Example of updating a new default ACL entry. + */ + // [TARGET updateDefaultAcl(Acl)] + public Acl updateDefaultAcl() { + // [START updateDefaultAcl] + Acl acl = bucket.updateDefaultAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.OWNER)); + // [END updateDefaultAcl] + return acl; + } + + /** + * Example of listing the default ACL entries. + */ + // [TARGET listDefaultAcls()] + public List listDefaultAcls() { + // [START listDefaultAcls] + List acls = bucket.listDefaultAcls(); + for (Acl acl : acls) { + // do something with ACL entry + } + // [END listDefaultAcls] + return acls; + } } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/StorageSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/StorageSnippets.java index 88f39f9c98ed..8cc262ea0a5c 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/StorageSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/snippets/StorageSnippets.java @@ -30,6 +30,9 @@ import com.google.cloud.ReadChannel; import com.google.cloud.ServiceAccountSigner; import com.google.cloud.WriteChannel; +import com.google.cloud.storage.Acl; +import com.google.cloud.storage.Acl.Role; +import com.google.cloud.storage.Acl.User; import com.google.cloud.storage.Blob; import com.google.cloud.storage.BlobId; import com.google.cloud.storage.BlobInfo; @@ -149,8 +152,8 @@ public Bucket getBucketWithMetageneration(String bucketName, long bucketMetagene } /** - * Example of getting information on a blob, only if its metageneration matches a value, otherwise - * a {@link StorageException} is thrown. + * Example of getting information on a blob, only if its metageneration matches a value, + * otherwise a {@link StorageException} is thrown. */ // [TARGET get(String, String, BlobGetOption...)] // [VARIABLE "my_unique_bucket"] @@ -180,8 +183,8 @@ public Blob getBlobFromId(String bucketName, String blobName) { } /** - * Example of getting information on a blob, only if its metageneration matches a value, otherwise - * a {@link StorageException} is thrown. + * Example of getting information on a blob, only if its metageneration matches a value, + * otherwise a {@link StorageException} is thrown. */ // [TARGET get(BlobId, BlobGetOption...)] // [VARIABLE "my_unique_bucket"] @@ -549,8 +552,8 @@ public void writer(String bucketName, String blobName) throws IOException { } /** - * Example of creating a signed URL that is valid for 2 weeks, using the default credentials for - * signing the URL. + * Example of creating a signed URL that is valid for 2 weeks, using the default credentials + * for signing the URL. */ // [TARGET signUrl(BlobInfo, long, TimeUnit, SignUrlOption...)] // [VARIABLE "my_unique_bucket"] @@ -684,4 +687,225 @@ public List batchDeleteIterable(String bucketName, String blobName1, St // [END batchDeleteIterable] return deleted; } + + /** + * Example of getting the ACL entry for an entity on a bucket. + */ + // [TARGET getAcl(String, Entity)] + // [VARIABLE "my_unique_bucket"] + public Acl getBucketAcl(String bucketName) { + // [START getBucketAcl] + Acl acl = storage.getAcl(bucketName, User.ofAllAuthenticatedUsers()); + // [END getBucketAcl] + return acl; + } + + /** + * Example of deleting the ACL entry for an entity on a bucket. + */ + // [TARGET deleteAcl(String, Entity)] + // [VARIABLE "my_unique_bucket"] + public boolean deleteBucketAcl(String bucketName) { + // [START deleteBucketAcl] + boolean deleted = storage.deleteAcl(bucketName, User.ofAllAuthenticatedUsers()); + if (deleted) { + // the acl entry was deleted + } else { + // the acl entry was not found + } + // [END deleteBucketAcl] + return deleted; + } + + /** + * Example of creating a new ACL entry on a bucket. + */ + // [TARGET createAcl(String, Acl)] + // [VARIABLE "my_unique_bucket"] + public Acl createBucketAcl(String bucketName) { + // [START createBucketAcl] + Acl acl = storage.createAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER)); + // [END createBucketAcl] + return acl; + } + + /** + * Example of updating a new ACL entry on a bucket. + */ + // [TARGET updateAcl(String, Acl)] + // [VARIABLE "my_unique_bucket"] + public Acl updateBucketAcl(String bucketName) { + // [START updateBucketAcl] + Acl acl = storage.updateAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER)); + // [END updateBucketAcl] + return acl; + } + + /** + * Example of listing the ACL entries for a blob. + */ + // [TARGET listAcls(String)] + // [VARIABLE "my_unique_bucket"] + public List listBucketAcls(String bucketName) { + // [START listBucketAcls] + List acls = storage.listAcls(bucketName); + for (Acl acl : acls) { + // do something with ACL entry + } + // [END listBucketAcls] + return acls; + } + + /** + * Example of getting the default ACL entry for an entity on a bucket. + */ + // [TARGET getDefaultAcl(String, Entity)] + // [VARIABLE "my_unique_bucket"] + public Acl getDefaultBucketAcl(String bucketName) { + // [START getDefaultBucketAcl] + Acl acl = storage.getDefaultAcl(bucketName, User.ofAllAuthenticatedUsers()); + // [END getDefaultBucketAcl] + return acl; + } + + /** + * Example of deleting the default ACL entry for an entity on a bucket. + */ + // [TARGET deleteDefaultAcl(String, Entity)] + // [VARIABLE "my_unique_bucket"] + public boolean deleteDefaultBucketAcl(String bucketName) { + // [START deleteDefaultBucketAcl] + boolean deleted = storage.deleteDefaultAcl(bucketName, User.ofAllAuthenticatedUsers()); + if (deleted) { + // the acl entry was deleted + } else { + // the acl entry was not found + } + // [END deleteDefaultBucketAcl] + return deleted; + } + + /** + * Example of creating a new default ACL entry on a bucket. + */ + // [TARGET createDefaultAcl(String, Acl)] + // [VARIABLE "my_unique_bucket"] + public Acl createDefaultBucketAcl(String bucketName) { + // [START createDefaultBucketAcl] + Acl acl = + storage.createDefaultAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER)); + // [END createDefaultBucketAcl] + return acl; + } + + /** + * Example of updating a new default ACL entry on a bucket. + */ + // [TARGET updateDefaultAcl(String, Acl)] + // [VARIABLE "my_unique_bucket"] + public Acl updateDefaultBucketAcl(String bucketName) { + // [START updateDefaultBucketAcl] + Acl acl = + storage.updateDefaultAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER)); + // [END updateDefaultBucketAcl] + return acl; + } + + /** + * Example of listing the default ACL entries for a blob. + */ + // [TARGET listDefaultAcls(String)] + // [VARIABLE "my_unique_bucket"] + public List listDefaultBucketAcls(String bucketName) { + // [START listDefaultBucketAcls] + List acls = storage.listDefaultAcls(bucketName); + for (Acl acl : acls) { + // do something with ACL entry + } + // [END listDefaultBucketAcls] + return acls; + } + + /** + * Example of getting the ACL entry for an entity on a blob. + */ + // [TARGET getAcl(BlobId, Entity)] + // [VARIABLE "my_unique_bucket"] + // [VARIABLE "my_blob_name"] + // [VARIABLE 42] + public Acl getBlobAcl(String bucketName, String blobName, long blobGeneration) { + // [START getBlobAcl] + BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration); + Acl acl = storage.getAcl(blobId, User.ofAllAuthenticatedUsers()); + // [END getBlobAcl] + return acl; + } + + /** + * Example of deleting the ACL entry for an entity on a blob. + */ + // [TARGET deleteAcl(BlobId, Entity)] + // [VARIABLE "my_unique_bucket"] + // [VARIABLE "my_blob_name"] + // [VARIABLE 42] + public boolean deleteBlobAcl(String bucketName, String blobName, long blobGeneration) { + // [START deleteBlobAcl] + BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration); + boolean deleted = storage.deleteAcl(blobId, User.ofAllAuthenticatedUsers()); + if (deleted) { + // the acl entry was deleted + } else { + // the acl entry was not found + } + // [END deleteBlobAcl] + return deleted; + } + + /** + * Example of creating a new ACL entry on a blob. + */ + // [TARGET createAcl(BlobId, Acl)] + // [VARIABLE "my_unique_bucket"] + // [VARIABLE "my_blob_name"] + // [VARIABLE 42] + public Acl createBlobAcl(String bucketName, String blobName, long blobGeneration) { + // [START createBlobAcl] + BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration); + Acl acl = storage.createAcl(blobId, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER)); + // [END createBlobAcl] + return acl; + } + + /** + * Example of updating a new ACL entry on a blob. + */ + // [TARGET updateAcl(BlobId, Acl)] + // [VARIABLE "my_unique_bucket"] + // [VARIABLE "my_blob_name"] + // [VARIABLE 42] + public Acl updateBlobAcl(String bucketName, String blobName, long blobGeneration) { + // [START updateBlobAcl] + BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration); + Acl acl = storage.updateAcl(blobId, Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER)); + // [END updateBlobAcl] + return acl; + } + + /** + * Example of listing the ACL entries for a blob. + */ + // [TARGET listAcls(BlobId)] + // [VARIABLE "my_unique_bucket"] + // [VARIABLE "my_blob_name"] + // [VARIABLE 42] + public List listBlobAcls(String bucketName, String blobName, long blobGeneration) { + // [START listBlobAcls] + BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration); + List acls = storage.listAcls(blobId); + for (Acl acl : acls) { + // do something with ACL entry + } + // [END listBlobAcls] + return acls; + } } diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBlobSnippets.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBlobSnippets.java index 5fe46a54b722..9fcfb2a4a416 100644 --- a/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBlobSnippets.java +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBlobSnippets.java @@ -21,9 +21,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.google.cloud.storage.Acl; import com.google.cloud.storage.Blob; import com.google.cloud.storage.BlobId; import com.google.cloud.storage.BlobInfo; @@ -32,6 +34,7 @@ import com.google.cloud.storage.StorageException; import com.google.cloud.storage.testing.RemoteStorageHelper; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -43,6 +46,7 @@ import java.io.InputStream; import java.net.URL; import java.net.URLConnection; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -101,6 +105,7 @@ public void testBlob() throws IOException { copiedBlob.delete(); copiedBlob = blobSnippets.copyToBucket(BUCKET); assertNotNull(copiedBlob); + copiedBlob.delete(); blobSnippets.reload(); blobSnippets.writer(); URL signedUrl = blobSnippets.signUrl(); @@ -117,6 +122,15 @@ public void testBlob() throws IOException { assertArrayEquals(CONTENT, readBytes); } assertFalse(blobSnippets.delete()); + blobSnippets = new BlobSnippets(storage.get(blob.bucket(), blob.name())); + assertNull(blobSnippets.getAcl()); + assertNotNull(blobSnippets.createAcl()); + Acl updatedAcl = blobSnippets.updateAcl(); + assertEquals(Acl.Role.OWNER, updatedAcl.role()); + Set acls = Sets.newHashSet(blobSnippets.listAcls()); + assertTrue(acls.contains(updatedAcl)); + assertTrue(blobSnippets.deleteAcl()); + assertNull(blobSnippets.getAcl()); storage.delete(BlobId.of(BUCKET, BLOB)); } } diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBucketSnippets.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBucketSnippets.java index 5a8dd68f77a4..87e8b40fbdff 100644 --- a/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBucketSnippets.java +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITBucketSnippets.java @@ -18,8 +18,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import com.google.cloud.storage.Acl; +import com.google.cloud.storage.Acl.Role; import com.google.cloud.storage.Blob; import com.google.cloud.storage.Bucket; import com.google.cloud.storage.BucketInfo; @@ -109,6 +112,24 @@ public void testBucket() throws InterruptedException { blobs = bucketSnippets.getBlobFromStringIterable(BLOB3, BLOB4); assertEquals(BLOB3, blobs.get(0).name()); assertEquals(BLOB4, blobs.get(1).name()); + // test ACLs + assertNull(bucketSnippets.getAcl()); + assertNotNull(bucketSnippets.createAcl()); + Acl updatedAcl = bucketSnippets.updateAcl(); + assertEquals(Role.OWNER, updatedAcl.role()); + Set acls = Sets.newHashSet(bucketSnippets.listAcls()); + assertTrue(acls.contains(updatedAcl)); + assertTrue(bucketSnippets.deleteAcl()); + assertNull(bucketSnippets.getAcl()); + // test default ACLs + assertNull(bucketSnippets.getDefaultAcl()); + assertNotNull(bucketSnippets.createDefaultAcl()); + updatedAcl = bucketSnippets.updateDefaultAcl(); + assertEquals(Role.OWNER, updatedAcl.role()); + acls = Sets.newHashSet(bucketSnippets.listDefaultAcls()); + assertTrue(acls.contains(updatedAcl)); + assertTrue(bucketSnippets.deleteDefaultAcl()); + assertNull(bucketSnippets.getDefaultAcl()); thrown.expect(StorageException.class); assertTrue(bucketSnippets.delete()); } diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITStorageSnippets.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITStorageSnippets.java index 363bfe80f464..fcb00fae6134 100644 --- a/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITStorageSnippets.java +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/storage/snippets/ITStorageSnippets.java @@ -21,17 +21,21 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.google.cloud.Page; +import com.google.cloud.storage.Acl; import com.google.cloud.storage.Blob; +import com.google.cloud.storage.BlobId; import com.google.cloud.storage.BlobInfo; import com.google.cloud.storage.Bucket; import com.google.cloud.storage.Storage; import com.google.cloud.storage.StorageException; import com.google.cloud.storage.testing.RemoteStorageHelper; import com.google.common.collect.Iterators; +import com.google.common.collect.Sets; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -256,4 +260,69 @@ public void testBatchIterable() throws IOException { assertFalse(deleted.get(0)); assertTrue(deleted.get(1)); } + + @Test + public void testBucketAcl() { + assertNull(storageSnippets.getBucketAcl(BUCKET)); + assertFalse(storageSnippets.deleteBucketAcl(BUCKET)); + assertNotNull(storageSnippets.createBucketAcl(BUCKET)); + Acl updatedAcl = storageSnippets.updateBucketAcl(BUCKET); + assertEquals(Acl.Role.OWNER, updatedAcl.role()); + Set acls = Sets.newHashSet(storageSnippets.listBucketAcls(BUCKET)); + assertTrue(acls.contains(updatedAcl)); + assertTrue(storageSnippets.deleteBucketAcl(BUCKET)); + assertNull(storageSnippets.getBucketAcl(BUCKET)); + } + + @Test + public void testDefaultBucketAcl() { + assertNull(storageSnippets.getDefaultBucketAcl(BUCKET)); + assertFalse(storageSnippets.deleteDefaultBucketAcl(BUCKET)); + assertNotNull(storageSnippets.createDefaultBucketAcl(BUCKET)); + Acl updatedAcl = storageSnippets.updateDefaultBucketAcl(BUCKET); + assertEquals(Acl.Role.OWNER, updatedAcl.role()); + Set acls = Sets.newHashSet(storageSnippets.listDefaultBucketAcls(BUCKET)); + assertTrue(acls.contains(updatedAcl)); + assertTrue(storageSnippets.deleteDefaultBucketAcl(BUCKET)); + assertNull(storageSnippets.getDefaultBucketAcl(BUCKET)); + } + + @Test + public void testBlobAcl() { + String blobName = "test-blob-acl"; + BlobId blobId = BlobId.of(BUCKET, "test-blob-acl"); + BlobInfo blob = BlobInfo.builder(blobId).build(); + Blob createdBlob = storage.create(blob); + assertNull(storageSnippets.getBlobAcl(BUCKET, blobName, createdBlob.generation())); + assertNotNull(storageSnippets.createBlobAcl(BUCKET, blobName, createdBlob.generation())); + Acl updatedAcl = storageSnippets.updateBlobAcl(BUCKET, blobName, createdBlob.generation()); + assertEquals(Acl.Role.OWNER, updatedAcl.role()); + Set acls = + Sets.newHashSet(storageSnippets.listBlobAcls(BUCKET, blobName, createdBlob.generation())); + assertTrue(acls.contains(updatedAcl)); + assertTrue(storageSnippets.deleteBlobAcl(BUCKET, blobName, createdBlob.generation())); + assertNull(storageSnippets.getBlobAcl(BUCKET, blobName, createdBlob.generation())); + // test non-existing blob + String nonExistingBlob = "test-blob-acl"; + assertNull(storageSnippets.getBlobAcl(BUCKET, nonExistingBlob, -1L)); + assertFalse(storageSnippets.deleteBlobAcl(BUCKET, nonExistingBlob, -1L)); + try { + storageSnippets.createBlobAcl(BUCKET, nonExistingBlob, -1L); + fail("Expected StorageException"); + } catch (StorageException ex) { + // expected + } + try { + storageSnippets.updateBlobAcl(BUCKET, nonExistingBlob, -1L); + fail("Expected StorageException"); + } catch (StorageException ex) { + // expected + } + try { + storageSnippets.listBlobAcls(BUCKET, nonExistingBlob, -1L); + fail("Expected StorageException"); + } catch (StorageException ex) { + // expected + } + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index 53490cbf1bb7..1c2f9f57243f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -606,6 +606,11 @@ public URL signUrl(long duration, TimeUnit unit, SignUrlOption... options) { /** * Returns the ACL entry for the specified entity on this blob or {@code null} if not found. * + *

Example of getting the ACL entry for an entity. + *

 {@code
+   * Acl acl = blob.getAcl(User.ofAllAuthenticatedUsers());
+   * }
+ * * @throws StorageException upon failure */ public Acl getAcl(Entity entity) { @@ -615,6 +620,16 @@ public Acl getAcl(Entity entity) { /** * Deletes the ACL entry for the specified entity on this blob. * + *

Example of deleting the ACL entry for an entity. + *

 {@code
+   * boolean deleted = blob.deleteAcl(User.ofAllAuthenticatedUsers());
+   * if (deleted) {
+   *   // the acl entry was deleted
+   * } else {
+   *   // the acl entry was not found
+   * }
+   * }
+ * * @return {@code true} if the ACL was deleted, {@code false} if it was not found * @throws StorageException upon failure */ @@ -625,6 +640,11 @@ public boolean deleteAcl(Entity entity) { /** * Creates a new ACL entry on this blob. * + *

Example of creating a new ACL entry. + *

 {@code
+   * Acl acl = blob.createAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.READER));
+   * }
+ * * @throws StorageException upon failure */ public Acl createAcl(Acl acl) { @@ -634,6 +654,11 @@ public Acl createAcl(Acl acl) { /** * Updates an ACL entry on this blob. * + *

Example of updating a new ACL entry. + *

 {@code
+   * Acl acl = blob.updateAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.OWNER));
+   * }
+ * * @throws StorageException upon failure */ public Acl updateAcl(Acl acl) { @@ -643,6 +668,14 @@ public Acl updateAcl(Acl acl) { /** * Lists the ACL entries for this blob. * + *

Example of listing the ACL entries. + *

 {@code
+   * List acls = blob.listAcls();
+   * for (Acl acl : acls) {
+   *   // do something with ACL entry
+   * }
+   * }
+ * * @throws StorageException upon failure */ public List listAcls() { diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index b149955073f8..9955dda330f3 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -637,8 +637,8 @@ public Page list(BlobListOption... options) { /** * Returns the requested blob in this bucket or {@code null} if not found. * - *

Example of getting a blob in the bucket, only if its metageneration matches a value, otherwise - * a {@link StorageException} is thrown. + *

Example of getting a blob in the bucket, only if its metageneration matches a value, + * otherwise a {@link StorageException} is thrown. *

 {@code
    * String blobName = "my_blob_name";
    * long generation = 42;
@@ -820,6 +820,11 @@ public Blob create(String blob, InputStream content, BlobWriteOption... options)
   /**
    * Returns the ACL entry for the specified entity on this bucket or {@code null} if not found.
    *
+   * 

Example of getting the ACL entry for an entity. + *

 {@code
+   * Acl acl = bucket.getAcl(User.ofAllAuthenticatedUsers());
+   * }
+ * * @throws StorageException upon failure */ public Acl getAcl(Entity entity) { @@ -829,6 +834,16 @@ public Acl getAcl(Entity entity) { /** * Deletes the ACL entry for the specified entity on this bucket. * + *

Example of deleting the ACL entry for an entity. + *

 {@code
+   * boolean deleted = bucket.deleteAcl(User.ofAllAuthenticatedUsers());
+   * if (deleted) {
+   *   // the acl entry was deleted
+   * } else {
+   *   // the acl entry was not found
+   * }
+   * }
+ * * @return {@code true} if the ACL was deleted, {@code false} if it was not found * @throws StorageException upon failure */ @@ -839,6 +854,11 @@ public boolean deleteAcl(Entity entity) { /** * Creates a new ACL entry on this bucket. * + *

Example of creating a new ACL entry. + *

 {@code
+   * Acl acl = bucket.createAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.READER));
+   * }
+ * * @throws StorageException upon failure */ public Acl createAcl(Acl acl) { @@ -848,6 +868,11 @@ public Acl createAcl(Acl acl) { /** * Updates an ACL entry on this bucket. * + *

Example of updating a new ACL entry. + *

 {@code
+   * Acl acl = bucket.updateAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.OWNER));
+   * }
+ * * @throws StorageException upon failure */ public Acl updateAcl(Acl acl) { @@ -857,6 +882,14 @@ public Acl updateAcl(Acl acl) { /** * Lists the ACL entries for this bucket. * + *

Example of listing the ACL entries. + *

 {@code
+   * List acls = bucket.listAcls();
+   * for (Acl acl : acls) {
+   *   // do something with ACL entry
+   * }
+   * }
+ * * @throws StorageException upon failure */ public List listAcls() { @@ -870,6 +903,11 @@ public List listAcls() { *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

Example of getting the default ACL entry for an entity. + *

 {@code
+   * Acl acl = bucket.getDefaultAcl(User.ofAllAuthenticatedUsers());
+   * }
+ * * @throws StorageException upon failure */ public Acl getDefaultAcl(Entity entity) { @@ -882,6 +920,16 @@ public Acl getDefaultAcl(Entity entity) { *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

Example of deleting the default ACL entry for an entity. + *

 {@code
+   * boolean deleted = bucket.deleteDefaultAcl(User.ofAllAuthenticatedUsers());
+   * if (deleted) {
+   *   // the acl entry was deleted
+   * } else {
+   *   // the acl entry was not found
+   * }
+   * }
+ * * @return {@code true} if the ACL was deleted, {@code false} if it was not found * @throws StorageException upon failure */ @@ -895,6 +943,11 @@ public boolean deleteDefaultAcl(Entity entity) { *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

Example of creating a new default ACL entry. + *

 {@code
+   * Acl acl = bucket.createDefaultAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.READER));
+   * }
+ * * @throws StorageException upon failure */ public Acl createDefaultAcl(Acl acl) { @@ -907,6 +960,11 @@ public Acl createDefaultAcl(Acl acl) { *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

Example of updating a new default ACL entry. + *

 {@code
+   * Acl acl = bucket.updateDefaultAcl(Acl.of(User.ofAllAuthenticatedUsers(), Acl.Role.OWNER));
+   * }
+ * * @throws StorageException upon failure */ public Acl updateDefaultAcl(Acl acl) { @@ -919,6 +977,14 @@ public Acl updateDefaultAcl(Acl acl) { *

Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

Example of listing the default ACL entries. + *

 {@code
+   * List acls = bucket.listDefaultAcls();
+   * for (Acl acl : acls) {
+   *   // do something with ACL entry
+   * }
+   * }
+ * * @throws StorageException upon failure */ public List listDefaultAcls() { diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 68c483aa35fd..4d8f44608242 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -1303,8 +1303,8 @@ public static Builder builder() { /** * Returns the requested blob or {@code null} if not found. * - *

Example of getting information on a blob, only if its metageneration matches a value, otherwise - * a {@link StorageException} is thrown. + *

Example of getting information on a blob, only if its metageneration matches a value, + * otherwise a {@link StorageException} is thrown. *

 {@code
    * String bucketName = "my_unique_bucket";
    * String blobName = "my_blob_name";
@@ -1320,8 +1320,8 @@ public static Builder builder() {
   /**
    * Returns the requested blob or {@code null} if not found.
    *
-   * 

Example of getting information on a blob, only if its metageneration matches a value, otherwise - * a {@link StorageException} is thrown. + *

Example of getting information on a blob, only if its metageneration matches a value, + * otherwise a {@link StorageException} is thrown. *

 {@code
    * String bucketName = "my_unique_bucket";
    * String blobName = "my_blob_name";
@@ -1774,8 +1774,8 @@ public static Builder builder() {
    *   
  • The default credentials, if no credentials were passed to {@link StorageOptions} * * - *

    Example of creating a signed URL that is valid for 2 weeks, using the default credentials for - * signing the URL. + *

    Example of creating a signed URL that is valid for 2 weeks, using the default credentials + * for signing the URL. *

     {@code
        * String bucketName = "my_unique_bucket";
        * String blobName = "my_blob_name";
    @@ -1954,6 +1954,12 @@ public static Builder builder() {
        * Returns the ACL entry for the specified entity on the specified bucket or {@code null} if not
        * found.
        *
    +   * 

    Example of getting the ACL entry for an entity on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Acl acl = storage.getAcl(bucketName, User.ofAllAuthenticatedUsers());
    +   * }
    + * * @throws StorageException upon failure */ Acl getAcl(String bucket, Entity entity); @@ -1961,6 +1967,17 @@ public static Builder builder() { /** * Deletes the ACL entry for the specified entity on the specified bucket. * + *

    Example of deleting the ACL entry for an entity on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * boolean deleted = storage.deleteAcl(bucketName, User.ofAllAuthenticatedUsers());
    +   * if (deleted) {
    +   *   // the acl entry was deleted
    +   * } else {
    +   *   // the acl entry was not found
    +   * }
    +   * }
    + * * @return {@code true} if the ACL was deleted, {@code false} if it was not found * @throws StorageException upon failure */ @@ -1969,6 +1986,12 @@ public static Builder builder() { /** * Creates a new ACL entry on the specified bucket. * + *

    Example of creating a new ACL entry on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Acl acl = storage.createAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER));
    +   * }
    + * * @throws StorageException upon failure */ Acl createAcl(String bucket, Acl acl); @@ -1976,6 +1999,12 @@ public static Builder builder() { /** * Updates an ACL entry on the specified bucket. * + *

    Example of updating a new ACL entry on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Acl acl = storage.updateAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER));
    +   * }
    + * * @throws StorageException upon failure */ Acl updateAcl(String bucket, Acl acl); @@ -1983,6 +2012,15 @@ public static Builder builder() { /** * Lists the ACL entries for the provided bucket. * + *

    Example of listing the ACL entries for a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * List acls = storage.listAcls(bucketName);
    +   * for (Acl acl : acls) {
    +   *   // do something with ACL entry
    +   * }
    +   * }
    + * * @throws StorageException upon failure */ List listAcls(String bucket); @@ -1994,6 +2032,12 @@ public static Builder builder() { *

    Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

    Example of getting the default ACL entry for an entity on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Acl acl = storage.getDefaultAcl(bucketName, User.ofAllAuthenticatedUsers());
    +   * }
    + * * @throws StorageException upon failure */ Acl getDefaultAcl(String bucket, Entity entity); @@ -2004,6 +2048,17 @@ public static Builder builder() { *

    Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

    Example of deleting the default ACL entry for an entity on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * boolean deleted = storage.deleteDefaultAcl(bucketName, User.ofAllAuthenticatedUsers());
    +   * if (deleted) {
    +   *   // the acl entry was deleted
    +   * } else {
    +   *   // the acl entry was not found
    +   * }
    +   * }
    + * * @return {@code true} if the ACL was deleted, {@code false} if it was not found * @throws StorageException upon failure */ @@ -2015,6 +2070,13 @@ public static Builder builder() { *

    Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

    Example of creating a new default ACL entry on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Acl acl =
    +   *     storage.createDefaultAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER));
    +   * }
    + * * @throws StorageException upon failure */ Acl createDefaultAcl(String bucket, Acl acl); @@ -2025,6 +2087,13 @@ public static Builder builder() { *

    Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

    Example of updating a new default ACL entry on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Acl acl =
    +   *     storage.updateDefaultAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER));
    +   * }
    + * * @throws StorageException upon failure */ Acl updateDefaultAcl(String bucket, Acl acl); @@ -2035,6 +2104,15 @@ public static Builder builder() { *

    Default ACLs are applied to a new blob within the bucket when no ACL was provided for that * blob. * + *

    Example of listing the default ACL entries for a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * List acls = storage.listDefaultAcls(bucketName);
    +   * for (Acl acl : acls) {
    +   *   // do something with ACL entry
    +   * }
    +   * }
    + * * @throws StorageException upon failure */ List listDefaultAcls(String bucket); @@ -2043,6 +2121,15 @@ public static Builder builder() { * Returns the ACL entry for the specified entity on the specified blob or {@code null} if not * found. * + *

    Example of getting the ACL entry for an entity on a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * String blobName = "my_blob_name";
    +   * long blobGeneration = 42;
    +   * BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration);
    +   * Acl acl = storage.getAcl(blobId, User.ofAllAuthenticatedUsers());
    +   * }
    + * * @throws StorageException upon failure */ Acl getAcl(BlobId blob, Entity entity); @@ -2050,6 +2137,20 @@ public static Builder builder() { /** * Deletes the ACL entry for the specified entity on the specified blob. * + *

    Example of deleting the ACL entry for an entity on a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * String blobName = "my_blob_name";
    +   * long blobGeneration = 42;
    +   * BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration);
    +   * boolean deleted = storage.deleteAcl(blobId, User.ofAllAuthenticatedUsers());
    +   * if (deleted) {
    +   *   // the acl entry was deleted
    +   * } else {
    +   *   // the acl entry was not found
    +   * }
    +   * }
    + * * @return {@code true} if the ACL was deleted, {@code false} if it was not found * @throws StorageException upon failure */ @@ -2058,6 +2159,15 @@ public static Builder builder() { /** * Creates a new ACL entry on the specified blob. * + *

    Example of creating a new ACL entry on a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * String blobName = "my_blob_name";
    +   * long blobGeneration = 42;
    +   * BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration);
    +   * Acl acl = storage.createAcl(blobId, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER));
    +   * }
    + * * @throws StorageException upon failure */ Acl createAcl(BlobId blob, Acl acl); @@ -2065,6 +2175,15 @@ public static Builder builder() { /** * Updates an ACL entry on the specified blob. * + *

    Example of updating a new ACL entry on a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * String blobName = "my_blob_name";
    +   * long blobGeneration = 42;
    +   * BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration);
    +   * Acl acl = storage.updateAcl(blobId, Acl.of(User.ofAllAuthenticatedUsers(), Role.OWNER));
    +   * }
    + * * @throws StorageException upon failure */ Acl updateAcl(BlobId blob, Acl acl); @@ -2072,6 +2191,18 @@ public static Builder builder() { /** * Lists the ACL entries for the provided blob. * + *

    Example of listing the ACL entries for a blob. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * String blobName = "my_blob_name";
    +   * long blobGeneration = 42;
    +   * BlobId blobId = BlobId.of(bucketName, blobName, blobGeneration);
    +   * List acls = storage.listAcls(blobId);
    +   * for (Acl acl : acls) {
    +   *   // do something with ACL entry
    +   * }
    +   * }
    + * * @throws StorageException upon failure */ List listAcls(BlobId blob); From b0046d0810b955e99f7fbee5e4f84c95ac3854bc Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 7 Sep 2016 16:38:04 +0200 Subject: [PATCH 3/4] Update StorageExample class to use new ACL methods --- .../google/cloud/examples/storage/StorageExample.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/StorageExample.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/StorageExample.java index dc8837a496dc..9d7548058b4f 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/StorageExample.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/storage/StorageExample.java @@ -582,7 +582,7 @@ public void run(Storage storage, Tuple params) { System.out.printf("Bucket %s does not exist%n", blobId.bucket()); return; } - bucket.toBuilder().acl(addAcl(bucket.acl(), acl)).build().update(); + acl = bucket.createAcl(acl); System.out.printf("Added ACL %s to bucket %s%n", acl, blobId.bucket()); } else { Blob blob = storage.get(blobId); @@ -590,16 +590,10 @@ public void run(Storage storage, Tuple params) { System.out.printf("Blob %s does not exist%n", blobId); return; } - blob.toBuilder().acl(addAcl(blob.acl(), acl)).build().update(); + acl = blob.createAcl(acl); System.out.printf("Added ACL %s to blob %s%n", acl, blobId); } } - - private static List addAcl(List acls, Acl newAcl) { - List newAcls = new LinkedList<>(acls); - newAcls.add(newAcl); - return newAcls; - } } /** From 5376eff36a01a0707b3741c54497927d7a0929d3 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Mon, 12 Sep 2016 10:53:29 +0200 Subject: [PATCH 4/4] Consistently order fields in Acl, update serialVersionUID --- .../java/com/google/cloud/storage/Acl.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java index e3dd72f6460f..9a0e60cac02a 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Acl.java @@ -34,8 +34,7 @@ */ public final class Acl implements Serializable { - private static final long serialVersionUID = 6435575339887912222L; - + private static final long serialVersionUID = 7516713233557576082L; static final Function FROM_OBJECT_PB_FUNCTION = new Function() { @Override @@ -51,10 +50,10 @@ public Acl apply(BucketAccessControl aclPb) { } }; - private final String id; - private final String etag; private final Entity entity; private final Role role; + private final String id; + private final String etag; public enum Role { OWNER, READER, WRITER @@ -359,33 +358,33 @@ private Acl(Builder builder) { } /** - * Returns the ID of the ACL entry. + * Returns the entity for this ACL object. */ - public String id() { - return id; + public Entity entity() { + return entity; } /** - * Returns HTTP 1.1 Entity tag for the ACL entry. - * - * @see Entity Tags + * Returns the role associated to the entity in this ACL object. */ - public String etag() { - return etag; + public Role role() { + return role; } /** - * Returns the entity for this ACL object. + * Returns the ID of the ACL entry. */ - public Entity entity() { - return entity; + public String id() { + return id; } /** - * Returns the role associated to the entity in this ACL object. + * Returns HTTP 1.1 Entity tag for the ACL entry. + * + * @see Entity Tags */ - public Role role() { - return role; + public String etag() { + return etag; } /** @@ -447,8 +446,8 @@ public boolean equals(Object obj) { BucketAccessControl toBucketPb() { BucketAccessControl bucketPb = new BucketAccessControl(); - bucketPb.setRole(role().toString()); bucketPb.setEntity(entity().toString()); + bucketPb.setRole(role().toString()); bucketPb.setId(id()); bucketPb.setEtag(etag()); return bucketPb; @@ -456,8 +455,8 @@ BucketAccessControl toBucketPb() { ObjectAccessControl toObjectPb() { ObjectAccessControl objectPb = new ObjectAccessControl(); - objectPb.setRole(role().name()); objectPb.setEntity(entity().toPb()); + objectPb.setRole(role().name()); objectPb.setId(id()); objectPb.setEtag(etag()); return objectPb;