def filter_subscriptions(self, event, subscriptions): action = '%s_VIEW' % event.realm.upper() for subscription in subscriptions: if event.realm in self.exception_realms: yield subscription continue sid, auth = subscription[1:3] # PermissionCache already takes care of sid = None if not auth: sid = 'anonymous' perm = PermissionCache(self.env, sid) resource_id = get_target_id(event.target) self.log.debug( 'Checking *_VIEW permission on event for resource %s:%s' % (event.realm, resource_id) ) if perm.has_permission(action) and action in perm(event.realm, resource_id): yield subscription else: self.log.debug( "Filtering %s because of %s rule" % (sid, self.__class__.__name__) )
def test_reporter_can_edit_own_ticket_description(self): """Authenticated user can modify description of ticket they reported. The authenticated user must have TICKET_CHGPROP or TICKET_APPEND. """ self.perm_sys.grant_permission('somebody1', 'TICKET_CHGPROP') self.perm_sys.grant_permission('somebody2', 'TICKET_APPEND') ticket1 = self._insert_ticket('somebody1') ticket2 = self._insert_ticket('somebody2') ticket3 = self._insert_ticket('somebody3') action = 'TICKET_EDIT_DESCRIPTION' perm_cache = PermissionCache(self.env, 'somebody1', ticket1.resource) self.assertIn(action, perm_cache) self.assertTrue( self.policy.check_permission(action, perm_cache.username, ticket1.resource, perm_cache)) perm_cache = PermissionCache(self.env, 'somebody2', ticket2.resource) self.assertIn(action, perm_cache) self.assertTrue( self.policy.check_permission(action, perm_cache.username, ticket2.resource, perm_cache)) perm_cache = PermissionCache(self.env, 'somebody3', ticket3.resource) self.assertNotIn(action, perm_cache) self.assertIsNone( self.policy.check_permission(action, perm_cache.username, ticket3.resource, perm_cache))
def _send_index(self, environ, start_response): projects = [] for env_name in os.listdir(self.path): env_path = os.path.join(self.path, env_name) try: env = open_environment(env_path) env_perm = PermissionCache( PermissionSystem(env).get_user_permissions( environ.get("REMOTE_USER", "anonymous"))) if env_perm.has_permission('WIKI_VIEW'): projects.append({ 'name': env.project_name, 'description': env.project_description, # XXX: get rid of the double / in the beginning 'href': construct_url(environ, path_info="/" + env_name), }) except Exception: pass projects.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) start_response("200 OK", [('content-type', 'text/html')]) return self.template.render({"projects": projects}, format='xhtml', template="wsgiplugin.index")
def setUp(self): self.env = EnvironmentStub(default_data=True, enable=['trac.*', 'tractags.*']) self.env.path = tempfile.mkdtemp() self.perms = PermissionSystem(self.env) setup = TagSetup(self.env) # Current tractags schema is setup with enabled component anyway. # Revert these changes for getting default permissions inserted. self._revert_tractags_schema_init() setup.upgrade_environment() self.provider = TicketTagProvider(self.env) self.realm = 'ticket' self.tag_sys = TagSystem(self.env) self.tags = ['tag1', 'tag2'] # Populate tables with initial test data. self._create_ticket(self.tags) # Mock an anonymous request. self.anon_req = Mock() self.anon_req.perm = PermissionCache(self.env) self.req = Mock(authname='editor') self.req.authname = 'editor' self.req.perm = PermissionCache(self.env, username='******')
def match_request(self, req): if req.path_info.startswith('/projects'): path_info = req.path_info[10:] if path_info: self.log.debug('TracForgeDispatch: Starting WSGI relaunch for %s (%s)', path_info, req.method) project = path_info.split('/', 1)[0] # Check that we aren't trying to recurse (possible link loop) if project == os.path.basename(self.env.path): req.redirect(req.href()) # Assert permissions on the desination environment try: project_env = open_environment(os.path.join(os.path.dirname(self.env.path), project)) except IOError: raise TracError('No such project "%s"'%project) authname = RequestDispatcher(self.env).authenticate(req) project_perm = PermissionCache(project_env, authname) project_perm.assert_permission('PROJECT_VIEW') self.log.debug('TracForgeDispath: Access granted, running relaunch') self.log.debug('TracForgeDispatch: Status of req.args is %r', req.__dict__.get('args', 'NOT FOUND')) #self.log.debug('TracForgeDispatch: wsgi.input contains %s', req.read()) self._send_project(req, path_info) self.log.debug('TracForgeDispatch: Relaunch completed, terminating request') self.log.debug('TracForgeDispatch: Response was %r', req._response) req._tf_print = True raise RequestDone, 'request done'
def test_can_edit_ticket_if_he_can_create_referenced_tickets(self): self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm_cache = PermissionCache(self.env, name_team_member) story = self.teh.create_ticket(Type.USER_STORY) self.assert_true(perm_cache.has_permission(Action.TICKET_EDIT_PAGE_ACCESS, story.resource)) self.assert_false(perm_cache.has_permission(Action.TICKET_EDIT, story.resource))
def test_get_taggable_realms(self): class HiddenTagProvider(tractags.api.DefaultTagProvider): implements(IPermissionRequestor) realm = 'hidden' # IPermissionRequestor method def get_permission_actions(self): return ['TEST_VIEW'] # ITagProvider method overwrite def check_permission(self, perm, action): """Somewhat inaccessible tag provider.""" return perm.has_permission('TEST_VIEW') all_realms = set(['hidden', 'ticket', 'wiki']) # Mock an anonymous request. perm = PermissionCache(self.env) self.assertEquals(all_realms - set(['hidden']), self.tag_s.get_taggable_realms(perm)) self.perms.grant_permission('testuser', 'TEST_VIEW') perm = PermissionCache(self.env, 'testuser') self.assertEquals(all_realms, self.tag_s.get_taggable_realms(perm)) # Get realms unconditionally. self.assertEquals(all_realms, self.tag_s.get_taggable_realms())
def setUp(self): self.env = EnvironmentStub( enable=['trac.*', 'tractags.*']) self.env.path = tempfile.mkdtemp() self.db = self.env.get_db_cnx() setup = TagSetup(self.env) # Current tractags schema is setup with enabled component anyway. # Revert these changes for getting a clean setup. self._revert_tractags_schema_init() setup.upgrade_environment(self.db) self.tag_s = TagSystem(self.env) self.tag_rh = TagRequestHandler(self.env) perms = PermissionSystem(self.env) # Revoke default permissions, because more diversity is required here. perms.revoke_permission('anonymous', 'TAGS_VIEW') perms.revoke_permission('authenticated', 'TAGS_MODIFY') perms.grant_permission('reader', 'TAGS_VIEW') perms.grant_permission('writer', 'TAGS_MODIFY') perms.grant_permission('admin', 'TAGS_ADMIN') self.anonymous = PermissionCache(self.env) self.reader = PermissionCache(self.env, 'reader') self.writer = PermissionCache(self.env, 'writer') self.admin = PermissionCache(self.env, 'admin') self.href = Href('/trac') self.abs_href = Href('http://example.org/trac')
def match(self, message): reporter = emailaddr2user(self.env, message['from']) reply_to_ticket = ReplyToTicket(self.env) perm = PermissionCache(self.env, reporter) if not perm.has_permission('TICKET_ADD_HOURS'): return False return bool(reply_to_ticket.ticket(message))
def test_meta_action_granted(self): resource = Resource('wiki', 'UserPage') self.assertEquals( self.check('WIKI_DELETE', 'user', resource, PermissionCache(self.env, username='******')), True) self.assertEquals( self.check('WIKI_DELETE', 'other', resource, PermissionCache(self.env, username='******')), None)
def test_edit_description_action_is_scoped_as_well(self): self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm = PermissionCache(self.env, name_team_member) requirement = self.teh.create_ticket(Type.REQUIREMENT) requirement_resource = requirement.resource self.assert_false( perm.has_permission(Action.TICKET_EDIT_DESCRIPTION, requirement_resource))
def ticket_changed(self, ticket, comment, author, old_values): """Called when a ticket is modified. `old_values` is a dictionary containing the previous values of the fields that have changed. """ perm = PermissionCache(self.env, author) if perm.has_permission('TICKET_ADD_HOURS'): self.add_hours_by_comment(comment, ticket.id, author)
def test_get_admin_panels(self): provider = BuildConfigurationsAdminPageProvider(self.env) req = Mock(perm=PermissionCache(self.env, 'joe')) self.assertEqual([('bitten', 'Builds', 'configs', 'Configurations')], list(provider.get_admin_panels(req))) PermissionSystem(self.env).revoke_permission('joe', 'BUILD_MODIFY') req = Mock(perm=PermissionCache(self.env, 'joe')) self.assertEqual([], list(provider.get_admin_panels(req)))
def test_can_edit_ticket_if_he_can_create_referenced_tickets(self): self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm_cache = PermissionCache(self.env, name_team_member) story = self.teh.create_ticket(Type.USER_STORY) self.assert_true( perm_cache.has_permission(Action.TICKET_EDIT_PAGE_ACCESS, story.resource)) self.assert_false( perm_cache.has_permission(Action.TICKET_EDIT, story.resource))
def test_get_admin_panels(self): provider = BuildMasterAdminPageProvider(self.env) req = Mock(perm=PermissionCache(self.env, 'joe')) self.assertEqual([('bitten', 'Builds', 'master', 'Master Settings')], list(provider.get_admin_panels(req))) PermissionSystem(self.env).revoke_permission('joe', 'BUILD_ADMIN') req = Mock(perm=PermissionCache(self.env, 'joe')) self.assertEqual([], list(provider.get_admin_panels(req)))
def test_can_edit_ticket_for_custom_types(self): custom_type_name = 'MaintenanceTask' self._create_custom_ticket_type(custom_type_name, [Key.COMPONENT]) permission_name = 'CREATE_' + custom_type_name.upper() self.teh.grant_permission(name_team_member, permission_name) self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm_cache = PermissionCache(self.env, name_team_member) ticket = self.teh.create_ticket(custom_type_name) self.assert_true(perm_cache.has_permission(Action.TICKET_EDIT, ticket.resource)) self.assert_true(perm_cache.has_permission(Action.TICKET_EDIT_PAGE_ACCESS, ticket.resource))
def setUp(self): self.env = EnvironmentStub(default_data=True) self.perm_sys = PermissionSystem(self.env) self.ctlr = TicketSystem(self.env).action_controllers[0] self.req1 = Mock(authname='user1', args={}, perm=PermissionCache(self.env, 'user1')) self.req2 = Mock(authname='user2', args={}, perm=PermissionCache(self.env, 'user2')) self.ticket = Ticket(self.env) self.ticket['status'] = 'invalid' self.ticket.insert()
def is_authorised(authname, perms, env, permission=None, list_permission='PROJECT_ACCESS'): if not authname: authname = 'anonymous' perms = PermissionCache(env, authname) if not perms.has_permission(list_permission): return False if permission: return perms.has_permission(permission) return True
def watch_hours(self, ticket): def readTicketValue(name, tipe, default=0): if ticket.values.has_key(name): return tipe(ticket.values[name] or default) else: cursor = self.env.get_db_cnx().cursor() cursor.execute( "SELECT * FROM ticket_custom where ticket=%s and name=%s", (ticket.id, name)) val = cursor.fetchone() if val: return tipe(val[2] or default) return default hours = readTicketValue("hours", convertfloat) totalHours = readTicketValue("totalhours", convertfloat) db = self.env.get_db_cnx() ticket_id = ticket.id cl = ticket.get_changelog() self.log.debug("found hours: " + str(hours)) #self.log.debug("Dir_ticket:"+str(dir(ticket))) #self.log.debug("ticket.values:"+str(ticket.values)) #self.log.debug("changelog:"+str(cl)) most_recent_change = None if cl: most_recent_change = cl[-1] change_time = most_recent_change[0] author = most_recent_change[1] else: change_time = ticket.time_created author = ticket.values["reporter"] self.log.debug("Checking permissions") perm = PermissionCache(self.env, author) if not perm or not perm.has_permission("TIME_RECORD"): self.log.debug( "Skipping recording because no permission to affect time") if hours != 0: tup = (ticket_id, author, change_time, "hours") self.log.debug("deleting ticket change %s %s %s %s" % tup) try: delete_ticket_change(self, ticket_id, author, change_time, "hours") except Exception, e: self.log.debug("FAIL: %s" % e) self.log.debug("hours change deleted") return
def test_can_edit_ticket_for_custom_types(self): custom_type_name = 'MaintenanceTask' self._create_custom_ticket_type(custom_type_name, [Key.COMPONENT]) permission_name = 'CREATE_' + custom_type_name.upper() self.teh.grant_permission(name_team_member, permission_name) self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm_cache = PermissionCache(self.env, name_team_member) ticket = self.teh.create_ticket(custom_type_name) self.assert_true( perm_cache.has_permission(Action.TICKET_EDIT, ticket.resource)) self.assert_true( perm_cache.has_permission(Action.TICKET_EDIT_PAGE_ACCESS, ticket.resource))
def match_request(self, req): if req.path_info.startswith('/projects/'): path_info = req.path_info[10:].lstrip('/') if path_info: self.log.debug( 'TracForgeDispatch: Starting WSGI relaunch for %s (%s)', path_info, req.method) self.log.debug('SN = %s PI = %s', req.environ['SCRIPT_NAME'], req.environ['PATH_INFO']) project_name = path_info.split('/', 1)[0] # Check that we aren't trying to recurse (possible link loop) if project_name == os.path.basename(self.env.path): req.redirect(req.href()) project = Project(self.env, project_name) # Assert permissions on the desination environment if not project.exists: raise TracError('No such project "%s"', project.name) if not project.valid: raise TracError('Project %s is invalid:\n%s', project.name, project.env.exc) # Check that we have permissions in the desired project authname = RequestDispatcher(self.env).authenticate(req) project_perm = PermissionCache(project.env, authname) project_perm.require('PROJECT_LIST') start_response = req._start_response environ = copy.copy(req.environ) # Setup the environment variables environ['SCRIPT_NAME'] = req.href.projects(project.name) environ['PATH_INFO'] = path_info[len(project.name):] environ['trac.env_path'] = project.env_path if 'TRAC_ENV' in environ: del environ['TRAC_ENV'] if 'TRAC_ENV_PARENT_DIR' in environ: del environ['TRAC_ENV_PARENT_DIR'] if 'trac.env_parent' in environ: del environ['trac.env_parent_dir'] environ['tracforge_master_link'] = req.href.projects() # Remove mod_python options to avoid conflicts if 'mod_python.subprocess_env' in environ: del environ['mod_python.subprocess_env'] if 'mod_python.options' in environ: del environ['mod_python.options'] req._response = dispatch_request(environ, start_response) raise RequestDone
def filter_subscriptions(self, event, subscriptions): action = '%s_VIEW'%event.realm.upper() for subscription in subscriptions: sid, auth = subscription[1:3] # PermissionCache already takes care of sid = None if not auth: sid = 'anonymous' perm = PermissionCache(self.env, sid) if event.realm in self.exception_realms or perm.has_permission(action): yield subscription else: self.log.debug( "Filtering %s with realm %s because of rule: DefaultPermissionFilter"\ % (sid, event.realm) )
def test_available_actions_isolation(self): # Grant TICKET_CREATE in product environment ... self.perm.grant_permission('anonymous', 'TICKET_CREATE') self.req.perm = PermissionCache(self.env) self.assertEqual(['leave', 'reopen'], self._get_actions({'status': 'closed'})) # ... but no perms in global environment self.req.perm = PermissionCache(self.global_env) product_env = self.env try: self.env = self.global_env self.assertEqual(['leave'], self._get_actions({'status': 'closed'})) finally: self.env = product_env
def setUp(self): tmpdir = os.path.realpath(tempfile.gettempdir()) self.env = EnvironmentStub(enable=['trac.*', AuthzPolicy], path=tmpdir) self.env.config.set('trac', 'permission_policies', 'AuthzPolicy, DefaultPermissionPolicy') self.env.config.set('ticket', 'restrict_owner', True) self.perm_sys = PermissionSystem(self.env) self.env.insert_known_users([ ('user1', '', ''), ('user2', '', ''), ('user3', '', ''), ('user4', '', '') ]) self.perm_sys.grant_permission('user1', 'TICKET_MODIFY') self.perm_sys.grant_permission('user2', 'TICKET_VIEW') self.perm_sys.grant_permission('user3', 'TICKET_MODIFY') self.perm_sys.grant_permission('user4', 'TICKET_MODIFY') self.authz_file = os.path.join(tmpdir, 'trac-authz-policy') create_file(self.authz_file) self.env.config.set('authz_policy', 'authz_file', self.authz_file) self.ctlr = TicketSystem(self.env).action_controllers[0] self.req1 = Mock(authname='user1', args={}, perm=PermissionCache(self.env, 'user1')) self.ticket = Ticket(self.env) self.ticket['status'] = 'new' self.ticket.insert()
def setUp(self): self.env = EnvironmentStub(enable=[ 'trac.*', 'acct_mgr.api.*', 'acct_mgr.admin.*', 'acct_mgr.db.*', 'acct_mgr.register.*', 'acct_mgr.pwhash.HtDigestHashMethod', 'acct_mgr.tests.admin.BadCheck', 'acct_mgr.tests.admin.DummyCheck' ]) self.env.path = tempfile.mkdtemp() self.perm = PermissionSystem(self.env) # Create a user reference in the permission system. self.perm.grant_permission('admin', 'ACCTMGR_ADMIN') # Prepare a generic request object for admin actions. self.req = Mock(authname='admin', method='GET', args=dict(), abs_href=self.env.abs_href, chrome=dict(notices=[], warnings=[]), href=self.env.abs_href, locale='', redirect=lambda x: None, session=dict(), tz='') self.req.perm = PermissionCache(self.env, 'admin') self.acctmgr = AccountManager(self.env)
def setUp(self): self.env = EnvironmentStub(default_data=True, enable=['trac.*', 'tractags.*']) self.env.path = tempfile.mkdtemp() self.perms = PermissionSystem(self.env) self.db = self.env.get_db_cnx() setup = TagSetup(self.env) # Current tractags schema is setup with enabled component anyway. # Revert these changes for getting default permissions inserted. self._revert_tractags_schema_init() setup.upgrade_environment(self.db) self.provider = TicketTagProvider(self.env) self.realm = 'ticket' self.tag_sys = TagSystem(self.env) self.tags = ['tag1'] cursor = self.db.cursor() # Populate table with initial test data, not synced with tickets yet. cursor.execute(""" INSERT INTO tags (tagspace, name, tag) VALUES ('ticket', '1', 'deleted')""") self.realm = 'ticket' self._create_ticket(self.tags) self.req = Mock() # Mock an anonymous request. self.req.perm = PermissionCache(self.env)
def test_create(self): _redirect_url = '' def redirect(url): _redirect_url = url raise RequestDone req = Mock(perm=PermissionCache(self.env, 'admin'), authname='admin', chrome={}, href=Href('/'), redirect=redirect, method='POST', args={ 'add': True, 'name': "test", 'type': "textarea", 'label': "testing", 'format': "wiki", 'row': '9', 'columns': '42' }) try: self.plugin.render_admin_panel(req, 'ticket', 'customfields', None) except RequestDone, e: self.assertEquals( sorted(list(self.env.config.options('ticket-custom'))), [(u'test', u'textarea'), (u'test.cols', u'60'), (u'test.format', u'wiki'), (u'test.label', u'testing'), (u'test.options', u''), (u'test.order', u'1'), (u'test.rows', u'5'), (u'test.value', u'')])
def test_edit_optional_select(self): self.test_add_optional_select() self.assertEquals('select', self.env.config.get('ticket-custom', 'test')) _redirect_url = '' def redirect(url): _redirect_url = url raise RequestDone req = Mock(perm=PermissionCache(self.env, 'admin'), authname='admin', chrome={}, href=Href('/'), redirect=redirect, method='POST', args={ 'save': True, 'name': u'test', 'label': u'testing', 'type': u'select', 'value': u'', 'options': u'\r\none\r\ntwo' }) try: self.plugin.render_admin_panel(req, 'ticket', 'customfields', 'test') except RequestDone, e: self.assertEquals( sorted(list(self.env.config.options('ticket-custom'))), [(u'test', u'select'), (u'test.label', u'testing'), (u'test.options', u'|one|two'), (u'test.order', u'2'), (u'test.value', u'')])
def test_order_with_mismatched_keys(self): # http://trac-hacks.org/ticket/11540 self.api.create_custom_field({ 'name': u'one', 'format': 'plain', 'value': '', 'label': u'One', 'type': u'text', 'order': 1 }) def redirect(url): raise RequestDone req = Mock(perm=PermissionCache(self.env, 'admin'), authname='admin', chrome={}, href=Href('/'), redirect=redirect, method='POST', args={ 'apply': True, 'order_two': '1' }) try: self.plugin.render_admin_panel(req, 'ticket', 'customfields', None) except RequestDone, e: pass
def test_apply_optional_select(self): # Reuse the added custom field that test verified to work self.test_add_optional_select() self.assertEquals('select', self.env.config.get('ticket-custom', 'test')) # Now check that details are maintained across order change # that reads fields, deletes them, and creates them again # http://trac-hacks.org/ticket/1834#comment:5 _redirect_url = '' def redirect(url): _redirect_url = url raise RequestDone req = Mock(perm=PermissionCache(self.env, 'admin'), authname='admin', chrome={}, href=Href('/'), redirect=redirect, method='POST', args={ 'apply': True, 'order_test': '2' }) try: self.plugin.render_admin_panel(req, 'ticket', 'customfields', None) except RequestDone, e: self.assertEquals( sorted(list(self.env.config.options('ticket-custom'))), [(u'test', u'select'), (u'test.label', u'testing'), (u'test.options', u'|one|two'), (u'test.order', u'2'), (u'test.value', u'')])
def test_available_actions_no_perms(self): self.req.perm = PermissionCache(self.env) self.assertEqual(['leave'], self._get_actions({'status': 'new'})) self.assertEqual(['leave'], self._get_actions({'status': 'assigned'})) self.assertEqual(['leave'], self._get_actions({'status': 'accepted'})) self.assertEqual(['leave'], self._get_actions({'status': 'reopened'})) self.assertEqual(['leave'], self._get_actions({'status': 'closed'}))
def setUp(self): self.env = EnvironmentStub(default_data=True) self.perm_sys = PermissionSystem(self.env) self.ctlr = TicketSystem(self.env).action_controllers[0] self.ticket = Ticket(self.env) self.ticket['status'] = 'new' self.ticket.insert() with self.env.db_transaction as db: for user in ('user1', 'user2', 'user3', 'user4'): db("INSERT INTO session VALUES (%s, %s, %s)", (user, 1, 0)) permissions = [ ('user1', 'TICKET_EDIT_CC'), ('user2', 'TICKET_EDIT_CC'), ('user2', 'TICKET_BATCH_MODIFY'), ('user3', 'TICKET_ADMIN'), ('user4', 'TICKET_VIEW'), ('user1', 'group1'), ('user2', 'group1'), ('user2', 'group2'), ('user3', 'group2'), ('user4', 'group3') ] for perm in permissions: self.perm_sys.grant_permission(*perm) self.req = Mock(authname='user1', args={}, perm=PermissionCache(self.env, 'user0')) self.expected = """\
def test_process_edit_platform(self): BuildConfig(self.env, name='foo', label='Foo', path='branches/foo', active=True).insert() platform = TargetPlatform(self.env, config='foo', name='any') platform.insert() req = Mock(method='GET', chrome={}, href=Href('/'), perm=PermissionCache(self.env, 'joe'), args={}) provider = BuildConfigurationsAdminPageProvider(self.env) template_name, data = provider.render_admin_panel( req, 'bitten', 'configs', 'foo/%d' % platform.id) self.assertEqual('bitten_admin_configs.html', template_name) assert 'platform' in data platform = data['platform'] self.assertEqual( { 'id': 1, 'exists': True, 'name': 'any', 'rules': [('', '')], }, platform)
def test_process_remove_platforms_no_selection(self): BuildConfig(self.env, name='foo', label='Foo', path='branches/foo', active=True).insert() platform = TargetPlatform(self.env, config='foo', name='any') platform.insert() redirected_to = [] def redirect(url): redirected_to.append(url) raise RequestDone req = Mock(method='POST', perm=PermissionCache(self.env, 'joe'), abs_href=Href('http://example.org/'), redirect=redirect, authname='joe', args={'remove': ''}) provider = BuildConfigurationsAdminPageProvider(self.env) try: provider.render_admin_panel(req, 'bitten', 'configs', 'foo') self.fail('Expected TracError') except TracError, e: self.assertEqual('No platform selected', e.message)
def test_add_optional_select(self): # http://trac-hacks.org/ticket/1834 _redirect_url = '' def redirect(url): _redirect_url = url raise RequestDone req = Mock(perm=PermissionCache(self.env, 'admin'), authname='admin', chrome={}, href=Href('/'), redirect=redirect, method='POST', args={ 'add': True, 'name': "test", 'type': "select", 'label': "testing", 'options': "\r\none\r\ntwo" }) try: self.plugin.render_admin_panel(req, 'ticket', 'customfields', None) except RequestDone, e: self.assertEquals( sorted(list(self.env.config.options('ticket-custom'))), [(u'test', u'select'), (u'test.label', u'testing'), (u'test.options', u'|one|two'), (u'test.order', u'1'), (u'test.value', u'')])
def watch_hours(self, ticket): def readTicketValue(name, tipe, default=0): if ticket.values.has_key(name): return tipe(ticket.values[name] or default) else: cursor = self.env.get_db_cnx().cursor() cursor.execute("SELECT * FROM ticket_custom where ticket=%s and name=%s" , (ticket.id, name)) val = cursor.fetchone() if val: return tipe(val[2] or default) return default hours = readTicketValue("hours", convertfloat) totalHours = readTicketValue("totalhours", convertfloat) db = self.env.get_db_cnx() ticket_id = ticket.id cl = ticket.get_changelog() self.log.debug("found hours: "+str(hours )); #self.log.debug("Dir_ticket:"+str(dir(ticket))) #self.log.debug("ticket.values:"+str(ticket.values)) #self.log.debug("changelog:"+str(cl)) most_recent_change = None if cl: most_recent_change = cl[-1]; change_time = most_recent_change[0] author = most_recent_change[1] else: change_time = ticket.time_created author = ticket.values["reporter"] self.log.debug("Checking permissions") perm = PermissionCache(self.env, author) if not perm or not perm.has_permission("TIME_RECORD"): self.log.debug("Skipping recording because no permission to affect time") if hours != 0: tup = (ticket_id, author, change_time, "hours") self.log.debug("deleting ticket change %s %s %s %s" % tup) try: delete_ticket_change(self, ticket_id, author, change_time, "hours") except Exception, e: self.log.debug("FAIL: %s" % e) self.log.debug("hours change deleted") return
def match_request(self, req): if req.path_info.startswith("/projects/"): path_info = req.path_info[10:].lstrip("/") if path_info: self.log.debug("TracForgeDispatch: Starting WSGI relaunch for %s (%s)", path_info, req.method) self.log.debug("SN = %s PI = %s", req.environ["SCRIPT_NAME"], req.environ["PATH_INFO"]) project_name = path_info.split("/", 1)[0] # Check that we aren't trying to recurse (possible link loop) if project_name == os.path.basename(self.env.path): req.redirect(req.href()) project = Project(self.env, project_name) # Assert permissions on the desination environment if not project.exists: raise TracError('No such project "%s"', project.name) if not project.valid: raise TracError("Project %s is invalid:\n%s", project.name, project.env.exc) # Check that we have permissions in the desired project authname = RequestDispatcher(self.env).authenticate(req) project_perm = PermissionCache(project.env, authname) project_perm.require("PROJECT_LIST") start_response = req._start_response environ = copy.copy(req.environ) # Setup the environment variables environ["SCRIPT_NAME"] = req.href.projects(project.name) environ["PATH_INFO"] = path_info[len(project.name) :] environ["trac.env_path"] = project.env_path if "TRAC_ENV" in environ: del environ["TRAC_ENV"] if "TRAC_ENV_PARENT_DIR" in environ: del environ["TRAC_ENV_PARENT_DIR"] if "trac.env_parent" in environ: del environ["trac.env_parent_dir"] environ["tracforge_master_link"] = req.href.projects() # Remove mod_python options to avoid conflicts if "mod_python.subprocess_env" in environ: del environ["mod_python.subprocess_env"] if "mod_python.options" in environ: del environ["mod_python.options"] req._response = dispatch_request(environ, start_response) raise RequestDone
def filter_subscriptions(self, event, subscriptions): action = 'ACCTMGR_USER_ADMIN' for subscription in subscriptions: if event.realm != 'acct_mgr': yield subscription continue # Make acct_mgr subscriptions available only for admins. sid, auth = subscription[1:3] # PermissionCache already takes care of sid = None if not auth: sid = 'anonymous' perm = PermissionCache(self.env, sid) if perm.has_permission(action): yield subscription else: self.log.debug( "Filtering %s because of %s rule" % (sid, self.__class__.__name__) )
def process_request(self, req): parent_dir = os.path.dirname(self.env.path) #env_paths = dict([(filename, os.path.join(parent_dir, filename)) # for filename in os.listdir(parent_dir)]) projects = [] for env_name in os.listdir(parent_dir): env_path = os.path.join(parent_dir, env_name) # Don't list this environment if env_path == self.env.path: continue try: env = open_environment(env_path) try: #self.log.debug(env.path) env_perm = PermissionCache(env, req.authname) #self.log.debug(env_perm.perms) if env_perm.has_permission('PROJECT_VIEW'): projects.append({ 'name': env.project_name, 'description': env.project_description, 'href': req.href.projects(env_name), }) except Exception, e: # Only show errors to admins to prevent excessive disclosure if req.perm.has_permission('TRACFORGE_ADMIN'): projects.append({ 'name': env.project_name, 'description': to_unicode(e) }) except Exception, e: if req.perm.has_permission('TRACFORGE_ADMIN'): projects.append({ 'name': env_path, 'description': to_unicode(e), })
def _send_index(self, environ, start_response): projects = [] for env_name in os.listdir(self.path): env_path = os.path.join(self.path, env_name) try: env = open_environment(env_path) env_perm = PermissionCache(PermissionSystem(env).get_user_permissions(environ.get("REMOTE_USER", "anonymous"))) if env_perm.has_permission('WIKI_VIEW'): projects.append({ 'name': env.project_name, 'description': env.project_description, # XXX: get rid of the double / in the beginning 'href': construct_url(environ, path_info="/"+env_name), }) except Exception: pass projects.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) start_response("200 OK", [('content-type', 'text/html')]) return self.template.render({"projects":projects}, format='xhtml', template = "wsgiplugin.index")
def process_request(self, req): raise TracError('How did I get here?') path_info = req.path_info[10:] if path_info: project = path_info.split('/', 1)[0] # Check that we aren't trying to recurse (possible link loop) if project == os.path.basename(self.env.path): req.redirect(req.href()) # Assert permissions on the desination environment project_path = os.path.join(os.path.dirname(self.env.path), project) try: project_env = open_environment(project_path) except IOError: raise TracError('No such project "%s" at %s'% (project,project_path)) project_perm = PermissionCache(project_env, req.authname) project_perm.assert_permission('PROJECT_VIEW') return self._send_project(req, path_info) else: return self._send_index(req)
def test_team_members_can_edit_bugs(self): bug = self.teh.create_ticket(Type.BUG, {Key.SUMMARY: 'A bug'}) self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm = PermissionCache(self.env, name_team_member) self.assert_true(perm.has_permission(Action.TICKET_EDIT, bug.resource))
def edit_user(self, req): """ Handle user edit: view & save """ changes = {} username = req.args.get('username') if not username: add_warning(req, _('Invalid username')) return self.list_users(req) # Load user being edited userstore = get_userstore() user = userstore.getUser(username) if not user: add_warning(req, _('Invalid username (or connection error)')) return self.list_users(req) # Load user who's doing the edit changed_by = userstore.getUser(req.authname) papi = Projects() # Check permissions and redirect to user listing (handy after editing the user) req.perm.require('USER_AUTHOR', Resource('user', id=user.id)) data = req.args data['user'] = user data['author'] = userstore.getUserWhereId(user.author_id) if user.author_id else None data['base_path'] = req.base_path data['dateformats'] = DATEFORMATS data['is_local'] = userstore.is_local(user) data['now'] = datetime.utcnow() data['expired'] = user.expires and ((user.expires - datetime.utcnow()).days < 0) data['states'] = userstore.USER_STATUS_LABELS data['projects'] = papi.get_authored_projects(user) # Add javascript libraries for datepicker and autocomplete add_script(req, 'multiproject/js/jquery-ui.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') add_script(req, 'multiproject/js/multiproject.js') add_script(req, 'multiproject/js/admin_user_edit.js') # If get request show edit if req.method.upper() == 'GET': return 'admin_user_edit.html', data # Close pressed: get back to user listing if req.args.get('close'): return req.redirect(req.href('admin/users/manage')) # Handle save if 'limitexceeded' in req.args: add_warning(req, _('Picture you tried to upload was too big. Try a smaller one')) # Update author if changed author_id = req.args.get('author_id', None) # If id field is empty but name is not: manual input if not author_id and req.args.get('author_text'): add_warning(req, _('Author cannot be found')) return 'admin_user_edit.html', data # Check set reset the author if author_id: author = userstore.getUserWhereId(int(author_id)) if not author: add_warning(req, _('Author cannot be found')) return 'admin_user_edit.html', data # Check if author is valid: has permission to author? perm = PermissionCache(self.env, author.username) if 'USER_AUTHOR' not in perm: add_warning(req, _('User %s cannot work as an author (does not have USER_AUTHOR permissions)' % author)) return self.back(req) user.author_id = author.id changes['author'] = author else: user.author_id = None user.lastName = req.args.get('last') if not user.lastName: add_warning(req, _('Last name required')) return self.back(req) old_mail = user.mail user.mail = req.args.get('email') if not user.mail: add_warning(req, _('Email address required')) return self.back(req) if old_mail != user.mail: changes['email'] = user.mail org_store = CQDEOrganizationStore.instance() # TODO: is this correct? # When changing email, reset organizations to which the user belongs in user.organization_keys = org_store.get_organization_keys(user) or None # Update password if changed password = req.args.get('password') if password: if not userstore.is_local(user): add_warning(req, _("Can't change password for user that uses external authentication method")) return self.back(req) if len(password) < 7: add_warning(req, _("Password must be at least 7 characters long - please provide longer password")) return self.back(req) if password != req.args.get('confirmpw'): add_warning(req, _("Password do not match - please check")) return self.back(req) user.givenName = req.args.get('first') user.mobile = req.args.get('mobile') # Set or reset account expiration date expiration_str = req.args.get('expires', '') if expiration_str: try: # Parse date and set expiration time in the end of the day expires = datetime.strptime(expiration_str, DATEFORMATS['py']) expires += timedelta(hours=23, minutes=59, seconds=59) # If changed if expires != user.expires: user.expires = expires changes['expiration_date'] = user.expires.strftime(DATEFORMATS['py']) except Exception: self.log.exception('Date formatting failed') add_warning(req, _('Non-recognized expiration format')) pass # Remove expiration date elif user.expires: changes['expiration_date'] = 'Never expires' user.expires = None # Update status if set status = int(req.args.get('status', 0)) if status and status in userstore.USER_STATUS_LABELS.keys() and user.status != status: changes['status'] = userstore.USER_STATUS_LABELS[status] user.status = status if req.args.get('removeicon'): user.icon = None else: icon = req.args.get('icon') if not isinstance(icon, unicode) and icon.filename: user.createIcon(req.args.get('icon')) self.log.info('Saving changes to user: %s' % user) ok = userstore.updateUser(user) if ok and password: changes['password'] = password ok = userstore.updatePassword(user, password) if not ok: add_warning(req, _("Could not save changes")) add_notice(req, _("User %s updated" % username)) # Notify user about changes via email? if req.args.get('notify'): data = { 'user':user, 'changed_by':changed_by, 'changes':changes } try: enotify = EmailNotifier(self.env, "Account updated", data) enotify.template_name = 'account_edited.txt' enotify.notify(user.mail) add_notice(req, _("Notified user about the changes")) except TracError: add_warning(req, _("Failed to send email notification - user changed anyway")) # Check if user has still (after modification) permission to modify user # NOTE: req.perm cannot be used here because it is not updated yet resource = Resource('user', id=user.id) perm = PermissionCache(self.env, username=req.authname) if perm.has_permission('USER_AUTHOR', resource): return self.back(req) add_notice(req, _('You have no longer permission to modify the account: %s' % user.username)) return req.redirect(req.href('admin/users/manage'))
def test_no_endless_loop_if_permission_is_checked_with_string_instead_of_resource(self): perm = PermissionCache(self.env, 'foo') perm.has_permission('AGILO_BACKLOG_EDIT', '%s:Sprint Backlog' % Realm.BACKLOG)
def test_edit_description_action_is_scoped_as_well(self): self.teh.grant_permission(name_team_member, Role.TEAM_MEMBER) perm = PermissionCache(self.env, name_team_member) requirement = self.teh.create_ticket(Type.REQUIREMENT) requirement_resource = requirement.resource self.assert_false(perm.has_permission(Action.TICKET_EDIT_DESCRIPTION, requirement_resource))