S3/ACL.py
7f50f846
 ## Amazon S3 - Access Control List representation
 ## Author: Michal Ludvig <michal@logix.cz>
 ##         http://www.logix.cz/michal
 ## License: GPL Version 2
 
 from Utils import *
 
 try:
 	import xml.etree.ElementTree as ET
 except ImportError:
 	import elementtree.ElementTree as ET
 
34399925
 class Grantee(object):
 	ALL_USERS_URI = "http://acs.amazonaws.com/groups/global/AllUsers"
 
 	xsi_type = None
 	tag = None
 	name = None
 	display_name = None
 	permission = None
 
 	def __str__(self):
 		return '%(name)s : %(permission)s' % { "name" : self.name, "permission" : self.permission }
 
 	def isAllUsers(self):
 		return self.tag == "URI" and self.name == Grantee.ALL_USERS_URI
 	
 	def isAnonRead(self):
 		return self.isAllUsers and self.permission == "READ"
 
 class GranteeAnonRead(Grantee):
 	xsi_type = "Group"
 	tag = "URI"
 	name = Grantee.ALL_USERS_URI
 	permission = "READ"
 
7f50f846
 class ACL(object):
 	EMPTY_ACL = """
 	<AccessControlPolicy>
 		<AccessControlList>
 		</AccessControlList>
 	</AccessControlPolicy>
 	"""
34399925
 
 	grants = []
 
7f50f846
 	def __init__(self, xml = None):
 		if not xml:
 			xml = ACL.EMPTY_ACL
 		self.tree = getTreeFromXml(xml)
34399925
 		self.grants = self.parseGrants()
7f50f846
 	
34399925
 	def parseGrants(self):
7f50f846
 		for grant in self.tree.findall(".//Grant"):
34399925
 			grantee = Grantee()
 			g = grant.find(".//Grantee")
 			grantee.xsi_type = g.attrib['{http://www.w3.org/2001/XMLSchema-instance}type']
 			grantee.permission = grant.find('Permission').text
 			for el in g:
 				if el.tag == "DisplayName":
 					grantee.display_name = el.text
 				else:
 					grantee.tag = el.tag
 					grantee.name = el.text
 			self.grants.append(grantee)
 		return self.grants
 
 	def getGrantList(self):
 		acl = {}
 		for grantee in self.grants:
 			if grantee.display_name:
 				user = grantee.display_name
 			elif grantee.isAllUsers():
 				user = "*anon*"
7f50f846
 			else:
34399925
 				user = grantee.name
 			acl[user] = grantee.permission
7f50f846
 		return acl
 
34399925
 	def isAnonRead(self):
 		for grantee in self.grants:
 			if grantee.isAnonRead():
 				return True
 		return False
 	
 	def grantAnonRead(self):
 		if not self.isAnonRead():
 			self.grants.append(GranteeAnonRead())
 	
 	def revokeAnonRead(self):
 		self.grants = [g for g in self.grants if not g.isAnonRead()]
 
 	def __str__(self):
 		return ET.tostring(self.tree)
 
7f50f846
 if __name__ == "__main__":
 	xml = """<?xml version="1.0" encoding="UTF-8"?>
 <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
 <Owner>
 	<ID>12345678901234567890</ID>
 	<DisplayName>owner-nickname</DisplayName>
 </Owner>
 <AccessControlList>
 	<Grant>
 		<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
 			<ID>12345678901234567890</ID>
 			<DisplayName>owner-nickname</DisplayName>
 		</Grantee>
 		<Permission>FULL_CONTROL</Permission>
 	</Grant>
 	<Grant>
 		<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
 			<URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
 		</Grantee>
 		<Permission>READ</Permission>
 	</Grant>
 </AccessControlList>
 </AccessControlPolicy>
 	"""
 	acl = ACL(xml)
34399925
 	print "Grants:", acl.getGrantList()
 	acl.revokeAnonRead()
 	print "Grants:", acl.getGrantList()
 	acl.grantAnonRead()
 	print "Grants:", acl.getGrantList()
 	#print acl