1
2
3
4
5
6
7
8
9
10
11
12
13
14 import os.path
15 import textwrap
16 import unittest
17
18 from trac.config import ConfigurationError
19 from trac.resource import Resource
20 from trac.test import EnvironmentStub, Mock, mkdtemp, rmtree
21 from trac.util import create_file
22 from trac.versioncontrol.api import RepositoryManager
23 from trac.versioncontrol.svn_authz import AuthzSourcePolicy, parse
24
25
27
31
34
36 create_file(self.authz_file, textwrap.dedent("""\
37 [groups]
38 developers = foo, bar
39 users = @developers, &baz
40
41 [aliases]
42 baz = CN=Hàröld Hacker,OU=Enginéers,DC=red-bean,DC=com
43
44 # Applies to all repositories
45 [/]
46 * = r
47
48 [/trunk]
49 @developers = rw
50 &baz =
51 @users = r
52
53 [/branches]
54 bar = rw
55
56 ; Applies only to module
57 [module:/trunk]
58 foo = rw
59 &baz = r
60
61 ; Unicode module names
62 [module:/c/résumé]
63 bar = rw
64 Foo = rw
65 BAZ = r
66
67 ; Unicode module names
68 [module:/c/résumé]
69 bar = rw
70 Foo = rw
71 BAZ = r
72
73 ; Unused module, not parsed
74 [unused:/some/path]
75 foo = r
76 """))
77 authz = parse(self.authz_file, {'', 'module'})
78 self.assertEqual({
79 '': {
80 u'/': {
81 u'*': True,
82 },
83 u'/trunk': {
84 u'foo': True,
85 u'bar': True,
86 u'CN=Hàröld Hacker,OU=Enginéers,DC=red-bean,DC=com': True,
87 },
88 u'/branches': {
89 u'bar': True,
90 },
91 },
92 u'module': {
93 u'/trunk': {
94 u'foo': True,
95 u'CN=Hàröld Hacker,OU=Enginéers,DC=red-bean,DC=com': True,
96 },
97 u'/c/résumé': {
98 u'bar': True,
99 u'Foo': True,
100 u'BAZ': True,
101 },
102 },
103 }, authz)
104
105
107
109 tmpdir = mkdtemp()
110 self.authz_file = os.path.join(tmpdir, 'trac-authz')
111 create_file(self.authz_file, textwrap.dedent("""\
112 [groups]
113 group1 = user
114 group2 = @group1
115
116 cycle1 = @cycle2
117 cycle2 = @cycle3
118 cycle3 = @cycle1, user
119
120 alias1 = &jekyll
121 alias2 = @alias1
122
123 [aliases]
124 jekyll = Mr Hyde
125
126 # Read / write permissions
127 [/readonly]
128 user = r
129 [/writeonly]
130 user = w
131 [/readwrite]
132 user = rw
133 [/empty]
134 user =
135
136 # Trailing slashes
137 [/trailing_a]
138 user = r
139 [/trailing_b/]
140 user = r
141
142 # Sub-paths
143 [/sub/path]
144 user = r
145
146 # Module usage
147 [module:/module_a]
148 user = r
149 [other:/module_b]
150 user = r
151 [/module_c]
152 user = r
153 [module:/module_d]
154 user =
155 [/module_d]
156 user = r
157
158 # Wildcards
159 [/wildcard]
160 * = r
161
162 # Special tokens
163 [/special/anonymous]
164 $anonymous = r
165 [/special/authenticated]
166 $authenticated = r
167
168 # Groups
169 [/groups_a]
170 @group1 = r
171 [/groups_b]
172 @group2 = r
173 [/cyclic]
174 @cycle1 = r
175
176 # Precedence
177 [module:/precedence_a]
178 user =
179 [/precedence_a]
180 user = r
181 [/precedence_b]
182 user = r
183 [/precedence_b/sub]
184 user =
185 [/precedence_b/sub/test]
186 user = r
187 [/precedence_c]
188 user =
189 @group1 = r
190 [/precedence_d]
191 @group1 = r
192 user =
193
194 # Aliases
195 [/aliases_a]
196 &jekyll = r
197 [/aliases_b]
198 @alias2 = r
199
200 # Scoped repository
201 [scoped:/scope/dir1]
202 joe = r
203 [scoped:/scope/dir2]
204 Jane = r
205
206 # multiple entries
207 [/multiple]
208 $authenticated = r
209 [/multiple/foo]
210 joe =
211 $authenticated =
212 * = r
213 [/multiple/bar]
214 * =
215 john = r
216 Jane = r
217 $anonymous = r
218 [/multiple/baz]
219 $anonymous = r
220 * =
221 Jane = r
222 [module:/multiple/bar]
223 joe = r
224 john =
225
226 # multiple entries with module and parent directory
227 [/multiple/1]
228 user = r
229 @group1 = r
230 $authenticated = r
231 * = r
232 [module:/multiple/1/user]
233 user =
234 [module:/multiple/1/group]
235 @group1 =
236 [module:/multiple/1/auth]
237 $authenticated =
238 [module:/multiple/1/star]
239 * =
240 [/multiple/2]
241 user =
242 @group1 =
243 $authenticated =
244 * =
245 [module:/multiple/2/user]
246 user = r
247 [module:/multiple/2/group]
248 @group1 = r
249 [module:/multiple/2/auth]
250 $authenticated = r
251 [module:/multiple/2/star]
252 * = r
253 """))
254 self.env = EnvironmentStub(enable=[AuthzSourcePolicy], path=tmpdir)
255 self.env.config.set('trac', 'permission_policies',
256 'AuthzSourcePolicy, DefaultPermissionPolicy')
257 self.env.config.set('svn', 'authz_file', self.authz_file)
258
259
260 rm = RepositoryManager(self.env)
261
262 class TestRepositoryManager(rm.__class__):
263 def get_real_repositories(self):
264 return {Mock(reponame='module'), Mock(reponame='other'),
265 Mock(reponame='scoped')}
266
267 def get_repository(self, reponame):
268 if reponame == 'scoped':
269 def get_changeset(rev):
270 if rev == 123:
271 def get_changes():
272 yield ('/dir1/file',)
273 elif rev == 456:
274 def get_changes():
275 yield ('/dir2/file',)
276 else:
277 def get_changes():
278 return iter([])
279 return Mock(get_changes=get_changes)
280 return Mock(scope='/scope',
281 get_changeset=get_changeset)
282 return Mock(scope='/')
283
284 rm.__class__ = TestRepositoryManager
285
288
296
304
312
319
330
343
356
358 policy = AuthzSourcePolicy(self.env)
359
360 self.assertPathPerm(True, 'unknown')
361 self.assertPathPerm(True, 'joe')
362 self.assertRevPerm(True, 'unknown')
363 self.assertRevPerm(True, 'joe')
364
365 policy._mtime = 0
366 create_file(self.authz_file, textwrap.dedent("""\
367 [/somepath]
368 joe = r
369 denied =
370 [module:/otherpath]
371 Jane = r
372 $anonymous = r
373 [inactive:/not-in-this-instance]
374 unknown = r
375 """))
376 self.assertPathPerm(None, 'unknown')
377 self.assertRevPerm(None, 'unknown')
378 self.assertPathPerm(None, 'denied')
379 self.assertRevPerm(None, 'denied')
380 self.assertPathPerm(True, 'joe')
381 self.assertRevPerm(True, 'joe')
382 self.assertPathPerm(True, 'Jane')
383 self.assertRevPerm(True, 'Jane')
384 self.assertPathPerm(True, 'anonymous')
385 self.assertRevPerm(True, 'anonymous')
386
391
393
394 self.assertPathPerm(True, 'user', '', '/readonly')
395 self.assertPathPerm(True, 'user', '', '/readwrite')
396 self.assertPathPerm(False, 'user', '', '/writeonly')
397 self.assertPathPerm(False, 'user', '', '/empty')
398
400
401 self.assertPathPerm(True, 'user', '', '/trailing_a')
402 self.assertPathPerm(True, 'user', '', '/trailing_a/')
403 self.assertPathPerm(True, 'user', '', '/trailing_b')
404 self.assertPathPerm(True, 'user', '', '/trailing_b/')
405
411
413
414 self.assertPathPerm(True, 'user', 'module', '/module_a')
415 self.assertPathPerm(None, 'user', 'module', '/module_b')
416
417
418 self.assertPathPerm(True, 'user', 'module', '/module_c')
419
420 self.assertPathPerm(True, 'user', '', '/module_d')
421 self.assertPathPerm(False, 'user', 'module', '/module_d')
422
428
430
431 self.assertPathPerm(True, 'anonymous', '', '/special/anonymous')
432 self.assertPathPerm(None, 'user', '', '/special/anonymous')
433
434 self.assertPathPerm(None, 'anonymous', '', '/special/authenticated')
435 self.assertPathPerm(True, 'joe', '', '/special/authenticated')
436 self.assertPathPerm(True, 'Jane', '', '/special/authenticated')
437
446
448
449 self.assertPathPerm(False, 'user', 'module', '/precedence_a')
450
451 self.assertPathPerm(True, 'user', '', '/precedence_b/sub/test')
452
453
454
455 self.assertPathPerm(True, 'user', '', '/precedence_b/sub')
456 self.assertPathPerm(True, 'user', '', '/precedence_b')
457
458 self.assertPathPerm(True, 'user', '', '/precedence_c')
459 self.assertPathPerm(True, 'user', '', '/precedence_d')
460
466
468
469 self.assertPathPerm(True, 'joe', 'scoped', '/dir1')
470 self.assertPathPerm(None, 'joe', 'scoped', '/dir2')
471 self.assertPathPerm(True, 'joe', 'scoped', '/')
472 self.assertPathPerm(None, 'Jane', 'scoped', '/dir1')
473 self.assertPathPerm(True, 'Jane', 'scoped', '/dir2')
474 self.assertPathPerm(True, 'Jane', 'scoped', '/')
475
477 self.assertPathPerm(True, 'anonymous', '', '/multiple/foo')
478 self.assertPathPerm(True, 'joe', '', '/multiple/foo')
479 self.assertPathPerm(True, 'anonymous', '', '/multiple/bar')
480 self.assertPathPerm(False, 'joe', '', '/multiple/bar')
481 self.assertPathPerm(True, 'john', '', '/multiple/bar')
482 self.assertPathPerm(True, 'anonymous', '', '/multiple/baz')
483 self.assertPathPerm(True, 'Jane', '', '/multiple/baz')
484 self.assertPathPerm(False, 'joe', '', '/multiple/baz')
485 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/foo')
486 self.assertPathPerm(True, 'joe', 'module', '/multiple/foo')
487 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/bar')
488 self.assertPathPerm(True, 'joe', 'module', '/multiple/bar')
489 self.assertPathPerm(False, 'john', 'module', '/multiple/bar')
490 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/baz')
491 self.assertPathPerm(True, 'Jane', 'module', '/multiple/baz')
492 self.assertPathPerm(False, 'joe', 'module', '/multiple/baz')
493
495 self.assertPathPerm(True, 'anonymous', '', '/multiple/1')
496 self.assertPathPerm(True, 'user', '', '/multiple/1')
497 self.assertPathPerm(True, 'someone', '', '/multiple/1')
498 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/1')
499 self.assertPathPerm(True, 'user', 'module', '/multiple/1')
500 self.assertPathPerm(True, 'someone', 'module', '/multiple/1')
501 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/1/user')
502 self.assertPathPerm(False, 'user', 'module', '/multiple/1/user')
503 self.assertPathPerm(True, 'someone', 'module', '/multiple/1/user')
504 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/1/group')
505 self.assertPathPerm(False, 'user', 'module', '/multiple/1/group')
506 self.assertPathPerm(True, 'someone', 'module', '/multiple/1/group')
507 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/1/auth')
508 self.assertPathPerm(False, 'user', 'module', '/multiple/1/auth')
509 self.assertPathPerm(False, 'someone', 'module', '/multiple/1/auth')
510 self.assertPathPerm(False, 'anonymous', 'module', '/multiple/1/star')
511 self.assertPathPerm(False, 'user', 'module', '/multiple/1/star')
512 self.assertPathPerm(False, 'someone', 'module', '/multiple/1/star')
513
514 self.assertPathPerm(False, 'anonymous', '', '/multiple/2')
515 self.assertPathPerm(False, 'user', '', '/multiple/2')
516 self.assertPathPerm(False, 'someone', '', '/multiple/2')
517 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/2')
518 self.assertPathPerm(True, 'user', 'module', '/multiple/2')
519 self.assertPathPerm(True, 'someone', 'module', '/multiple/2')
520 self.assertPathPerm(False, 'anonymous', 'module', '/multiple/2/user')
521 self.assertPathPerm(True, 'user', 'module', '/multiple/2/user')
522 self.assertPathPerm(False, 'someone', 'module', '/multiple/2/user')
523 self.assertPathPerm(False, 'anonymous', 'module', '/multiple/2/group')
524 self.assertPathPerm(True, 'user', 'module', '/multiple/2/group')
525 self.assertPathPerm(False, 'someone', 'module', '/multiple/2/group')
526 self.assertPathPerm(False, 'anonymous', 'module', '/multiple/2/auth')
527 self.assertPathPerm(True, 'user', 'module', '/multiple/2/auth')
528 self.assertPathPerm(True, 'someone', 'module', '/multiple/2/auth')
529 self.assertPathPerm(True, 'anonymous', 'module', '/multiple/2/star')
530 self.assertPathPerm(True, 'user', 'module', '/multiple/2/star')
531 self.assertPathPerm(True, 'someone', 'module', '/multiple/2/star')
532
534
535
536 self.assertRevPerm(True, 'joe', 'scoped', 123)
537 self.assertRevPerm(None, 'joe', 'scoped', 456)
538 self.assertRevPerm(True, 'joe', 'scoped', 789)
539 self.assertRevPerm(None, 'Jane', 'scoped', 123)
540 self.assertRevPerm(True, 'Jane', 'scoped', 456)
541 self.assertRevPerm(True, 'Jane', 'scoped', 789)
542 self.assertRevPerm(None, 'user', 'scoped', 123)
543 self.assertRevPerm(None, 'user', 'scoped', 456)
544 self.assertRevPerm(True, 'user', 'scoped', 789)
545
546
552
553
554 if __name__ == '__main__':
555 unittest.main(defaultTest='test_suite')
556