make deployment.py go away
[plstackapi.git] / planetstack / core / acl.py
1 from fnmatch import fnmatch
2
3 class AccessControlList:
4     def __init__(self, aclText=None):
5         self.rules = []
6         if aclText:
7             self.import_text(aclText)
8
9     def import_text(self, aclText):
10         # allow either newline or ';' to separate rules
11         aclText = aclText.replace("\n", ";")
12         for line in aclText.split(";"):
13             line = line.strip()
14             if line.startswith("#"):
15                 continue
16
17             if line=="":
18                 continue
19
20             parts = line.split()
21
22             if len(parts)==2 and (parts[1]=="all"):
23                 # "allow all" has no pattern
24                 parts = (parts[0], parts[1], "")
25
26             if len(parts)!=3:
27                 raise ACLValidationError(line)
28
29             (action, object, pattern) = parts
30
31             if action not in ["allow", "deny"]:
32                 raise ACLValidationError(line)
33
34             if object not in ["site", "user", "all"]:
35                 raise ACLValidationError(line)
36
37             self.rules.append( (action, object, pattern) )
38
39     def __str__(self):
40         lines = []
41         for rule in self.rules:
42             lines.append( " ".join(rule) )
43         return ";\n".join(lines)
44
45     def test(self, user):
46         for rule in self.rules:
47             if self.match_rule(rule, user):
48                 return rule[0]
49         return "deny"
50
51     def match_rule(self, rule, user):
52         (action, object, pattern) = rule
53
54         if (object == "site"):
55             if fnmatch(user.site.name, pattern):
56                 return True
57         elif (object == "user"):
58             if fnmatch(user.email, pattern):
59                 return True
60         elif (object == "all"):
61             return True
62
63         return False
64
65
66 if __name__ == '__main__':
67     class fakesite:
68         def __init__(self, siteName):
69             self.name = siteName
70
71     class fakeuser:
72         def __init__(self, email, siteName):
73             self.email = email
74             self.site = fakesite(siteName)
75
76     u_scott = fakeuser("scott@onlab.us", "ON.Lab")
77     u_bill = fakeuser("bill@onlab.us", "ON.Lab")
78     u_andy = fakeuser("acb@cs.princeton.edu", "Princeton")
79     u_john = fakeuser("jhh@cs.arizona.edu", "Arizona")
80     u_hacker = fakeuser("somehacker@foo.com", "Not A Real Site")
81
82     # check the "deny all" rule
83     acl = AccessControlList("deny all")
84     assert(acl.test(u_scott) == "deny")
85
86     # a blank ACL results in "deny all"
87     acl = AccessControlList("")
88     assert(acl.test(u_scott) == "deny")
89
90     # check the "allow all" rule
91     acl = AccessControlList("allow all")
92     assert(acl.test(u_scott) == "allow")
93
94     # allow only one site
95     acl = AccessControlList("allow site ON.Lab")
96     assert(acl.test(u_scott) == "allow")
97     assert(acl.test(u_andy) == "deny")
98
99     # some complicated ACL
100     acl = AccessControlList("""allow site Princeton
101                  allow user *@cs.arizona.edu
102                  deny site Arizona
103                  deny user scott@onlab.us
104                  allow site ON.Lab""")
105
106     assert(acl.test(u_scott) == "deny")
107     assert(acl.test(u_bill) == "allow")
108     assert(acl.test(u_andy) == "allow")
109     assert(acl.test(u_john) == "allow")
110     assert(acl.test(u_hacker) == "deny")
111
112     print acl
113