import repository from arizona
[raven.git] / lib / ravenlib / acl / baseacl.py
1 import fnmatch
2
3 ACL_CREATE = "acl_create"
4 ACL_DELETE = "acl_delete"
5 ACL_ADD_RIGHT = "acl_add"
6 ACL_REMOVE_RIGHT = "acl_remove"
7
8 class AclError(Exception):
9     def __init__(self, value):
10         self.value = value
11     def __str__(self):
12         return repr(self.value)
13
14 class AclNotImplementedError(AclError):
15     pass
16
17 class AclPermissionError(AclError):
18     def __init__(self, principal, right, objectId = None):
19         self.principal = principal
20         self.right = right
21         self.objectId = None
22     def __str__(self):
23         if self.objectId:
24             return "'%s' does not have permission '%s' on '%s'" % (self.principal, 
25                         self.right, self.objectId)
26         else:
27             return "'%s' does not have permission '%s'" % (self.principal, self.right)
28
29 class AclExistsError(AclError):
30     def __init__(self, objectId):
31         self.objectId = objectId
32     def __str__(self):
33         return "acl already exists for " + self.objectId
34
35 class AclDoesNotExistError(AclError):
36     def __init__(self, objectId):
37         self.objectId = objectId
38     def __str__(self):
39         return "acl does not exist for " + self.objectId
40
41 class BaseAcl:
42     def __init__(self, objectId):
43         self.objectId = objectId
44         self.rights = {}
45
46     def get_rights(self, principal):
47         rights = []
48         # check every principal in the rights dictionary and wildcard match
49         # them.
50         for key in self.rights:
51             if fnmatch.fnmatch(principal, key):
52                 rights.extend(self.rights[key])
53         # uniquify it
54         rights = set(rights)
55         return rights
56
57     def test_right(self, principal, right):
58         rights = self.get_rights(principal)
59         if not right in rights:
60             raise AclPermissionError(principal, right, self.objectId)
61
62     def add_right(self, principal, right):
63         rights = self.rights.get(principal, [])
64         if not right in rights:
65             rights.append(right)
66             self.rights[principal] = rights
67             self.modified(principal)
68
69     def delete_right(self, principal, right):
70         rights = self.rights.get(principal, [])
71         if right in rights:
72             rights.remove(right)
73             self.rights[principal] = rights
74             self.modified(principal)
75
76     def modified(self, principal):
77         pass
78
79 class BaseAclManager:
80     def __init__(self):
81         pass
82
83     def acl_exists(self, objectId):
84         """
85             Returns true if the acl for 'objectId' exsits, false otherwise
86         """
87         raise AclNotImplementedError("acl_exists")
88
89     def get_acl(self, objectId):
90         """
91             Get the acl object for 'objectId'.
92             Throw AclDoesNotExistError if acl does not exist.
93         """
94         raise AclNotImplementedError("get_acl")
95
96     def create_acl(self, objectId):
97         """
98             Create the acl object for 'objectId'. acl is created in persistent
99                storage.
100             Throw AclExistsError if the acl already exists.
101         """
102         raise AclNotImplementedError("create_acl")
103
104     def delete_acl(self, objectId):
105         """
106             Delete the acl object for 'objectId'.
107             Throw AclDoesNotExist error if the acl does not exist.
108         """
109         raise AclNotImplementedError("delete_acl")
110
111     def test_acl(self, objectId, principal, right):
112         """
113             Test the acl 'objectId' to see if 'principal' can perform 'right'.
114             Throw AclPermissionError if the acl exists, but the permission is
115                not set.
116             Throw AclDoesNotExist error if the acl does not exist.
117         """
118         acl = self.get_acl(objectId)
119         acl.test_right(principal, right)
120
121     def create_acl_if_not_exist(self, objectId, rightsDict={}):
122         """
123             If the acl 'objectId' does not exist then create it and initialize
124             the rights using rightsDict.
125
126             RightsDict is a dictionary that maps principals to to lists for
127             rights. For example,
128
129                 rightsDict = {"scott": ["read", "write"]}
130         """
131         try:
132             acl = self.create_acl(objectId)
133         except AclExistsError, e:
134             # if it already exists, then we have no work to do, just get the
135             # acl and return it.
136
137             # XXX small potential for a race here -- ACL could have been
138             # deleted between the time we failed to create it and the time
139             # we get_acl() it.
140
141             return self.get_acl(objectId)
142
143         # the acl must have just been created. let's fill it in.
144
145         if rightsDict:
146             for principal in rightsDict.keys():
147                 rights = rightsDict[principal]
148                 for right in rights:
149                     acl.add_right(principal, right)
150
151         return acl
152