Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/gs/acl.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:18:57 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d30785e31577 |
|---|---|
| 1 # Copyright 2010 Google Inc. | |
| 2 # | |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 4 # copy of this software and associated documentation files (the | |
| 5 # "Software"), to deal in the Software without restriction, including | |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 9 # lowing conditions: | |
| 10 # | |
| 11 # The above copyright notice and this permission notice shall be included | |
| 12 # in all copies or substantial portions of the Software. | |
| 13 # | |
| 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 20 # IN THE SOFTWARE. | |
| 21 | |
| 22 from boto.gs.user import User | |
| 23 from boto.exception import InvalidAclError | |
| 24 | |
| 25 ACCESS_CONTROL_LIST = 'AccessControlList' | |
| 26 ALL_AUTHENTICATED_USERS = 'AllAuthenticatedUsers' | |
| 27 ALL_USERS = 'AllUsers' | |
| 28 DISPLAY_NAME = 'DisplayName' | |
| 29 DOMAIN = 'Domain' | |
| 30 EMAIL_ADDRESS = 'EmailAddress' | |
| 31 ENTRY = 'Entry' | |
| 32 ENTRIES = 'Entries' | |
| 33 GROUP_BY_DOMAIN = 'GroupByDomain' | |
| 34 GROUP_BY_EMAIL = 'GroupByEmail' | |
| 35 GROUP_BY_ID = 'GroupById' | |
| 36 ID = 'ID' | |
| 37 NAME = 'Name' | |
| 38 OWNER = 'Owner' | |
| 39 PERMISSION = 'Permission' | |
| 40 SCOPE = 'Scope' | |
| 41 TYPE = 'type' | |
| 42 USER_BY_EMAIL = 'UserByEmail' | |
| 43 USER_BY_ID = 'UserById' | |
| 44 | |
| 45 | |
| 46 CannedACLStrings = ['private', 'public-read', 'project-private', | |
| 47 'public-read-write', 'authenticated-read', | |
| 48 'bucket-owner-read', 'bucket-owner-full-control'] | |
| 49 """A list of Google Cloud Storage predefined (canned) ACL strings.""" | |
| 50 | |
| 51 SupportedPermissions = ['READ', 'WRITE', 'FULL_CONTROL'] | |
| 52 """A list of supported ACL permissions.""" | |
| 53 | |
| 54 | |
| 55 class ACL(object): | |
| 56 | |
| 57 def __init__(self, parent=None): | |
| 58 self.parent = parent | |
| 59 self.entries = Entries(self) | |
| 60 | |
| 61 @property | |
| 62 def acl(self): | |
| 63 return self | |
| 64 | |
| 65 def __repr__(self): | |
| 66 # Owner is optional in GS ACLs. | |
| 67 if hasattr(self, 'owner'): | |
| 68 entries_repr = ['Owner:%s' % self.owner.__repr__()] | |
| 69 else: | |
| 70 entries_repr = [''] | |
| 71 acl_entries = self.entries | |
| 72 if acl_entries: | |
| 73 for e in acl_entries.entry_list: | |
| 74 entries_repr.append(e.__repr__()) | |
| 75 return '<%s>' % ', '.join(entries_repr) | |
| 76 | |
| 77 # Method with same signature as boto.s3.acl.ACL.add_email_grant(), to allow | |
| 78 # polymorphic treatment at application layer. | |
| 79 def add_email_grant(self, permission, email_address): | |
| 80 entry = Entry(type=USER_BY_EMAIL, email_address=email_address, | |
| 81 permission=permission) | |
| 82 self.entries.entry_list.append(entry) | |
| 83 | |
| 84 # Method with same signature as boto.s3.acl.ACL.add_user_grant(), to allow | |
| 85 # polymorphic treatment at application layer. | |
| 86 def add_user_grant(self, permission, user_id): | |
| 87 entry = Entry(permission=permission, type=USER_BY_ID, id=user_id) | |
| 88 self.entries.entry_list.append(entry) | |
| 89 | |
| 90 def add_group_email_grant(self, permission, email_address): | |
| 91 entry = Entry(type=GROUP_BY_EMAIL, email_address=email_address, | |
| 92 permission=permission) | |
| 93 self.entries.entry_list.append(entry) | |
| 94 | |
| 95 def add_group_grant(self, permission, group_id): | |
| 96 entry = Entry(type=GROUP_BY_ID, id=group_id, permission=permission) | |
| 97 self.entries.entry_list.append(entry) | |
| 98 | |
| 99 def startElement(self, name, attrs, connection): | |
| 100 if name.lower() == OWNER.lower(): | |
| 101 self.owner = User(self) | |
| 102 return self.owner | |
| 103 elif name.lower() == ENTRIES.lower(): | |
| 104 self.entries = Entries(self) | |
| 105 return self.entries | |
| 106 else: | |
| 107 return None | |
| 108 | |
| 109 def endElement(self, name, value, connection): | |
| 110 if name.lower() == OWNER.lower(): | |
| 111 pass | |
| 112 elif name.lower() == ENTRIES.lower(): | |
| 113 pass | |
| 114 else: | |
| 115 setattr(self, name, value) | |
| 116 | |
| 117 def to_xml(self): | |
| 118 s = '<%s>' % ACCESS_CONTROL_LIST | |
| 119 # Owner is optional in GS ACLs. | |
| 120 if hasattr(self, 'owner'): | |
| 121 s += self.owner.to_xml() | |
| 122 acl_entries = self.entries | |
| 123 if acl_entries: | |
| 124 s += acl_entries.to_xml() | |
| 125 s += '</%s>' % ACCESS_CONTROL_LIST | |
| 126 return s | |
| 127 | |
| 128 | |
| 129 class Entries(object): | |
| 130 | |
| 131 def __init__(self, parent=None): | |
| 132 self.parent = parent | |
| 133 # Entries is the class that represents the same-named XML | |
| 134 # element. entry_list is the list within this class that holds the data. | |
| 135 self.entry_list = [] | |
| 136 | |
| 137 def __repr__(self): | |
| 138 entries_repr = [] | |
| 139 for e in self.entry_list: | |
| 140 entries_repr.append(e.__repr__()) | |
| 141 return '<Entries: %s>' % ', '.join(entries_repr) | |
| 142 | |
| 143 def startElement(self, name, attrs, connection): | |
| 144 if name.lower() == ENTRY.lower(): | |
| 145 entry = Entry(self) | |
| 146 self.entry_list.append(entry) | |
| 147 return entry | |
| 148 else: | |
| 149 return None | |
| 150 | |
| 151 def endElement(self, name, value, connection): | |
| 152 if name.lower() == ENTRY.lower(): | |
| 153 pass | |
| 154 else: | |
| 155 setattr(self, name, value) | |
| 156 | |
| 157 def to_xml(self): | |
| 158 if not self.entry_list: | |
| 159 return '' | |
| 160 s = '<%s>' % ENTRIES | |
| 161 for entry in self.entry_list: | |
| 162 s += entry.to_xml() | |
| 163 s += '</%s>' % ENTRIES | |
| 164 return s | |
| 165 | |
| 166 | |
| 167 # Class that represents a single (Scope, Permission) entry in an ACL. | |
| 168 class Entry(object): | |
| 169 | |
| 170 def __init__(self, scope=None, type=None, id=None, name=None, | |
| 171 email_address=None, domain=None, permission=None): | |
| 172 if not scope: | |
| 173 scope = Scope(self, type, id, name, email_address, domain) | |
| 174 self.scope = scope | |
| 175 self.permission = permission | |
| 176 | |
| 177 def __repr__(self): | |
| 178 return '<%s: %s>' % (self.scope.__repr__(), self.permission.__repr__()) | |
| 179 | |
| 180 def startElement(self, name, attrs, connection): | |
| 181 if name.lower() == SCOPE.lower(): | |
| 182 # The following if statement used to look like this: | |
| 183 # if not TYPE in attrs: | |
| 184 # which caused problems because older versions of the | |
| 185 # AttributesImpl class in the xml.sax library neglected to include | |
| 186 # a __contains__() method (which Python calls to implement the | |
| 187 # 'in' operator). So when you use the in operator, like the if | |
| 188 # statement above, Python invokes the __getiter__() method with | |
| 189 # index 0, which raises an exception. More recent versions of | |
| 190 # xml.sax include the __contains__() method, rendering the in | |
| 191 # operator functional. The work-around here is to formulate the | |
| 192 # if statement as below, which is the legal way to query | |
| 193 # AttributesImpl for containment (and is also how the added | |
| 194 # __contains__() method works). At one time gsutil disallowed | |
| 195 # xmlplus-based parsers, until this more specific problem was | |
| 196 # determined. | |
| 197 if TYPE not in attrs: | |
| 198 raise InvalidAclError('Missing "%s" in "%s" part of ACL' % | |
| 199 (TYPE, SCOPE)) | |
| 200 self.scope = Scope(self, attrs[TYPE]) | |
| 201 return self.scope | |
| 202 elif name.lower() == PERMISSION.lower(): | |
| 203 pass | |
| 204 else: | |
| 205 return None | |
| 206 | |
| 207 def endElement(self, name, value, connection): | |
| 208 if name.lower() == SCOPE.lower(): | |
| 209 pass | |
| 210 elif name.lower() == PERMISSION.lower(): | |
| 211 value = value.strip() | |
| 212 if not value in SupportedPermissions: | |
| 213 raise InvalidAclError('Invalid Permission "%s"' % value) | |
| 214 self.permission = value | |
| 215 else: | |
| 216 setattr(self, name, value) | |
| 217 | |
| 218 def to_xml(self): | |
| 219 s = '<%s>' % ENTRY | |
| 220 s += self.scope.to_xml() | |
| 221 s += '<%s>%s</%s>' % (PERMISSION, self.permission, PERMISSION) | |
| 222 s += '</%s>' % ENTRY | |
| 223 return s | |
| 224 | |
| 225 | |
| 226 class Scope(object): | |
| 227 | |
| 228 # Map from Scope type.lower() to lower-cased list of allowed sub-elems. | |
| 229 ALLOWED_SCOPE_TYPE_SUB_ELEMS = { | |
| 230 ALL_AUTHENTICATED_USERS.lower() : [], | |
| 231 ALL_USERS.lower() : [], | |
| 232 GROUP_BY_DOMAIN.lower() : [DOMAIN.lower()], | |
| 233 GROUP_BY_EMAIL.lower() : [ | |
| 234 DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()], | |
| 235 GROUP_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()], | |
| 236 USER_BY_EMAIL.lower() : [ | |
| 237 DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()], | |
| 238 USER_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()] | |
| 239 } | |
| 240 | |
| 241 def __init__(self, parent, type=None, id=None, name=None, | |
| 242 email_address=None, domain=None): | |
| 243 self.parent = parent | |
| 244 self.type = type | |
| 245 self.name = name | |
| 246 self.id = id | |
| 247 self.domain = domain | |
| 248 self.email_address = email_address | |
| 249 if self.type.lower() not in self.ALLOWED_SCOPE_TYPE_SUB_ELEMS: | |
| 250 raise InvalidAclError('Invalid %s %s "%s" ' % | |
| 251 (SCOPE, TYPE, self.type)) | |
| 252 | |
| 253 def __repr__(self): | |
| 254 named_entity = None | |
| 255 if self.id: | |
| 256 named_entity = self.id | |
| 257 elif self.email_address: | |
| 258 named_entity = self.email_address | |
| 259 elif self.domain: | |
| 260 named_entity = self.domain | |
| 261 if named_entity: | |
| 262 return '<%s: %s>' % (self.type, named_entity) | |
| 263 else: | |
| 264 return '<%s>' % self.type | |
| 265 | |
| 266 def startElement(self, name, attrs, connection): | |
| 267 if (not name.lower() in | |
| 268 self.ALLOWED_SCOPE_TYPE_SUB_ELEMS[self.type.lower()]): | |
| 269 raise InvalidAclError('Element "%s" not allowed in %s %s "%s" ' % | |
| 270 (name, SCOPE, TYPE, self.type)) | |
| 271 return None | |
| 272 | |
| 273 def endElement(self, name, value, connection): | |
| 274 value = value.strip() | |
| 275 if name.lower() == DOMAIN.lower(): | |
| 276 self.domain = value | |
| 277 elif name.lower() == EMAIL_ADDRESS.lower(): | |
| 278 self.email_address = value | |
| 279 elif name.lower() == ID.lower(): | |
| 280 self.id = value | |
| 281 elif name.lower() == NAME.lower(): | |
| 282 self.name = value | |
| 283 else: | |
| 284 setattr(self, name, value) | |
| 285 | |
| 286 def to_xml(self): | |
| 287 s = '<%s type="%s">' % (SCOPE, self.type) | |
| 288 if (self.type.lower() == ALL_AUTHENTICATED_USERS.lower() | |
| 289 or self.type.lower() == ALL_USERS.lower()): | |
| 290 pass | |
| 291 elif self.type.lower() == GROUP_BY_DOMAIN.lower(): | |
| 292 s += '<%s>%s</%s>' % (DOMAIN, self.domain, DOMAIN) | |
| 293 elif (self.type.lower() == GROUP_BY_EMAIL.lower() | |
| 294 or self.type.lower() == USER_BY_EMAIL.lower()): | |
| 295 s += '<%s>%s</%s>' % (EMAIL_ADDRESS, self.email_address, | |
| 296 EMAIL_ADDRESS) | |
| 297 if self.name: | |
| 298 s += '<%s>%s</%s>' % (NAME, self.name, NAME) | |
| 299 elif (self.type.lower() == GROUP_BY_ID.lower() | |
| 300 or self.type.lower() == USER_BY_ID.lower()): | |
| 301 s += '<%s>%s</%s>' % (ID, self.id, ID) | |
| 302 if self.name: | |
| 303 s += '<%s>%s</%s>' % (NAME, self.name, NAME) | |
| 304 else: | |
| 305 raise InvalidAclError('Invalid scope type "%s" ', self.type) | |
| 306 | |
| 307 s += '</%s>' % SCOPE | |
| 308 return s |
