1
# -*- coding: iso-8859-1 -*-
3
MoinMoin - MoinMoin.security Tests
5
TODO: when refactoring this, do not use "iter" (is a builtin)
7
@copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
8
2007 by MoinMoin:ReimarBauer,
9
2007 by MoinMoin:ThomasWaldmann
10
@license: GNU GPL, see COPYING for details.
15
from MoinMoin import security
16
acliter = security.ACLStringIterator
17
AccessControlList = security.AccessControlList
19
from MoinMoin.PageEditor import PageEditor
20
from MoinMoin.user import User
22
from MoinMoin._tests import become_trusted, create_page, nuke_page
24
class TestACLStringIterator(object):
27
""" security: empty acl string raise StopIteration """
28
iter = acliter(self.request.cfg.acl_rights_valid, '')
29
py.test.raises(StopIteration, iter.next)
31
def testWhiteSpace(self):
32
""" security: white space acl string raise StopIteration """
33
iter = acliter(self.request.cfg.acl_rights_valid, ' ')
34
py.test.raises(StopIteration, iter.next)
36
def testDefault(self):
37
""" security: default meta acl """
38
iter = acliter(self.request.cfg.acl_rights_valid, 'Default Default')
39
for mod, entries, rights in iter:
40
assert entries == ['Default']
43
def testEmptyRights(self):
44
""" security: empty rights """
45
iter = acliter(self.request.cfg.acl_rights_valid, 'WikiName:')
46
mod, entries, rights = iter.next()
47
assert entries == ['WikiName']
50
def testSingleWikiNameSingleWrite(self):
51
""" security: single wiki name, single right """
52
iter = acliter(self.request.cfg.acl_rights_valid, 'WikiName:read')
53
mod, entries, rights = iter.next()
54
assert entries == ['WikiName']
55
assert rights == ['read']
57
def testMultipleWikiNameAndRights(self):
58
""" security: multiple wiki names and rights """
59
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne,UserTwo:read,write')
60
mod, entries, rights = iter.next()
61
assert entries == ['UserOne', 'UserTwo']
62
assert rights == ['read', 'write']
64
def testMultipleWikiNameAndRightsSpaces(self):
65
""" security: multiple names with spaces """
66
iter = acliter(self.request.cfg.acl_rights_valid, 'user one,user two:read')
67
mod, entries, rights = iter.next()
68
assert entries == ['user one', 'user two']
69
assert rights == ['read']
71
def testMultipleEntries(self):
72
""" security: multiple entries """
73
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read,write UserTwo:read All:')
74
mod, entries, rights = iter.next()
75
assert entries == ['UserOne']
76
assert rights == ['read', 'write']
77
mod, entries, rights = iter.next()
78
assert entries == ['UserTwo']
79
assert rights == ['read']
80
mod, entries, rights = iter.next()
81
assert entries == ['All']
84
def testNameWithSpaces(self):
85
""" security: single name with spaces """
86
iter = acliter(self.request.cfg.acl_rights_valid, 'user one:read')
87
mod, entries, rights = iter.next()
88
assert entries == ['user one']
89
assert rights == ['read']
91
def testMultipleEntriesWithSpaces(self):
92
""" security: multiple entries with spaces """
93
iter = acliter(self.request.cfg.acl_rights_valid, 'user one:read,write user two:read')
94
mod, entries, rights = iter.next()
95
assert entries == ['user one']
96
assert rights == ['read', 'write']
97
mod, entries, rights = iter.next()
98
assert entries == ['user two']
99
assert rights == ['read']
101
def testMixedNames(self):
102
""" security: mixed wiki names and names with spaces """
103
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne,user two:read,write user three,UserFour:read')
104
mod, entries, rights = iter.next()
105
assert entries == ['UserOne', 'user two']
106
assert rights == ['read', 'write']
107
mod, entries, rights = iter.next()
108
assert entries == ['user three', 'UserFour']
109
assert rights == ['read']
111
def testModifier(self):
112
""" security: acl modifiers """
113
iter = acliter(self.request.cfg.acl_rights_valid, '+UserOne:read -UserTwo:')
114
mod, entries, rights = iter.next()
116
assert entries == ['UserOne']
117
assert rights == ['read']
118
mod, entries, rights = iter.next()
120
assert entries == ['UserTwo']
123
def testIgnoreInvalidACL(self):
124
""" security: ignore invalid acl
126
The last part of this acl can not be parsed. If it ends with :
127
then it will be parsed as one name with spaces.
129
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read user two is ignored')
130
mod, entries, rights = iter.next()
131
assert entries == ['UserOne']
132
assert rights == ['read']
133
py.test.raises(StopIteration, iter.next)
135
def testEmptyNamesWithRight(self):
136
""" security: empty names with rights
138
The documents does not talk about this case, may() should ignore
139
the rights because there is no entry.
141
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read :read All:')
142
mod, entries, rights = iter.next()
143
assert entries == ['UserOne']
144
assert rights == ['read']
145
mod, entries, rights = iter.next()
147
assert rights == ['read']
148
mod, entries, rights = iter.next()
149
assert entries == ['All']
152
def testIgnodeInvalidRights(self):
153
""" security: ignore rights not in acl_rights_valid """
154
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read,sing,write,drink,sleep')
155
mod, entries, rights = iter.next()
156
assert rights == ['read', 'write']
158
def testBadGuy(self):
159
""" security: bad guy may not allowed anything
161
This test was failing on the apply acl rights test.
163
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read,write BadGuy: All:read')
164
mod, entries, rights = iter.next()
165
mod, entries, rights = iter.next()
166
assert entries == ['BadGuy']
169
def testAllowExtraWhitespace(self):
170
""" security: allow extra white space between entries """
171
iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne,user two:read,write user three,UserFour:read All:')
172
mod, entries, rights = iter.next()
173
assert entries == ['UserOne', 'user two']
174
assert rights == ['read', 'write']
175
mod, entries, rights = iter.next()
176
assert entries == ['user three', 'UserFour']
177
assert rights == ['read']
178
mod, entries, rights = iter.next()
179
assert entries == ['All']
183
class TestAcl(object):
184
""" security: testing access control list
186
TO DO: test unknown user?
188
def setup_method(self, method):
190
self.savedUser = self.request.user.name
192
def teardown_method(self, method):
194
self.request.user.name = self.savedUser
196
def testApplyACLByUser(self):
197
""" security: applying acl by user name"""
204
"Admin1,Admin2:read,write,delete,revert,admin "
205
"Admin3:read,write,admin "
207
"name with spaces,another one:read,write "
208
"CamelCase,extended name:read,write "
212
acl = security.AccessControlList(self.request.cfg, acl_rights)
214
# Should apply these rights:
218
('Admin1', ('read', 'write', 'admin', 'revert', 'delete')),
219
('Admin2', ('read', 'write', 'admin', 'revert', 'delete')),
220
('Admin3', ('read', 'write', 'admin')),
221
('JoeDoe', ('read', 'write')),
222
('SomeGuy', ('read', )),
223
# Extended names or mix of extended and CamelCase
224
('name with spaces', ('read', 'write', )),
225
('another one', ('read', 'write', )),
226
('CamelCase', ('read', 'write', )),
227
('extended name', ('read', 'write', )),
230
# All other users - every one not mentioned in the acl lines
232
('Anonymous', ('read', )),
233
# we check whether ACL processing stops for a user/right match
236
('PlusGuy', ('read', )),
240
for user, may in users:
241
mayNot = [right for right in self.request.cfg.acl_rights_valid
243
# User should have these rights...
245
assert acl.may(self.request, user, right)
248
assert not acl.may(self.request, user, right)
251
class TestPageAcls(object):
252
""" security: real-life access control list on pages testing
254
mainpage_name = u'AclTestMainPage'
255
subpage_name = u'AclTestMainPage/SubPage'
256
item_rwforall = u'EveryoneMayReadWriteMe'
257
subitem_4boss = u'EveryoneMayReadWriteMe/OnlyTheBossMayWMe'
260
(mainpage_name, u"#acl JoeDoe:\n#acl JaneDoe:read,write\nFoo!"),
261
(subpage_name, u"FooFoo!"),
262
(item_rwforall, u"#acl All:read,write\nMay be read from and written to by anyone"),
263
(subitem_4boss, u"#acl JoeDoe:read,write\nOnly JoeDoe (the boss) may write"),
266
from MoinMoin._tests import wikiconfig
267
class Config(wikiconfig.Config):
268
acl_rights_before = u"WikiAdmin:admin,read,write,delete,revert"
269
acl_rights_default = u"All:read,write"
270
acl_rights_after = u"All:read"
271
acl_hierarchic = False
273
def setup_class(self):
275
self.savedUser = self.request.user.name
276
self.request.user = User(self.request, auth_username=u'WikiAdmin')
277
self.request.user.valid = True
279
for page_name, page_content in self.pages:
280
create_page(self.request, page_name, page_content)
282
def teardown_class(self):
284
self.request.user.name = self.savedUser
286
for page_name, dummy in self.pages:
287
nuke_page(self.request, page_name)
289
def testPageACLs(self):
290
""" security: test page acls """
292
# hierarchic, pagename, username, expected_rights
293
(False, self.mainpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
294
(True, self.mainpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
295
(False, self.mainpage_name, u'AnyUser', ['read']), # by after acl
296
(True, self.mainpage_name, u'AnyUser', ['read']), # by after acl
297
(False, self.mainpage_name, u'JaneDoe', ['read', 'write']), # by page acl
298
(True, self.mainpage_name, u'JaneDoe', ['read', 'write']), # by page acl
299
(False, self.mainpage_name, u'JoeDoe', []), # by page acl
300
(True, self.mainpage_name, u'JoeDoe', []), # by page acl
301
(False, self.subpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
302
(True, self.subpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
303
(False, self.subpage_name, u'AnyUser', ['read', 'write']), # by default acl
304
(True, self.subpage_name, u'AnyUser', ['read']), # by after acl
305
(False, self.subpage_name, u'JoeDoe', ['read', 'write']), # by default acl
306
(True, self.subpage_name, u'JoeDoe', []), # by inherited acl from main page
307
(False, self.subpage_name, u'JaneDoe', ['read', 'write']), # by default acl
308
(True, self.subpage_name, u'JaneDoe', ['read', 'write']), # by inherited acl from main page
309
(True, self.subitem_4boss, u'AnyUser', ['read']), # by after acl
310
(True, self.subitem_4boss, u'JoeDoe', ['read', 'write']), # by item acl
313
for hierarchic, pagename, username, may in tests:
314
u = User(self.request, auth_username=username)
317
def _have_right(u, right, pagename, hierarchic):
318
self.request.cfg.acl_hierarchic = hierarchic
319
can_access = u.may.__getattr__(right)(pagename)
321
print "page %s: %s test if %s may %s (success)" % (
322
pagename, ['normal', 'hierarchic'][hierarchic], username, right)
324
print "page %s: %s test if %s may %s (failure)" % (
325
pagename, ['normal', 'hierarchic'][hierarchic], username, right)
328
# User should have these rights...
330
yield _have_right, u, right, pagename, hierarchic
332
def _not_have_right(u, right, pagename, hierarchic):
333
self.request.cfg.acl_hierarchic = hierarchic
334
can_access = u.may.__getattr__(right)(pagename)
336
print "page %s: %s test if %s may not %s (failure)" % (
337
pagename, ['normal', 'hierarchic'][hierarchic], username, right)
339
print "page %s: %s test if %s may not %s (success)" % (
340
pagename, ['normal', 'hierarchic'][hierarchic], username, right)
341
assert not can_access
343
# User should NOT have these rights:
344
mayNot = [right for right in self.request.cfg.acl_rights_valid
347
yield _not_have_right, u, right, pagename, hierarchic
349
coverage_modules = ['MoinMoin.security']