Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(628)

Unified Diff: third_party/boto/boto/gs/acl.py

Issue 12755026: Added gsutil/boto to depot_tools/third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Added readme Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/boto/boto/gs/__init__.py ('k') | third_party/boto/boto/gs/bucket.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/boto/boto/gs/acl.py
diff --git a/third_party/boto/boto/gs/acl.py b/third_party/boto/boto/gs/acl.py
new file mode 100755
index 0000000000000000000000000000000000000000..047254cfa9b98a834a60130c5975555c4ec05126
--- /dev/null
+++ b/third_party/boto/boto/gs/acl.py
@@ -0,0 +1,304 @@
+# Copyright 2010 Google Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+from boto.gs.user import User
+from boto.exception import InvalidAclError
+
+ACCESS_CONTROL_LIST = 'AccessControlList'
+ALL_AUTHENTICATED_USERS = 'AllAuthenticatedUsers'
+ALL_USERS = 'AllUsers'
+DISPLAY_NAME = 'DisplayName'
+DOMAIN = 'Domain'
+EMAIL_ADDRESS = 'EmailAddress'
+ENTRY = 'Entry'
+ENTRIES = 'Entries'
+GROUP_BY_DOMAIN = 'GroupByDomain'
+GROUP_BY_EMAIL = 'GroupByEmail'
+GROUP_BY_ID = 'GroupById'
+ID = 'ID'
+NAME = 'Name'
+OWNER = 'Owner'
+PERMISSION = 'Permission'
+SCOPE = 'Scope'
+TYPE = 'type'
+USER_BY_EMAIL = 'UserByEmail'
+USER_BY_ID = 'UserById'
+
+
+CannedACLStrings = ['private', 'public-read', 'project-private',
+ 'public-read-write', 'authenticated-read',
+ 'bucket-owner-read', 'bucket-owner-full-control']
+"""A list of Google Cloud Storage predefined (canned) ACL strings."""
+
+SupportedPermissions = ['READ', 'WRITE', 'FULL_CONTROL']
+"""A list of supported ACL permissions."""
+
+class ACL:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+ self.entries = []
+
+ @property
+ def acl(self):
+ return self
+
+ def __repr__(self):
+ # Owner is optional in GS ACLs.
+ if hasattr(self, 'owner'):
+ entries_repr = ['Owner:%s' % self.owner.__repr__()]
+ else:
+ entries_repr = ['']
+ acl_entries = self.entries
+ if acl_entries:
+ for e in acl_entries.entry_list:
+ entries_repr.append(e.__repr__())
+ return '<%s>' % ', '.join(entries_repr)
+
+ # Method with same signature as boto.s3.acl.ACL.add_email_grant(), to allow
+ # polymorphic treatment at application layer.
+ def add_email_grant(self, permission, email_address):
+ entry = Entry(type=USER_BY_EMAIL, email_address=email_address,
+ permission=permission)
+ self.entries.entry_list.append(entry)
+
+ # Method with same signature as boto.s3.acl.ACL.add_user_grant(), to allow
+ # polymorphic treatment at application layer.
+ def add_user_grant(self, permission, user_id):
+ entry = Entry(permission=permission, type=USER_BY_ID, id=user_id)
+ self.entries.entry_list.append(entry)
+
+ def add_group_email_grant(self, permission, email_address):
+ entry = Entry(type=GROUP_BY_EMAIL, email_address=email_address,
+ permission=permission)
+ self.entries.entry_list.append(entry)
+
+ def add_group_grant(self, permission, group_id):
+ entry = Entry(type=GROUP_BY_ID, id=group_id, permission=permission)
+ self.entries.entry_list.append(entry)
+
+ def startElement(self, name, attrs, connection):
+ if name.lower() == OWNER.lower():
+ self.owner = User(self)
+ return self.owner
+ elif name.lower() == ENTRIES.lower():
+ self.entries = Entries(self)
+ return self.entries
+ else:
+ return None
+
+ def endElement(self, name, value, connection):
+ if name.lower() == OWNER.lower():
+ pass
+ elif name.lower() == ENTRIES.lower():
+ pass
+ else:
+ setattr(self, name, value)
+
+ def to_xml(self):
+ s = '<%s>' % ACCESS_CONTROL_LIST
+ # Owner is optional in GS ACLs.
+ if hasattr(self, 'owner'):
+ s += self.owner.to_xml()
+ acl_entries = self.entries
+ if acl_entries:
+ s += acl_entries.to_xml()
+ s += '</%s>' % ACCESS_CONTROL_LIST
+ return s
+
+
+class Entries:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+ # Entries is the class that represents the same-named XML
+ # element. entry_list is the list within this class that holds the data.
+ self.entry_list = []
+
+ def __repr__(self):
+ entries_repr = []
+ for e in self.entry_list:
+ entries_repr.append(e.__repr__())
+ return '<Entries: %s>' % ', '.join(entries_repr)
+
+ def startElement(self, name, attrs, connection):
+ if name.lower() == ENTRY.lower():
+ entry = Entry(self)
+ self.entry_list.append(entry)
+ return entry
+ else:
+ return None
+
+ def endElement(self, name, value, connection):
+ if name.lower() == ENTRY.lower():
+ pass
+ else:
+ setattr(self, name, value)
+
+ def to_xml(self):
+ s = '<%s>' % ENTRIES
+ for entry in self.entry_list:
+ s += entry.to_xml()
+ s += '</%s>' % ENTRIES
+ return s
+
+
+# Class that represents a single (Scope, Permission) entry in an ACL.
+class Entry:
+
+ def __init__(self, scope=None, type=None, id=None, name=None,
+ email_address=None, domain=None, permission=None):
+ if not scope:
+ scope = Scope(self, type, id, name, email_address, domain)
+ self.scope = scope
+ self.permission = permission
+
+ def __repr__(self):
+ return '<%s: %s>' % (self.scope.__repr__(), self.permission.__repr__())
+
+ def startElement(self, name, attrs, connection):
+ if name.lower() == SCOPE.lower():
+ # The following if statement used to look like this:
+ # if not TYPE in attrs:
+ # which caused problems because older versions of the
+ # AttributesImpl class in the xml.sax library neglected to include
+ # a __contains__() method (which Python calls to implement the
+ # 'in' operator). So when you use the in operator, like the if
+ # statement above, Python invokes the __getiter__() method with
+ # index 0, which raises an exception. More recent versions of
+ # xml.sax include the __contains__() method, rendering the in
+ # operator functional. The work-around here is to formulate the
+ # if statement as below, which is the legal way to query
+ # AttributesImpl for containment (and is also how the added
+ # __contains__() method works). At one time gsutil disallowed
+ # xmlplus-based parsers, until this more specific problem was
+ # determined.
+ if TYPE not in attrs:
+ raise InvalidAclError('Missing "%s" in "%s" part of ACL' %
+ (TYPE, SCOPE))
+ self.scope = Scope(self, attrs[TYPE])
+ return self.scope
+ elif name.lower() == PERMISSION.lower():
+ pass
+ else:
+ return None
+
+ def endElement(self, name, value, connection):
+ if name.lower() == SCOPE.lower():
+ pass
+ elif name.lower() == PERMISSION.lower():
+ value = value.strip()
+ if not value in SupportedPermissions:
+ raise InvalidAclError('Invalid Permission "%s"' % value)
+ self.permission = value
+ else:
+ setattr(self, name, value)
+
+ def to_xml(self):
+ s = '<%s>' % ENTRY
+ s += self.scope.to_xml()
+ s += '<%s>%s</%s>' % (PERMISSION, self.permission, PERMISSION)
+ s += '</%s>' % ENTRY
+ return s
+
+class Scope:
+
+ # Map from Scope type.lower() to lower-cased list of allowed sub-elems.
+ ALLOWED_SCOPE_TYPE_SUB_ELEMS = {
+ ALL_AUTHENTICATED_USERS.lower() : [],
+ ALL_USERS.lower() : [],
+ GROUP_BY_DOMAIN.lower() : [DOMAIN.lower()],
+ GROUP_BY_EMAIL.lower() : [
+ DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()],
+ GROUP_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()],
+ USER_BY_EMAIL.lower() : [
+ DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()],
+ USER_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()]
+ }
+
+ def __init__(self, parent, type=None, id=None, name=None,
+ email_address=None, domain=None):
+ self.parent = parent
+ self.type = type
+ self.name = name
+ self.id = id
+ self.domain = domain
+ self.email_address = email_address
+ if self.type.lower() not in self.ALLOWED_SCOPE_TYPE_SUB_ELEMS:
+ raise InvalidAclError('Invalid %s %s "%s" ' %
+ (SCOPE, TYPE, self.type))
+
+ def __repr__(self):
+ named_entity = None
+ if self.id:
+ named_entity = self.id
+ elif self.email_address:
+ named_entity = self.email_address
+ elif self.domain:
+ named_entity = self.domain
+ if named_entity:
+ return '<%s: %s>' % (self.type, named_entity)
+ else:
+ return '<%s>' % self.type
+
+ def startElement(self, name, attrs, connection):
+ if (not name.lower() in
+ self.ALLOWED_SCOPE_TYPE_SUB_ELEMS[self.type.lower()]):
+ raise InvalidAclError('Element "%s" not allowed in %s %s "%s" ' %
+ (name, SCOPE, TYPE, self.type))
+ return None
+
+ def endElement(self, name, value, connection):
+ value = value.strip()
+ if name.lower() == DOMAIN.lower():
+ self.domain = value
+ elif name.lower() == EMAIL_ADDRESS.lower():
+ self.email_address = value
+ elif name.lower() == ID.lower():
+ self.id = value
+ elif name.lower() == NAME.lower():
+ self.name = value
+ else:
+ setattr(self, name, value)
+
+ def to_xml(self):
+ s = '<%s type="%s">' % (SCOPE, self.type)
+ if (self.type.lower() == ALL_AUTHENTICATED_USERS.lower()
+ or self.type.lower() == ALL_USERS.lower()):
+ pass
+ elif self.type.lower() == GROUP_BY_DOMAIN.lower():
+ s += '<%s>%s</%s>' % (DOMAIN, self.domain, DOMAIN)
+ elif (self.type.lower() == GROUP_BY_EMAIL.lower()
+ or self.type.lower() == USER_BY_EMAIL.lower()):
+ s += '<%s>%s</%s>' % (EMAIL_ADDRESS, self.email_address,
+ EMAIL_ADDRESS)
+ if self.name:
+ s += '<%s>%s</%s>' % (NAME, self.name, NAME)
+ elif (self.type.lower() == GROUP_BY_ID.lower()
+ or self.type.lower() == USER_BY_ID.lower()):
+ s += '<%s>%s</%s>' % (ID, self.id, ID)
+ if self.name:
+ s += '<%s>%s</%s>' % (NAME, self.name, NAME)
+ else:
+ raise InvalidAclError('Invalid scope type "%s" ', self.type)
+
+ s += '</%s>' % SCOPE
+ return s
« no previous file with comments | « third_party/boto/boto/gs/__init__.py ('k') | third_party/boto/boto/gs/bucket.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698