1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import unittest
16
17 from trac.perm import PermissionSystem
18 from trac.tests.functional import FunctionalTwillTestCaseSetup, tc
19 from trac.util.text import unicode_to_base64
20
21
24 """Check permissions required to access an administration panel.
25
26 :param href: the relative href of the administration panel
27 :param perms: list or tuple of permissions required to access
28 the administration panel
29 :param h2_text: the body of the h2 heading on the administration
30 panel"""
31 self._tester.go_to_front()
32 self._tester.logout()
33 self._tester.login('user')
34 if isinstance(perms, basestring):
35 perms = (perms, )
36
37 h2 = r'<h2>[ \t\n]*%s[ \t\n]*' \
38 r'( <span class="trac-count">\(\d+\)</span>)?[ \t\n]*</h2>'
39 try:
40 for perm in perms:
41 try:
42 tc.go(href)
43 tc.find("No administration panels available")
44 self._testenv.grant_perm('user', perm)
45 tc.go(href)
46 tc.find(h2 % h2_text)
47 finally:
48 self._testenv.revoke_perm('user', perm)
49 try:
50 tc.go(href)
51 tc.find("No administration panels available")
52 self._testenv.enable_authz_permpolicy({
53 href.strip('/').replace('/', ':', 1): {'user': perm},
54 })
55 tc.go(href)
56 tc.find(h2 % h2_text)
57 finally:
58 self._testenv.disable_authz_permpolicy()
59 finally:
60 self._tester.go_to_front()
61 self._tester.logout()
62 self._tester.login('admin')
63
64
67 """Check basic settings."""
68 self._tester.go_to_admin()
69 tc.formvalue('modbasic', 'url', 'https://my.example.com/something')
70 tc.submit()
71 tc.find('https://my.example.com/something')
72
73 try:
74 tc.formvalue('modbasic', 'default_dateinfo_format', 'absolute')
75 tc.submit()
76 tc.find(r'<option selected="selected" value="absolute">')
77 tc.formvalue('modbasic', 'default_dateinfo_format', 'relative')
78 tc.submit()
79 tc.find(r'<option selected="selected" value="relative">')
80 finally:
81 self._testenv.remove_config('trac', 'default_dateinfo_format')
82 self._tester.go_to_admin()
83 tc.find(r'<option selected="selected" value="relative">')
84 tc.find(r'<option value="absolute">')
85
86
89 """Check permissions required to access Basic Settings panel."""
90 self.test_authorization('/admin/general/basics', 'TRAC_ADMIN',
91 "Basic Settings")
92
93
96 """Set default handler from the Basic Settings page."""
97
98
99 self._tester.go_to_admin("Basic Settings")
100 tc.find(r'<option selected="selected" value="WikiModule">'
101 r'WikiModule</option>')
102 tc.go(self._tester.url)
103 tc.find("Welcome to Trac")
104
105
106 self._tester.go_to_admin("Basic Settings")
107 tc.formvalue('modbasic', 'default_handler', 'TimelineModule')
108 tc.submit()
109 tc.find("Your changes have been saved.")
110 tc.find(r'<option selected="selected" value="TimelineModule">'
111 r'TimelineModule</option>')
112 tc.go(self._tester.url)
113 tc.find(r'<h1>Timeline</h1>')
114
115
116 try:
117 self._testenv.set_config('components',
118 'trac.timeline.web_ui.TimelineModule',
119 'disabled')
120 self._tester.go_to_admin("Basic Settings")
121 tc.find(r'<option value="TimelineModule">TimelineModule</option>')
122 tc.find(r'<span class="hint">\s*TimelineModule is not a valid '
123 r'IRequestHandler or is not enabled.\s*</span>')
124 tc.go(self._tester.url)
125 tc.find(r'<h1>Configuration Error</h1>')
126 tc.find(r'Cannot find an implementation of the '
127 r'<code>IRequestHandler</code> interface named '
128 r'<code>TimelineModule</code>')
129 finally:
130 self._testenv.remove_config('components',
131 'trac.timeline.web_ui.timelinemodule')
132
133
134 try:
135 self._testenv.set_config('trac', 'default_handler',
136 'BatchModifyModule')
137 self._tester.go_to_admin("Basic Settings")
138 tc.find(r'<option value="BatchModifyModule">BatchModifyModule'
139 r'</option>')
140 tc.find(r'<span class="hint">\s*BatchModifyModule is not a valid '
141 r'IRequestHandler or is not enabled.\s*</span>')
142 tc.formvalue('modbasic', 'default_handler', 'BatchModifyModule')
143 tc.submit()
144 tc.find(r'<option value="BatchModifyModule">BatchModifyModule'
145 r'</option>')
146 tc.find(r'<span class="hint">\s*BatchModifyModule is not a valid '
147 r'IRequestHandler or is not enabled.\s*</span>')
148 tc.go(self._tester.url)
149 tc.find(r'<h1>Configuration Error</h1>')
150 tc.find(r'<code>BatchModifyModule</code> is not a valid default '
151 r'handler.')
152 finally:
153 self._testenv.set_config('trac', 'default_handler', 'WikiModule')
154
155
158 """Turn off logging."""
159
160 self._tester.go_to_admin("Logging")
161 tc.find('trac.log')
162 tc.formvalue('modlog', 'log_type', 'none')
163 tc.submit()
164 tc.find('selected="selected" value="none">None</option')
165
166
169 """Check permissions required to access Logging panel."""
170 self.test_authorization('/admin/general/logging', 'TRAC_ADMIN',
171 "Logging")
172
173
176 """Turn logging back on."""
177
178 self._tester.go_to_admin("Logging")
179 tc.find('trac.log')
180 tc.formvalue('modlog', 'log_type', 'file')
181 tc.formvalue('modlog', 'log_file', 'trac.log2')
182 tc.formvalue('modlog', 'log_level', 'INFO')
183 tc.submit()
184 tc.find('selected="selected" value="file">File</option')
185 tc.find('id="log_file".*value="trac.log2"')
186 tc.find('selected="selected">INFO</option>')
187
188
191 """Setting logging back to normal."""
192
193 self._tester.go_to_admin("Logging")
194 tc.find('trac.log')
195 tc.formvalue('modlog', 'log_file', 'trac.log')
196 tc.formvalue('modlog', 'log_level', 'DEBUG')
197 tc.submit()
198 tc.find('selected="selected" value="file">File</option')
199 tc.find('id="log_file".*value="trac.log"')
200 tc.find('selected="selected">DEBUG</option>')
201
202
205 """Check permissions required to access Permissions panel."""
206 self.test_authorization('/admin/general/perm',
207 ('PERMISSION_GRANT', 'PERMISSION_REVOKE'),
208 "Manage Permissions and Groups")
209
210
213 """Create a permissions group"""
214 self._tester.go_to_admin("Permissions")
215 tc.find('Manage Permissions')
216 tc.formvalue('addperm', 'gp_subject', 'somegroup')
217 tc.formvalue('addperm', 'action', 'REPORT_CREATE')
218 tc.submit()
219 somegroup = unicode_to_base64('somegroup')
220 REPORT_CREATE = unicode_to_base64('REPORT_CREATE')
221 tc.find('%s:%s' % (somegroup, REPORT_CREATE))
222
223
226 """Remove a permissions group"""
227 self._tester.go_to_admin("Permissions")
228 tc.find('Manage Permissions')
229 somegroup = unicode_to_base64('somegroup')
230 REPORT_CREATE = unicode_to_base64('REPORT_CREATE')
231 tc.find('%s:%s' % (somegroup, REPORT_CREATE))
232 tc.formvalue('revokeform', 'sel', '%s:%s' % (somegroup, REPORT_CREATE))
233 tc.submit()
234 tc.notfind('%s:%s' % (somegroup, REPORT_CREATE))
235 tc.notfind(somegroup)
236
237
240 """Add a user to a permissions group"""
241 self._tester.go_to_admin("Permissions")
242 tc.find('Manage Permissions')
243 tc.formvalue('addsubj', 'sg_subject', 'authenticated')
244 tc.formvalue('addsubj', 'sg_group', 'somegroup')
245 tc.submit()
246 authenticated = unicode_to_base64('authenticated')
247 somegroup = unicode_to_base64('somegroup')
248 tc.find('%s:%s' % (authenticated, somegroup))
249
250 revoke_checkbox = '%s:%s' % (unicode_to_base64('anonymous'),
251 unicode_to_base64('PERMISSION_GRANT'))
252 tc.formvalue('addperm', 'gp_subject', 'anonymous')
253 tc.formvalue('addperm', 'action', 'PERMISSION_GRANT')
254 tc.submit()
255 tc.find(revoke_checkbox)
256 self._testenv.get_trac_environment().config.touch()
257 self._tester.logout()
258 self._tester.go_to_admin("Permissions")
259 try:
260 tc.formvalue('addsubj', 'sg_subject', 'someuser')
261 tc.formvalue('addsubj', 'sg_group', 'authenticated')
262 tc.submit()
263 tc.find("The subject <strong>someuser</strong> was not added "
264 "to the group <strong>authenticated</strong>. The group "
265 "has <strong>TICKET_CREATE</strong> permission and you "
266 "cannot grant permissions you don't possess.")
267 finally:
268 self._tester.login('admin')
269 self._tester.go_to_admin("Permissions")
270 tc.formvalue('revokeform', 'sel', revoke_checkbox)
271 tc.submit()
272 tc.notfind(revoke_checkbox)
273
274
277 """Remove a user from a permissions group"""
278 self._tester.go_to_admin("Permissions")
279 tc.find('Manage Permissions')
280 authenticated = unicode_to_base64('authenticated')
281 somegroup = unicode_to_base64('somegroup')
282 tc.find('%s:%s' % (authenticated, somegroup))
283 tc.formvalue('revokeform', 'sel', '%s:%s' % (authenticated, somegroup))
284 tc.submit()
285 tc.notfind('%s:%s' % (authenticated, somegroup))
286
287
290 """Tests for the Copy Permissions functionality
291 added in https://trac.edgewall.org/ticket/11099."""
292 checkbox_value = lambda s, p: '%s:%s' % (unicode_to_base64(s),
293 unicode_to_base64(p))
294 grant_msg = "The subject %s has been granted the permission %s\."
295 def grant_permission(subject, action):
296 tc.formvalue('addperm', 'gp_subject', subject)
297 tc.formvalue('addperm', 'action', action)
298 tc.submit()
299 tc.find(grant_msg % (subject, action))
300 tc.find(checkbox_value(subject, action))
301
302 env = self._testenv.get_trac_environment()
303
304
305 self._tester.go_to_admin('Permissions')
306 perm_sys = PermissionSystem(env)
307 anon_perms = perm_sys.store.get_user_permissions('anonymous')
308 for perm in anon_perms:
309 tc.find(checkbox_value('anonymous', perm))
310 tc.notfind(checkbox_value('user1', perm))
311 tc.formvalue('copyperm', 'cp_subject', 'anonymous')
312 tc.formvalue('copyperm', 'cp_target', 'user1')
313 tc.submit()
314 for perm in anon_perms:
315 tc.find("The subject user1 has been granted the permission %s\."
316 % perm)
317 tc.find(checkbox_value('user1', perm))
318
319
320 tc.notfind(checkbox_value('noperms', ''))
321 tc.formvalue('copyperm', 'cp_subject', 'noperms')
322 tc.formvalue('copyperm', 'cp_target', 'user1')
323 tc.submit()
324 tc.find("The subject noperms does not have any permissions\.")
325
326
327 grant_permission('group1', 'TICKET_VIEW')
328 tc.formvalue('addsubj', 'sg_subject', 'noperms')
329 tc.formvalue('addsubj', 'sg_group', 'group1')
330 tc.submit()
331 tc.find("The subject noperms has been added to the group group1\.")
332
333 tc.formvalue('copyperm', 'cp_subject', 'noperms')
334 tc.formvalue('copyperm', 'cp_target', 'user1')
335 tc.submit()
336 tc.find("The subject noperms does not have any permissions\.")
337
338
339 tc.formvalue('copyperm', 'cp_subject', 'noperms')
340 tc.formvalue('copyperm', 'cp_target', 'USER1')
341 tc.submit()
342 tc.find("All upper-cased tokens are reserved for permission names\.")
343 self._tester.go_to_admin("Permissions")
344
345
346 tc.formvalue('copyperm', 'cp_subject', 'USER1')
347 tc.formvalue('copyperm', 'cp_target', 'noperms')
348 tc.submit()
349 tc.find("All upper-cased tokens are reserved for permission names\.")
350 self._tester.go_to_admin("Permissions")
351
352
353 anon_perms = perm_sys.store.get_user_permissions('anonymous')
354 for perm in anon_perms:
355 tc.notfind(checkbox_value('user2', perm))
356 grant_permission('user2', anon_perms[0])
357
358 tc.formvalue('copyperm', 'cp_subject', 'anonymous')
359 tc.formvalue('copyperm', 'cp_target', 'user2')
360 tc.submit()
361
362 tc.notfind("The subject <em>user2</em> has been granted the "
363 "permission %s\." % anon_perms[0])
364 for perm in anon_perms[1:]:
365 tc.find("The subject user2 has been granted the permission %s\."
366 % perm)
367 tc.find(checkbox_value('user2', perm))
368
369
370 try:
371 env.db_transaction("INSERT INTO permission VALUES (%s,%s)",
372 ('anonymous', 'NOTDEFINED_PERMISSION'))
373 except env.db_exc.IntegrityError:
374 pass
375 env.config.touch()
376 tc.reload()
377 tc.find(checkbox_value('anonymous', 'NOTDEFINED_PERMISSION'))
378 perm_sys = PermissionSystem(env)
379 anon_perms = perm_sys.store.get_user_permissions('anonymous')
380 for perm in anon_perms:
381 tc.notfind(checkbox_value('user3', perm))
382
383 tc.formvalue('copyperm', 'cp_subject', 'anonymous')
384 tc.formvalue('copyperm', 'cp_target', 'user3')
385 tc.submit()
386
387 for perm in anon_perms:
388 msg = grant_msg % ('user3', perm)
389 if perm == 'NOTDEFINED_PERMISSION':
390 tc.notfind(msg)
391 tc.notfind(checkbox_value('user3', perm))
392 else:
393 tc.find(msg)
394 tc.find(checkbox_value('user3', perm))
395 perm_sys.revoke_permission('anonymous', 'NOTDEFINED_PERMISSION')
396
397
398 grant_permission('anonymous', 'PERMISSION_GRANT')
399 grant_permission('user3', 'TRAC_ADMIN')
400 self._tester.logout()
401 self._tester.go_to_admin("Permissions")
402
403 try:
404 tc.formvalue('copyperm', 'cp_subject', 'user3')
405 tc.formvalue('copyperm', 'cp_target', 'user4')
406 tc.submit()
407
408 perm_sys = PermissionSystem(env)
409 for perm in [perm[1] for perm in perm_sys.get_all_permissions()
410 if perm[0] == 'user3'
411 and perm[1] != 'TRAC_ADMIN']:
412 tc.find(grant_msg % ('user4', perm))
413 tc.notfind("The permission TRAC_ADMIN was not granted to user4 "
414 "because users cannot grant permissions they don't "
415 "possess.")
416 finally:
417 self._testenv.revoke_perm('anonymous', 'PERMISSION_GRANT')
418 self._tester.login('admin')
419
420
423 """Check plugin settings."""
424 self._tester.go_to_admin("Plugins")
425 tc.find('Manage Plugins')
426 tc.find('Install Plugin')
427
428
431 """Check permissions required to access Logging panel."""
432 self.test_authorization('/admin/general/plugin', 'TRAC_ADMIN',
433 "Manage Plugins")
434
435
438 """Test for regression of https://trac.edgewall.org/ticket/10752
439 Permissions on the web admin page should be greyed out when they
440 are no longer defined.
441 """
442 env = self._testenv.get_trac_environment()
443 try:
444 env.db_transaction("INSERT INTO permission VALUES (%s,%s)",
445 ('user', 'NOTDEFINED_PERMISSION'))
446 except env.db_exc.IntegrityError:
447 pass
448 env.config.touch()
449
450 self._tester.go_to_admin("Permissions")
451 tc.find('<span class="missing" '
452 'title="NOTDEFINED_PERMISSION is no longer defined">'
453 'NOTDEFINED_PERMISSION</span>')
454 tc.notfind('<input type="checkbox" [^>]+ disabled="disabled"')
455 tc.notfind('<input type="checkbox" [^>]+'
456 'title="You don\'t have permission to revoke this action" '
457 '[^>]+>')
458
459
462 """Test for regression of https://trac.edgewall.org/ticket/11069
463 The permissions list should only be populated with permissions that
464 the user can grant."""
465 self._tester.go_to_front()
466 self._tester.logout()
467 self._tester.login('user')
468 self._testenv.grant_perm('user', 'PERMISSION_GRANT')
469 env = self._testenv.get_trac_environment()
470 user_perms = PermissionSystem(env).get_user_permissions('user')
471 all_actions = PermissionSystem(env).get_actions()
472 try:
473 self._tester.go_to_admin("Permissions")
474 for action in all_actions:
475 option = r"<option>%s</option>" % action
476 if action in user_perms and user_perms[action] is True:
477 tc.find(option)
478 else:
479 tc.notfind(option)
480 finally:
481 self._testenv.revoke_perm('user', 'PERMISSION_GRANT')
482 self._tester.go_to_front()
483 self._tester.logout()
484 self._tester.login('admin')
485
486
488 """Test for regression of https://trac.edgewall.org/ticket/11095
489 The permission is truncated if it overflows the available space (CSS)
490 and the full permission name is shown in the title on hover.
491 """
493 self._tester.go_to_admin("Permissions")
494 tc.find('<span title="MILESTONE_VIEW">MILESTONE_VIEW</span>')
495 tc.find('<span title="WIKI_VIEW">WIKI_VIEW</span>')
496
497
499 """Test for regression of https://trac.edgewall.org/ticket/11117
500 Hint should be shown on the Basic Settings admin panel when pytz is not
501 installed.
502 """
504 self._tester.go_to_admin("Basic Settings")
505 pytz_hint = "Install pytz for a complete list of timezones."
506 from trac.util.datefmt import pytz
507 if pytz is None:
508 tc.find(pytz_hint)
509 else:
510 tc.notfind(pytz_hint)
511
512
514 """Test for regression of https://trac.edgewall.org/ticket/11257
515 Hints should be shown on the Basic Settings admin panel when Babel is not
516 installed.
517 """
519 from trac.util.translation import get_available_locales, has_babel
520
521 babel_hint_lang = "Install Babel for extended language support."
522 babel_hint_date = "Install Babel for localized date formats."
523 catalog_hint = "Message catalogs have not been compiled."
524 language_select = '<select name="default_language">'
525 disabled_language_select = \
526 '<select disabled="disabled" name="default_language" ' \
527 'title="Translations are currently unavailable">'
528
529 self._tester.go_to_admin("Basic Settings")
530 if has_babel:
531 tc.notfind(babel_hint_lang)
532 tc.notfind(babel_hint_date)
533 if get_available_locales():
534 tc.find(language_select)
535 tc.notfind(catalog_hint)
536 else:
537 tc.find(disabled_language_select)
538 tc.find(catalog_hint)
539 else:
540 tc.find(disabled_language_select)
541 tc.find(babel_hint_lang)
542 tc.find(babel_hint_date)
543 tc.notfind(catalog_hint)
544
545
571
572
573 test_suite = functionalSuite
574
575
576 if __name__ == '__main__':
577 unittest.main(defaultTest='test_suite')
578