1# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ 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 22from boto.s3.user import User 23 24 25CannedACLStrings = ['private', 'public-read', 26 'public-read-write', 'authenticated-read', 27 'bucket-owner-read', 'bucket-owner-full-control', 28 'log-delivery-write'] 29 30 31class Policy(object): 32 33 def __init__(self, parent=None): 34 self.parent = parent 35 self.namespace = None 36 self.acl = None 37 38 def __repr__(self): 39 grants = [] 40 for g in self.acl.grants: 41 if g.id == self.owner.id: 42 grants.append("%s (owner) = %s" % (g.display_name, g.permission)) 43 else: 44 if g.type == 'CanonicalUser': 45 u = g.display_name 46 elif g.type == 'Group': 47 u = g.uri 48 else: 49 u = g.email_address 50 grants.append("%s = %s" % (u, g.permission)) 51 return "<Policy: %s>" % ", ".join(grants) 52 53 def startElement(self, name, attrs, connection): 54 if name == 'AccessControlPolicy': 55 self.namespace = attrs.get('xmlns', None) 56 return None 57 if name == 'Owner': 58 self.owner = User(self) 59 return self.owner 60 elif name == 'AccessControlList': 61 self.acl = ACL(self) 62 return self.acl 63 else: 64 return None 65 66 def endElement(self, name, value, connection): 67 if name == 'Owner': 68 pass 69 elif name == 'AccessControlList': 70 pass 71 else: 72 setattr(self, name, value) 73 74 def to_xml(self): 75 if self.namespace is not None: 76 s = '<AccessControlPolicy xmlns="{0}">'.format(self.namespace) 77 else: 78 s = '<AccessControlPolicy>' 79 s += self.owner.to_xml() 80 s += self.acl.to_xml() 81 s += '</AccessControlPolicy>' 82 return s 83 84 85class ACL(object): 86 87 def __init__(self, policy=None): 88 self.policy = policy 89 self.grants = [] 90 91 def add_grant(self, grant): 92 self.grants.append(grant) 93 94 def add_email_grant(self, permission, email_address): 95 grant = Grant(permission=permission, type='AmazonCustomerByEmail', 96 email_address=email_address) 97 self.grants.append(grant) 98 99 def add_user_grant(self, permission, user_id, display_name=None): 100 grant = Grant(permission=permission, type='CanonicalUser', id=user_id, display_name=display_name) 101 self.grants.append(grant) 102 103 def startElement(self, name, attrs, connection): 104 if name == 'Grant': 105 self.grants.append(Grant(self)) 106 return self.grants[-1] 107 else: 108 return None 109 110 def endElement(self, name, value, connection): 111 if name == 'Grant': 112 pass 113 else: 114 setattr(self, name, value) 115 116 def to_xml(self): 117 s = '<AccessControlList>' 118 for grant in self.grants: 119 s += grant.to_xml() 120 s += '</AccessControlList>' 121 return s 122 123 124class Grant(object): 125 126 NameSpace = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' 127 128 def __init__(self, permission=None, type=None, id=None, 129 display_name=None, uri=None, email_address=None): 130 self.permission = permission 131 self.id = id 132 self.display_name = display_name 133 self.uri = uri 134 self.email_address = email_address 135 self.type = type 136 137 def startElement(self, name, attrs, connection): 138 if name == 'Grantee': 139 self.type = attrs['xsi:type'] 140 return None 141 142 def endElement(self, name, value, connection): 143 if name == 'ID': 144 self.id = value 145 elif name == 'DisplayName': 146 self.display_name = value 147 elif name == 'URI': 148 self.uri = value 149 elif name == 'EmailAddress': 150 self.email_address = value 151 elif name == 'Grantee': 152 pass 153 elif name == 'Permission': 154 self.permission = value 155 else: 156 setattr(self, name, value) 157 158 def to_xml(self): 159 s = '<Grant>' 160 s += '<Grantee %s xsi:type="%s">' % (self.NameSpace, self.type) 161 if self.type == 'CanonicalUser': 162 s += '<ID>%s</ID>' % self.id 163 s += '<DisplayName>%s</DisplayName>' % self.display_name 164 elif self.type == 'Group': 165 s += '<URI>%s</URI>' % self.uri 166 else: 167 s += '<EmailAddress>%s</EmailAddress>' % self.email_address 168 s += '</Grantee>' 169 s += '<Permission>%s</Permission>' % self.permission 170 s += '</Grant>' 171 return s 172