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

Side by Side Diff: third_party/gsutil/boto/gs/acl.py

Issue 12042069: Scripts to download files from google storage based on sha1 sums (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Removed gsutil/tests and gsutil/docs Created 7 years, 10 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 unified diff | Download patch
OLDNEW
(Empty)
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
50 SupportedPermissions = ['READ', 'WRITE', 'FULL_CONTROL']
51
52 class ACL:
53
54 def __init__(self, parent=None):
55 self.parent = parent
56 self.entries = []
57
58 @property
59 def acl(self):
60 return self
61
62 def __repr__(self):
63 # Owner is optional in GS ACLs.
64 if hasattr(self, 'owner'):
65 entries_repr = ['Owner:%s' % self.owner.__repr__()]
66 else:
67 entries_repr = ['']
68 acl_entries = self.entries
69 if acl_entries:
70 for e in acl_entries.entry_list:
71 entries_repr.append(e.__repr__())
72 return '<%s>' % ', '.join(entries_repr)
73
74 # Method with same signature as boto.s3.acl.ACL.add_email_grant(), to allow
75 # polymorphic treatment at application layer.
76 def add_email_grant(self, permission, email_address):
77 entry = Entry(type=USER_BY_EMAIL, email_address=email_address,
78 permission=permission)
79 self.entries.entry_list.append(entry)
80
81 # Method with same signature as boto.s3.acl.ACL.add_user_grant(), to allow
82 # polymorphic treatment at application layer.
83 def add_user_grant(self, permission, user_id):
84 entry = Entry(permission=permission, type=USER_BY_ID, id=user_id)
85 self.entries.entry_list.append(entry)
86
87 def add_group_email_grant(self, permission, email_address):
88 entry = Entry(type=GROUP_BY_EMAIL, email_address=email_address,
89 permission=permission)
90 self.entries.entry_list.append(entry)
91
92 def add_group_grant(self, permission, group_id):
93 entry = Entry(type=GROUP_BY_ID, id=group_id, permission=permission)
94 self.entries.entry_list.append(entry)
95
96 def startElement(self, name, attrs, connection):
97 if name.lower() == OWNER.lower():
98 self.owner = User(self)
99 return self.owner
100 elif name.lower() == ENTRIES.lower():
101 self.entries = Entries(self)
102 return self.entries
103 else:
104 return None
105
106 def endElement(self, name, value, connection):
107 if name.lower() == OWNER.lower():
108 pass
109 elif name.lower() == ENTRIES.lower():
110 pass
111 else:
112 setattr(self, name, value)
113
114 def to_xml(self):
115 s = '<%s>' % ACCESS_CONTROL_LIST
116 # Owner is optional in GS ACLs.
117 if hasattr(self, 'owner'):
118 s += self.owner.to_xml()
119 acl_entries = self.entries
120 if acl_entries:
121 s += acl_entries.to_xml()
122 s += '</%s>' % ACCESS_CONTROL_LIST
123 return s
124
125
126 class Entries:
127
128 def __init__(self, parent=None):
129 self.parent = parent
130 # Entries is the class that represents the same-named XML
131 # element. entry_list is the list within this class that holds the data.
132 self.entry_list = []
133
134 def __repr__(self):
135 entries_repr = []
136 for e in self.entry_list:
137 entries_repr.append(e.__repr__())
138 return '<Entries: %s>' % ', '.join(entries_repr)
139
140 def startElement(self, name, attrs, connection):
141 if name.lower() == ENTRY.lower():
142 entry = Entry(self)
143 self.entry_list.append(entry)
144 return entry
145 else:
146 return None
147
148 def endElement(self, name, value, connection):
149 if name.lower() == ENTRY.lower():
150 pass
151 else:
152 setattr(self, name, value)
153
154 def to_xml(self):
155 s = '<%s>' % ENTRIES
156 for entry in self.entry_list:
157 s += entry.to_xml()
158 s += '</%s>' % ENTRIES
159 return s
160
161
162 # Class that represents a single (Scope, Permission) entry in an ACL.
163 class Entry:
164
165 def __init__(self, scope=None, type=None, id=None, name=None,
166 email_address=None, domain=None, permission=None):
167 if not scope:
168 scope = Scope(self, type, id, name, email_address, domain)
169 self.scope = scope
170 self.permission = permission
171
172 def __repr__(self):
173 return '<%s: %s>' % (self.scope.__repr__(), self.permission.__repr__())
174
175 def startElement(self, name, attrs, connection):
176 if name.lower() == SCOPE.lower():
177 # The following if statement used to look like this:
178 # if not TYPE in attrs:
179 # which caused problems because older versions of the
180 # AttributesImpl class in the xml.sax library neglected to include
181 # a __contains__() method (which Python calls to implement the
182 # 'in' operator). So when you use the in operator, like the if
183 # statement above, Python invokes the __getiter__() method with
184 # index 0, which raises an exception. More recent versions of
185 # xml.sax include the __contains__() method, rendering the in
186 # operator functional. The work-around here is to formulate the
187 # if statement as below, which is the legal way to query
188 # AttributesImpl for containment (and is also how the added
189 # __contains__() method works). At one time gsutil disallowed
190 # xmlplus-based parsers, until this more specific problem was
191 # determined.
192 if TYPE not in attrs:
193 raise InvalidAclError('Missing "%s" in "%s" part of ACL' %
194 (TYPE, SCOPE))
195 self.scope = Scope(self, attrs[TYPE])
196 return self.scope
197 elif name.lower() == PERMISSION.lower():
198 pass
199 else:
200 return None
201
202 def endElement(self, name, value, connection):
203 if name.lower() == SCOPE.lower():
204 pass
205 elif name.lower() == PERMISSION.lower():
206 value = value.strip()
207 if not value in SupportedPermissions:
208 raise InvalidAclError('Invalid Permission "%s"' % value)
209 self.permission = value
210 else:
211 setattr(self, name, value)
212
213 def to_xml(self):
214 s = '<%s>' % ENTRY
215 s += self.scope.to_xml()
216 s += '<%s>%s</%s>' % (PERMISSION, self.permission, PERMISSION)
217 s += '</%s>' % ENTRY
218 return s
219
220 class Scope:
221
222 # Map from Scope type.lower() to lower-cased list of allowed sub-elems.
223 ALLOWED_SCOPE_TYPE_SUB_ELEMS = {
224 ALL_AUTHENTICATED_USERS.lower() : [],
225 ALL_USERS.lower() : [],
226 GROUP_BY_DOMAIN.lower() : [DOMAIN.lower()],
227 GROUP_BY_EMAIL.lower() : [
228 DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()],
229 GROUP_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()],
230 USER_BY_EMAIL.lower() : [
231 DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()],
232 USER_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()]
233 }
234
235 def __init__(self, parent, type=None, id=None, name=None,
236 email_address=None, domain=None):
237 self.parent = parent
238 self.type = type
239 self.name = name
240 self.id = id
241 self.domain = domain
242 self.email_address = email_address
243 if self.type.lower() not in self.ALLOWED_SCOPE_TYPE_SUB_ELEMS:
244 raise InvalidAclError('Invalid %s %s "%s" ' %
245 (SCOPE, TYPE, self.type))
246
247 def __repr__(self):
248 named_entity = None
249 if self.id:
250 named_entity = self.id
251 elif self.email_address:
252 named_entity = self.email_address
253 elif self.domain:
254 named_entity = self.domain
255 if named_entity:
256 return '<%s: %s>' % (self.type, named_entity)
257 else:
258 return '<%s>' % self.type
259
260 def startElement(self, name, attrs, connection):
261 if (not name.lower() in
262 self.ALLOWED_SCOPE_TYPE_SUB_ELEMS[self.type.lower()]):
263 raise InvalidAclError('Element "%s" not allowed in %s %s "%s" ' %
264 (name, SCOPE, TYPE, self.type))
265 return None
266
267 def endElement(self, name, value, connection):
268 value = value.strip()
269 if name.lower() == DOMAIN.lower():
270 self.domain = value
271 elif name.lower() == EMAIL_ADDRESS.lower():
272 self.email_address = value
273 elif name.lower() == ID.lower():
274 self.id = value
275 elif name.lower() == NAME.lower():
276 self.name = value
277 else:
278 setattr(self, name, value)
279
280 def to_xml(self):
281 s = '<%s type="%s">' % (SCOPE, self.type)
282 if (self.type.lower() == ALL_AUTHENTICATED_USERS.lower()
283 or self.type.lower() == ALL_USERS.lower()):
284 pass
285 elif self.type.lower() == GROUP_BY_DOMAIN.lower():
286 s += '<%s>%s</%s>' % (DOMAIN, self.domain, DOMAIN)
287 elif (self.type.lower() == GROUP_BY_EMAIL.lower()
288 or self.type.lower() == USER_BY_EMAIL.lower()):
289 s += '<%s>%s</%s>' % (EMAIL_ADDRESS, self.email_address,
290 EMAIL_ADDRESS)
291 if self.name:
292 s += '<%s>%s</%s>' % (NAME, self.name, NAME)
293 elif (self.type.lower() == GROUP_BY_ID.lower()
294 or self.type.lower() == USER_BY_ID.lower()):
295 s += '<%s>%s</%s>' % (ID, self.id, ID)
296 if self.name:
297 s += '<%s>%s</%s>' % (NAME, self.name, NAME)
298 else:
299 raise InvalidAclError('Invalid scope type "%s" ', self.type)
300
301 s += '</%s>' % SCOPE
302 return s
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698