Attachment 'hierachical-acl-666.diff'
Download 1 diff -Naur old/MoinMoin/multiconfig.py new/MoinMoin/multiconfig.py
2 --- old/MoinMoin/multiconfig.py 2005-06-12 13:43:48.613091432 +0200
3 +++ new/MoinMoin/multiconfig.py 2005-06-12 13:36:54.337070960 +0200
4 @@ -151,6 +151,7 @@
5 FIXME: update according to MoinMoin:UpdateConfiguration
6 """
7 acl_enabled = 0
8 + acl_hierarchic = 0
9 # All acl_right lines must use unicode!
10 acl_rights_default = u"Trusted:read,write,delete,revert Known:read,write,delete,revert All:read,write"
11 acl_rights_before = u""
12 @@ -324,6 +325,13 @@
13 # e.g u'%(page_front_page)s' % self
14 self.navi_bar = [elem % self for elem in self.navi_bar]
15
16 + # precompile acl strings
17 + if self.acl_enabled:
18 + from wikiacl import AccessControlList
19 + self.acl_default = AccessControlList(None, [self.acl_rights_default], cfg=self)
20 + self.acl_before = AccessControlList(None, [self.acl_rights_before], cfg=self)
21 + self.acl_after = AccessControlList(None, [self.acl_rights_after], cfg=self)
22 +
23 def _config_check(self):
24 """ Check namespace and warn about unknown names
25
26 diff -Naur old/MoinMoin/PageEditor.py new/MoinMoin/PageEditor.py
27 --- old/MoinMoin/PageEditor.py 2005-06-12 13:43:48.609092040 +0200
28 +++ new/MoinMoin/PageEditor.py 2005-06-12 13:37:11.216504896 +0200
29 @@ -916,7 +916,7 @@
30 # of wating for next request.
31 acl = self.getACL(self.request)
32 if (not self.request.user.may.admin(self.page_name) and
33 - parseACL(self.request, newtext) != acl and
34 + parseACL(self.request, newtext).acl != acl.acl and
35 action != "SAVE/REVERT"):
36 msg = _("You can't change ACLs on this page since you have no admin rights on it!")
37 raise self.NoAdmin, msg
38 diff -Naur old/MoinMoin/security.py new/MoinMoin/security.py
39 --- old/MoinMoin/security.py 2005-06-12 13:43:48.616090976 +0200
40 +++ new/MoinMoin/security.py 2005-06-12 13:37:18.395413536 +0200
41 @@ -22,8 +22,21 @@
42 class Permissions:
43 """ Basic interface for user permissions and system policy.
44
45 - Note that you still need to allow some of the related actions, this
46 - just controls their behaviour, not their activation.
47 + Note that you still need to allow some of the related actions, this
48 + just controls their behavior, not their activation.
49 +
50 + When sub classing this class, you must extend the class methods, not
51 + replace them, or you might break the acl in the wiki. Correct sub
52 + classing look like this:
53 +
54 + def read(self, pagename):
55 + # Your special security rule
56 + if somehting:
57 + return false
58 +
59 + # Do not return True or you break acl!
60 + # This call will use the default acl rules
61 + return Permissions.read(pagename)
62 """
63
64 def __init__(self, user):
65 @@ -32,27 +45,105 @@
66 from MoinMoin.Page import Page
67 self.Page = Page
68 self.name = user.name
69 + self.user = user
70 self.request = user._request
71
72 def save(self, editor, newtext, rev, **kw):
73 """ Check whether user may save a page.
74
75 - `editor` is the PageEditor instance, the other arguments are
76 - those of the `PageEditor.saveText` method.
77 + Default implementation ignore newtext, rev and kw, and just try
78 + to get permission for write.
79 +
80 + @param editor: PageEditor instance.
81 + @param newtext: new page text, you can enable of disable saving according
82 + to the content of the text, e.g. prevent link spam.
83 + @param rev: new revision number? XXX
84 + @param kw: XXX
85 + @rtype: bool
86 + @return: True if you can save or False
87 """
88 return self.write(editor.page_name)
89
90 def __getattr__(self, attr):
91 - """ if attr is one of the rights in acl_rights_valid, then return a
92 - checking function for it. Else raise an error.
93 + """ Shortcut to export getPermission function for all known acl rights
94 +
95 + if attr is one of the rights in acl_rights_valid, then return a
96 + checking function for it. Else use normal getattr().
97 +
98 + @param attr: one of acl known rights as defined in acl_rights_valid
99 + @rtype: function
100 + @return: checking function for that right, accepting a pagename
101 """
102 - request = self.request
103 - Page = self.Page
104 - if attr in request.cfg.acl_rights_valid:
105 - return lambda pagename, Page=Page, request=request, attr=attr: Page(request, pagename).getACL(request).may(request, self.name, attr)
106 + if attr in self.request.cfg.acl_rights_valid:
107 + self._right = attr
108 + return self._getPermission
109 else:
110 raise AttributeError, attr
111
112 + def _getPermission(self, pagename):
113 + """ Get permission by transversing page hierarchy
114 +
115 + If cfg.acl_hierarchic, we check each page in the hierarchy. If all
116 + pages agree, we have permission. If one page in the hierarchy
117 + does not agree, we don't. Otherwise, only pagename is checked.
118 +
119 + This method should not be called by users, use __getattr__
120 + instead. If you want to get permission for delete, try:
121 + instance.delete(pagename).
122 +
123 + @param pagename: pagename to get permission from
124 + @rtype: bool
125 + @return: True if you have permission or False
126 + """
127 + from MoinMoin.Page import Page
128 +
129 + # Use page hierarchy or only pagename, according to wiki config.
130 + if self.request.cfg.acl_hierarchic:
131 + pages = pagename.split('/')
132 + #open('/tmp/acl.log','a').write('acl_hierarchic enabled\n')
133 + else:
134 + #open('/tmp/acl.log','a').write('acl_hierarchic disabled\n')
135 + pages = [pagename]
136 +
137 + # disable logging seems not bugfree
138 + #open('/tmp/acl.log','a').write('may(%s): pages %s\n'%(self._right, pages,))
139 + # check before
140 + allowed = self.request.cfg.acl_before.may(self.request, self.user.name, self._right)
141 + if allowed is not None:
142 + #open('/tmp/acl.log','a').write('may: before returns %s\n'%(allowed,))
143 + return allowed
144 +
145 + # Get permission
146 + some_acl = False
147 + for i in range(len(pages), 0, -1):
148 + # Create the next pagename in the hierarchy
149 + # starting with the leave, going to the root
150 + name = '/'.join(pages[:i])
151 + # Get page acl and ask for permission
152 + acl = Page(self.request, name).getACL(self.request)
153 + #open('/tmp/acl.log','a').write('may: checking acl of %s (%s)\n'%(name, `acl.acl`))
154 + if acl.acl:
155 + some_acl = True
156 + allowed = acl.may(self.request, self.user.name, self._right)
157 + if allowed is not None:
158 + #open('/tmp/acl.log','a').write('may: acl of %s (%s) returns %s\n'%(name, `acl.acl`, allowed,))
159 + return allowed
160 + if not some_acl:
161 + allowed = self.request.cfg.acl_default.may(self.request, self.user.name, self._right)
162 + if allowed is not None:
163 + #open('/tmp/acl.log','a').write('may: default returns %s\n'%(allowed,))
164 + return allowed
165 +
166 + # check after
167 + allowed = self.request.cfg.acl_after.may(self.request, self.user.name, self._right)
168 + if allowed is not None:
169 + #open('/tmp/acl.log','a').write('may: after returns %s\n'%(allowed,))
170 + return allowed
171 +
172 + # sane default permission, if you want True,
173 + # just put 'All:read' (or more) into your acl_rights_after
174 + return False
175 +
176
177 # make an alias for the default policy
178 Default = Permissions
179 diff -Naur old/MoinMoin/wikiacl.py new/MoinMoin/wikiacl.py
180 --- old/MoinMoin/wikiacl.py 2005-06-12 13:43:48.620090368 +0200
181 +++ new/MoinMoin/wikiacl.py 2005-06-12 13:37:29.537719648 +0200
182 @@ -113,33 +113,24 @@
183
184 special_users = ["All", "Known", "Trusted"]
185
186 - def __init__(self, request, lines=[]):
187 + def __init__(self, request, lines=[], cfg=None):
188 """Initialize an ACL, starting from <nothing>.
189 """
190 - self.setLines(request.cfg, lines)
191 + if cfg is not None:
192 + self.setLines(cfg, lines)
193 + else:
194 + self.setLines(request.cfg, lines)
195
196 def setLines(self, cfg, lines=[]):
197 self.clean()
198 - self.addBefore(cfg)
199 - if not lines:
200 - self.addDefault(cfg)
201 - else:
202 - for line in lines:
203 - self.addLine(cfg, line)
204 - self.addAfter(cfg)
205 + for line in lines:
206 + self.addLine(cfg, line)
207
208 def clean(self):
209 self.acl = [] # [ ('User', {"read": 0, ...}), ... ]
210 self.acl_lines = []
211 self._is_group = {}
212
213 - def addBefore(self, cfg):
214 - self.addLine(cfg, cfg.acl_rights_before, remember=0)
215 - def addDefault(self, cfg):
216 - self.addLine(cfg, cfg.acl_rights_default, remember=0)
217 - def addAfter(self, cfg):
218 - self.addLine(cfg, cfg.acl_rights_after, remember=0)
219 -
220 def addLine(self, cfg, aclstring, remember=1):
221 """ Add another ACL line
222
223 @@ -182,7 +173,7 @@
224 rightsdict[right] = (right in rights)
225 self.acl.append((entry, rightsdict))
226
227 - def may(self, request, name, dowhat):
228 + def may(self, request, name, dowhat, recurse=False):
229 """May <name> <dowhat>?
230 Returns boolean answer.
231 """
232 @@ -210,7 +201,7 @@
233 allowed = rightsdict.get(dowhat)
234 if allowed is not None:
235 return allowed
236 - return 0
237 + return allowed
238
239 def getString(self, b='#acl ', e='\n'):
240 """print the acl strings we were fed with"""
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.