Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
Fix #151/#163: use ACL-specific endpoints where feasible for buckets and keys#318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
7f4fe7c2d89c38b5247296fe5372de2ad66b7d2febcb234ee90717104e5af929bbf6086034e06fe3edca081689bdcf7d27File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -19,15 +19,27 @@ class Bucket(object): | ||
| :type name: string | ||
| :param name: The name of the bucket. | ||
| """ | ||
| # ACL rules are lazily retrieved. | ||
| _acl = _default_object_acl = None | ||
| def __init__(self, connection=None, name=None, metadata=None): | ||
| self.connection = connection | ||
| self.name = name | ||
| self.metadata = metadata | ||
| # ACL rules are lazily retrieved. | ||
| self.acl = None | ||
| self.default_object_acl = None | ||
| @property | ||
| def acl(self): | ||
| """Create our ACL on demand.""" | ||
| if self._acl is None: | ||
| self._acl = BucketACL(self) | ||
| return self._acl | ||
| @property | ||
| def default_object_acl(self): | ||
| """Create our defaultObjectACL on demand.""" | ||
| if self._default_object_acl is None: | ||
| self._default_object_acl = DefaultObjectACL(self) | ||
| return self._default_object_acl | ||
| @classmethod | ||
| def from_dict(cls, bucket_dict, connection=None): | ||
| @@ -313,17 +325,15 @@ def has_metadata(self, field=None): | ||
| else: | ||
| return True | ||
| def reload_metadata(self, full=False): | ||
| def reload_metadata(self): | ||
| """Reload metadata from Cloud Storage. | ||
| :type full: bool | ||
| :param full: If True, loads all data (include ACL data). | ||
| :rtype: :class:`Bucket` | ||
| :returns: The bucket you just reloaded data for. | ||
| """ | ||
| projection = 'full' if full else 'noAcl' | ||
| query_params = {'projection': projection} | ||
| # Pass only '?projection=noAcl' here because 'acl'/'defaultObjectAcl' | ||
| # are handled via 'get_acl()'/'get_default_object_acl()' | ||
| query_params = {'projection': 'noAcl'} | ||
| self.metadata = self.connection.api_request( | ||
| method='GET', path=self.path, query_params=query_params) | ||
| return self | ||
| @@ -344,9 +354,14 @@ def get_metadata(self, field=None, default=None): | ||
| :rtype: dict or anything | ||
| :returns: All metadata or the value of the specific field. | ||
| """ | ||
| if field == 'acl': | ||
| raise KeyError("Use 'get_acl()'") | ||
| if field == 'defaultObjectAcl': | ||
| raise KeyError("Use 'get_default_object_acl()'") | ||
| if not self.has_metadata(field=field): | ||
| full = (field and field in ('acl', 'defaultObjectAcl')) | ||
| self.reload_metadata(full=full) | ||
| self.reload_metadata() | ||
| if field: | ||
| return self.metadata.get(field, default) | ||
| @@ -431,11 +446,15 @@ def reload_acl(self): | ||
| :rtype: :class:`Bucket` | ||
| :returns: The current bucket. | ||
| """ | ||
| self.acl = BucketACL(bucket=self) | ||
| self.acl.clear() | ||
| url_path = '%s/acl' % self.path | ||
| found = self.connection.api_request(method='GET', path=url_path) | ||
| for entry in found['items']: | ||
| self.acl.add_entity(self.acl.entity_from_dict(entry)) | ||
| for entry in self.get_metadata('acl', []): | ||
| entity = self.acl.entity_from_dict(entry) | ||
| self.acl.add_entity(entity) | ||
| # Even if we fetch no entries, the ACL is still loaded. | ||
| self.acl.loaded = True | ||
| return self | ||
| @@ -445,7 +464,7 @@ def get_acl(self): | ||
| :rtype: :class:`gcloud.storage.acl.BucketACL` | ||
| :returns: An ACL object for the current bucket. | ||
| """ | ||
| if not self.acl: | ||
| if not self.acl.loaded: | ||
| self.reload_acl() | ||
| return self.acl | ||
| @@ -487,12 +506,19 @@ def save_acl(self, acl=None): | ||
| # both evaluate to False, but mean very different things. | ||
| if acl is None: | ||
| acl = self.acl | ||
| dirty = acl.loaded | ||
| else: | ||
| dirty = True | ||
| if acl is None: | ||
| return self | ||
| if dirty: | ||
| result = self.connection.api_request( | ||
| method='PATCH', path=self.path, data={'acl': list(acl)}, | ||
| query_params={'projection': 'full'}) | ||
| self.acl.clear() | ||
| for entry in result['acl']: | ||
| self.acl.entity(self.acl.entity_from_dict(entry)) | ||
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page. | ||
| self.acl.loaded = True | ||
| self.patch_metadata({'acl': list(acl)}) | ||
| self.reload_acl() | ||
| return self | ||
| def clear_acl(self): | ||
| @@ -522,19 +548,26 @@ def clear_acl(self): | ||
| At this point all the custom rules you created have been removed. | ||
| """ | ||
| return self.save_acl(acl=[]) | ||
| # NOTE: back-end makes some ACL entries sticky (they remain even | ||
| # after the PATCH succeeds. | ||
| return self.save_acl([]) | ||
| def reload_default_object_acl(self): | ||
| """Reload the Default Object ACL rules for this bucket. | ||
| :rtype: :class:`Bucket` | ||
| :returns: The current bucket. | ||
| """ | ||
| self.default_object_acl = DefaultObjectACL(bucket=self) | ||
| doa = self.default_object_acl | ||
| doa.clear() | ||
| for entry in self.get_metadata('defaultObjectAcl', []): | ||
| entity = self.default_object_acl.entity_from_dict(entry) | ||
| self.default_object_acl.add_entity(entity) | ||
| url_path = '%s/defaultObjectAcl' % self.path | ||
| found = self.connection.api_request(method='GET', path=url_path) | ||
| for entry in found['items']: | ||
| doa.add_entity(doa.entity_from_dict(entry)) | ||
| # Even if we fetch no entries, the ACL is still loaded. | ||
| doa.loaded = True | ||
| return self | ||
| @@ -547,7 +580,7 @@ def get_default_object_acl(self): | ||
| :rtype: :class:`gcloud.storage.acl.DefaultObjectACL` | ||
| :returns: A DefaultObjectACL object for this bucket. | ||
| """ | ||
| if not self.default_object_acl: | ||
| if not self.default_object_acl.loaded: | ||
| self.reload_default_object_acl() | ||
| return self.default_object_acl | ||
| @@ -562,18 +595,26 @@ def save_default_object_acl(self, acl=None): | ||
| """ | ||
| if acl is None: | ||
| acl = self.default_object_acl | ||
| dirty = acl.loaded | ||
| else: | ||
| dirty = True | ||
| if dirty: | ||
| result = self.connection.api_request( | ||
| method='PATCH', path=self.path, | ||
| data={'defaultObjectAcl': list(acl)}, | ||
| query_params={'projection': 'full'}) | ||
| doa = self.default_object_acl | ||
| doa.clear() | ||
| for entry in result['defaultObjectAcl']: | ||
| doa.entity(doa.entity_from_dict(entry)) | ||
| doa.loaded = True | ||
| if acl is None: | ||
| return self | ||
| self.patch_metadata({'defaultObjectAcl': list(acl)}) | ||
| self.reload_default_object_acl() | ||
| return self | ||
| def clear_default_object_acl(self): | ||
| """Remove the Default Object ACL from this bucket.""" | ||
| return self.save_default_object_acl(acl=[]) | ||
| return self.save_default_object_acl([]) | ||
| def make_public(self, recursive=False, future=False): | ||
| """Make a bucket public. | ||
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.