def test_macro_neighborhood_feeds(): p_nbhd = M.Neighborhood.query.get(name='Projects') p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id) with h.push_context('--init--', 'wiki', neighborhood='Projects'): r = g.markdown_wiki.convert('[[neighborhood_feeds tool_name=wiki]]') assert 'Home modified by' in r, r orig_len = len(r) # Make project private & verify we don't see its new feed items anon = M.User.anonymous() p_test.acl.insert(0, M.ACE.deny( M.ProjectRole.anonymous(p_test)._id, 'read')) ThreadLocalORMSession.flush_all() pg = WM.Page.query.get(title='Home', app_config_id=c.app.config._id) pg.text = 'Change' with h.push_config(c, user=M.User.by_username('test-admin')): pg.commit() r = g.markdown_wiki.convert('[[neighborhood_feeds tool_name=wiki]]') new_len = len(r) assert new_len == orig_len p = BM.BlogPost(title='test me', neighborhood_id=p_test.neighborhood_id) p.text = 'test content' p.state = 'published' p.make_slug() with h.push_config(c, user=M.User.by_username('test-admin')): p.commit() ThreadLocalORMSession.flush_all() with h.push_config(c, user=anon): r = g.markdown_wiki.convert('[[neighborhood_blog_posts]]') assert 'test content' in r
def install_app(self, ep_name, mount_point=None, mount_label=None, ordinal=None, **override_options): App = g.entry_points['tool'][ep_name] with h.push_config(c, project=self): try: mount_point = v.MountPointValidator(App).to_python(mount_point) except fe.Invalid as e: raise exceptions.ToolError(str(e)) if ordinal is None: ordinal = int(self.ordered_mounts(include_hidden=True) [-1]['ordinal']) + 1 options = App.default_options() options['mount_point'] = mount_point options[ 'mount_label'] = mount_label or App.default_mount_label or mount_point options['ordinal'] = int(ordinal) options.update(override_options) cfg = AppConfig( project_id=self._id, tool_name=ep_name.lower(), options=options) app = App(self, cfg) with h.push_config(c, project=self, app=app): session(cfg).flush() app.install(self) return app
def test_start_date(self): stats = USM.UserStats(registration_date=datetime(2012, 04, 01)) self.assertEqual(stats.start_date, datetime(2012, 04, 01)) with h.push_config(config, **{"userstats.start_date": "2013-04-01"}): self.assertEqual(stats.start_date, datetime(2013, 04, 01)) with h.push_config(config, **{"userstats.start_date": "2011-04-01"}): self.assertEqual(stats.start_date, datetime(2012, 04, 01))
def encode(self, o): # ensure_ascii=False forces encode_basestring() to be called instead of # encode_basestring_ascii() and encode_basestring_ascii may likely be c-compiled # and thus not monkeypatchable with h.push_config(self, ensure_ascii=False), \ h.push_config(simplejson.encoder, ESCAPE=escape_pattern_with_lt), \ mock.patch.dict(simplejson.encoder.ESCAPE_DCT, {'<': r'\u003C'}): return original_tg_jsonify_GenericJSON_encode(self, o)
def test_no_capability(self): with h.push_config(config, **{'oauth.can_import_forum': 'some,fake,tokens'}): resp = self.api_post('/rest/p/test/discussion/perform_import', doc=self.json_text) assert resp.status_int == 403 with h.push_config(config, **{'oauth.can_import_forum': self.token('test-admin').api_key}): resp = self.api_post('/rest/p/test/discussion/perform_import', doc=self.json_text) assert resp.status_int == 200
def test_is_password_expired_before(self): before = dt.datetime.utcnow() - dt.timedelta(days=180) before = calendar.timegm(before.timetuple()) with h.push_config(tg.config, **{'auth.pwdexpire.before': str(before)}): assert_false(self.provider.is_password_expired(self.user)) before = dt.datetime.utcnow() - dt.timedelta(days=1) before = calendar.timegm(before.timetuple()) with h.push_config(tg.config, **{'auth.pwdexpire.before': str(before)}): assert_true(self.provider.is_password_expired(self.user))
def test_create_limit(self): self.create_ticket(summary='First ticket') # Set rate limit to unlimit with h.push_config(config, **{'forgetracker.rate_limits': '{}'}): summary = 'Second ticket' self.create_ticket(summary=summary) t = TM.Ticket.query.get(summary=summary) assert_not_equal(t, None) # Set rate limit to 1 in first hour of project with h.push_config(config, **{'forgetracker.rate_limits': '{"3600": 1}'}): summary = 'Third ticket' self.create_ticket(summary=summary, status=429) t = TM.Ticket.query.get(summary=summary) assert_equal(t, None)
def route_email( peer, mailfrom, rcpttos, data): ''' Route messages according to their destination: <topic>@<mount_point>.<subproj2>.<subproj1>.<project>.projects.domain.net gets sent to c.app.handle_message(topic, message) ''' try: msg = mail_util.parse_message(data) except: # pragma no cover log.exception('Parse Error: (%r,%r,%r)', peer, mailfrom, rcpttos) return if mail_util.is_autoreply(msg): log.info('Skipping autoreply message: %s', msg['headers']) return mail_user = mail_util.identify_sender(peer, mailfrom, msg['headers'], msg) with h.push_config(c, user=mail_user): log.info('Received email from %s', c.user.username) # For each of the addrs, determine the project/app and route # appropriately for addr in rcpttos: try: userpart, project, app = mail_util.parse_address(addr) with h.push_config(c, project=project, app=app): if not app.has_access(c.user, userpart): log.info('Access denied for %s to mailbox %s', c.user, userpart) elif not c.app.config.options.get('AllowEmailPosting', True): log.info("Posting from email is not enabled") else: if msg['multipart']: msg_hdrs = msg['headers'] for part in msg['parts']: if part.get('content_type', '').startswith('multipart/'): continue msg = dict( headers=dict(msg_hdrs, **part['headers']), message_id=part['message_id'], in_reply_to=part['in_reply_to'], references=part['references'], filename=part['filename'], content_type=part['content_type'], payload=part['payload']) c.app.handle_message(userpart, msg) else: c.app.handle_message(userpart, msg) except exc.MailError, e: log.error('Error routing email to %s: %s', addr, e) except:
def test_create_page_limit(self): data = { 'text': 'Embrace the Dark Side', 'labels': 'head hunting,dark side' } # Set rate limit to unlimit with h.push_config(tg.config, **{'forgewiki.rate_limits': '{}'}): r = self.api_post(u'/rest/p/test/wiki/page1/', status=200, **data) p = Page.query.get(title='page1') assert_not_equal(p, None) # Set rate limit to 1 in first hour of project with h.push_config(tg.config, **{'forgewiki.rate_limits': '{"3600": 1}'}): r = self.api_post(u'/rest/p/test/wiki/page2/', status=429, **data) p = Page.query.get(title='page2') assert_equal(p, None)
def test_project_redirect(self): with push_config(config, **{'activitystream.enabled': 'false'}): resp = self.app.get('/p/test2/') assert_equal(resp.status_int, 302) assert_equal(resp.location, 'http://localhost/p/test2/admin/') with push_config(config, **{'activitystream.enabled': 'true'}): resp = self.app.get('/p/test2/') assert_equal(resp.status_int, 302) assert_equal(resp.location, 'http://localhost/p/test2/activity/') with push_config(config, **{'activitystream.enabled': 'false'}): self.app.cookies['activitystream.enabled'] = 'true' resp = self.app.get('/p/test2/') assert_equal(resp.status_int, 302) assert_equal(resp.location, 'http://localhost/p/test2/activity/')
def install_app(self, ep_name, mount_point=None, mount_label=None, ordinal=None, **override_options): App = g.entry_points['tool'][ep_name] if not mount_point: base_mount_point = mount_point = App.default_mount_point for x in range(10): if self.app_instance(mount_point) is None: break mount_point = base_mount_point + '-%d' % x if not App.relaxed_mount_points: mount_point = mount_point.lower() if not App.validate_mount_point(mount_point): raise exceptions.ToolError, 'Mount point "%s" is invalid' % mount_point # HACK: reserved url components if mount_point in ('feed', 'index', 'icon', '_nav.json'): raise exceptions.ToolError, ( 'Mount point "%s" is reserved' % mount_point) if self.app_instance(mount_point) is not None: raise exceptions.ToolError, ( 'Mount point "%s" is already in use' % mount_point) assert self.app_instance(mount_point) is None if ordinal is None: ordinal = int(self.ordered_mounts(include_hidden=True)[-1]['ordinal']) + 1 options = App.default_options() options['mount_point'] = mount_point options['mount_label'] = mount_label or App.default_mount_label or mount_point options['ordinal'] = int(ordinal) options.update(override_options) cfg = AppConfig( project_id=self._id, tool_name=ep_name.lower(), options=options) app = App(self, cfg) with h.push_config(c, project=self, app=app): session(cfg).flush() app.install(self) return app
def install_app(self, ep_name, mount_point=None, mount_label=None, ordinal=None, **override_options): App = g.entry_points["tool"][ep_name] if not mount_point: base_mount_point = mount_point = App.default_mount_point for x in range(10): if self.app_instance(mount_point) is None: break mount_point = base_mount_point + "-%d" % x if not h.re_path_portion.match(mount_point): raise exceptions.ToolError, 'Mount point "%s" is invalid' % mount_point # HACK: reserved url components if mount_point in ("feed", "index", "icon", "_nav.json"): raise exceptions.ToolError, ('Mount point "%s" is reserved' % mount_point) if self.app_instance(mount_point) is not None: raise exceptions.ToolError, ('Mount point "%s" is already in use' % mount_point) assert self.app_instance(mount_point) is None if ordinal is None: ordinal = int(self.ordered_mounts(include_hidden=True)[-1]["ordinal"]) + 1 options = App.default_options() options["mount_point"] = mount_point options["mount_label"] = mount_label or App.default_mount_label or mount_point options["ordinal"] = int(ordinal) options.update(override_options) cfg = AppConfig(project_id=self._id, tool_name=ep_name, options=options) app = App(self, cfg) with h.push_config(c, project=self, app=app): session(cfg).flush() app.install(self) return app
def uninstall_app(self, mount_point): app = self.app_instance(mount_point) if app is None: return if self.support_page == app.config.options.mount_point: self.support_page = '' with h.push_config(c, project=self, app=app): app.uninstall(self)
def test_count_loc(self, unified_diff): stats = USM.UserStats() newcommit = mock.Mock( parent_ids=['deadbeef'], diffs=mock.Mock( changed=[mock.MagicMock()], copied=[mock.MagicMock()], added=[mock.MagicMock()], ), ) unified_diff.return_value = ['+++', '---', '+line'] newcommit.tree.get_blob_by_path.return_value = mock.MagicMock() newcommit.tree.get_blob_by_path.return_value.__iter__.return_value = [ 'one'] newcommit.repo.commit( ).tree.get_blob_by_path.return_value = mock.MagicMock() newcommit.repo.commit().tree.get_blob_by_path.return_value.__iter__.return_value = [ 'two'] commit_datetime = datetime.utcnow() project = mock.Mock( trove_topic=[], trove_language=[], ) stats.addCommit(newcommit, commit_datetime, project) self.assertEqual(stats.general[0].commits[0], {'lines': 3, 'number': 1, 'language': None}) unified_diff.reset_mock() with h.push_config(config, **{'userstats.count_lines_of_code': 'false'}): stats.addCommit(newcommit, commit_datetime, project) self.assertEqual(stats.general[0].commits[0], {'lines': 3, 'number': 2, 'language': None}) unified_diff.assert_not_called()
def test(self): # Keys are number of seconds, values are max number allowed until that time period is reached with h.push_config(h.tg.config, **{self.key_comment: self.rate_limits}): now = datetime.utcnow() start_date = now - timedelta(seconds=30) h.rate_limit(self.key_comment, 0, start_date) with assert_raises(exc.RatelimitError): h.rate_limit(self.key_comment, 1, start_date) start_date = now - timedelta(seconds=61) h.rate_limit(self.key_comment, 1, start_date) h.rate_limit(self.key_comment, 2, start_date) with assert_raises(exc.RatelimitError): h.rate_limit(self.key_comment, 3, start_date) start_date = now - timedelta(seconds=86301) h.rate_limit(self.key_comment, 19, start_date) with assert_raises(exc.RatelimitError): h.rate_limit(self.key_comment, 20, start_date) start_date = now - timedelta(seconds=86401) h.rate_limit(self.key_comment, 21, start_date) h.rate_limit(self.key_comment, 49, start_date) with assert_raises(exc.RatelimitError): h.rate_limit(self.key_comment, 50, start_date)
def test_project_rate_limit_admin(self): # Set rate limit to unlimit with h.push_config(config, **{'project.rate_limits': '{}'}): r = self.app.post('/p/register', params=dict(project_unixname='rateproject1', project_name='Rate project1', project_description='', neighborhood='Projects'), antispam=True, extra_environ=dict(username='******'), status=302) assert '/p/rateproject1/admin' in r.location # Set rate limit to 1 in first hour of user account with h.push_config(config, **{'project.rate_limits': '{"3600": 1}'}): r = self.app.post('/p/register', params=dict(project_unixname='rateproject2', project_name='Rate project2', project_description='', neighborhood='Projects'), antispam=True, extra_environ=dict(username='******')) assert '/p/rateproject2/admin' in r.location
def test_ip_address_header_not_set(): req = Mock() req.remote_addr = '1.2.3.4' req.headers = {} with h.push_config(config, **{'ip_address_header': 'X_FORWARDED_FOR'}): assert_equal(utils.ip_address(req), '1.2.3.4')
def test_check_phone_verification_disabled(self, g): g.phone_service = Mock(spec=phone.PhoneService) with h.push_config(tg.config, **{'project.verify_phone': 'false'}): result = self.p.check_phone_verification( self.user, 'request-id', '1111', 'hash') assert_false(g.phone_service.check.called) assert_equal(result, {'status': 'ok'})
def test_hotcopy(self, post_event, clone_from): with h.push_config(tg.config, **{'scm.git.hotcopy': 'True'}): repo = GM.Repository( name='testgit.git', fs_path=g.tmpdir + '/', url_path='/test/', tool='git', status='creating') repo.app.config.options['hotcopy'] = True repo_path = pkg_resources.resource_filename( 'forgegit', 'tests/data/testgit.git') dirname = os.path.join(repo.fs_path, repo.name) if os.path.exists(dirname): shutil.rmtree(dirname) repo.init() repo._impl.clone_from(repo_path) assert not clone_from.called assert len(list(repo.log())) assert os.path.exists( os.path.join(g.tmpdir, 'testgit.git/hooks/update')) assert os.path.exists( os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive-user')) assert os.path.exists( os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive')) assert os.stat( os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive'))[0] & stat.S_IXUSR with open(os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive')) as f: c = f.read() self.assertIn( 'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n', c) self.assertIn('exec $DIR/post-receive-user\n', c) shutil.rmtree(dirname)
def test_send_no_configured_webhooks(self, send_webhook): self.wh.delete() session(self.wh).flush(self.wh) sender = RepoPushWebhookSender() with h.push_config(c, app=self.git): sender.send(dict(arg1=1, arg2=2)) assert_equal(send_webhook.post.call_count, 0)
def test_events(self, post_event): setup_trove_categories() # Create event cfg = {"trovecategories.enableediting": "true"} with h.push_config(config, **cfg): r = self.app.post("/categories/create/", params=dict(categoryname="test")) category_id = post_event.call_args[0][1] assert_true(isinstance(category_id, int)) assert_equals(post_event.call_args[0][0], "trove_category_created") category = M.TroveCategory.query.get(trove_cat_id=category_id) # Update event category.fullname = "test2" session(M.TroveCategory).flush() edited_category_id = post_event.call_args[0][1] assert_true(isinstance(edited_category_id, int)) assert_equals(edited_category_id, category_id) assert_equals(post_event.call_args[0][0], "trove_category_updated") # Delete event M.TroveCategory.delete(category) session(M.TroveCategory).flush() deleted_category_id = post_event.call_args[0][1] assert_true(isinstance(deleted_category_id, int)) assert_equals(deleted_category_id, category_id) assert_equals(post_event.call_args[0][0], "trove_category_deleted")
def test_global_nav_links_present(self): with h.push_config(config, **self._set_config()): response = self.app.get('/').follow() nav_left = response.html.find(*self.global_nav_pattern) assert len(nav_left.findAll('a')) == 1 assert nav_left.a.get('href') == self.nav_data['url'] assert nav_left.a.text == self.nav_data['title']
def fork(self, project_id=None, mount_point=None, mount_label=None): # this shows the form and handles the submission security.require_authenticated() if not c.app.forkable: raise exc.HTTPNotFound from_repo = c.app.repo ThreadLocalORMSession.flush_all() ThreadLocalORMSession.close_all() from_project = c.project to_project = M.Project.query.get(_id=ObjectId(project_id)) mount_label = mount_label or '%s - %s' % (c.project.name, c.app.config.options.mount_label) mount_point = (mount_point or from_project.shortname) if request.method != 'POST' or not mount_point: return dict(from_repo=from_repo, user_project=c.user.private_project(), mount_point=mount_point, mount_label=mount_label) else: with h.push_config(c, project=to_project): if not to_project.database_configured: to_project.configure_project(is_user_project=True) security.require(security.has_access(to_project, 'admin')) try: to_project.install_app( ep_name=from_repo.tool_name, mount_point=mount_point, mount_label=mount_label, cloned_from_project_id=from_project._id, cloned_from_repo_id=from_repo._id) redirect(to_project.url()+mount_point+'/') except exc.HTTPRedirection: raise except Exception, ex: flash(str(ex), 'error') redirect(request.referer)
def test_macro_gittip_button(): p_nbhd = M.Neighborhood.query.get(name='Projects') p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id) with h.push_config(c, project=p_test): r = g.markdown_wiki.convert('[[gittip_button username=test]]') assert_equal( r, u'<div class="markdown_content"><p><iframe height="22pt" src="https://www.gittip.com/test/widget.html" style="border: 0; margin: 0; padding: 0;" width="48pt"></iframe></p>\n</div>')
def configure(self, **kw): """Handle POST to delete the Application or update its ``config.options``. """ with h.push_config(c, app=self.app): require_access(self.app, 'configure') is_admin = self.app.config.tool_name == 'admin' if kw.pop('delete', False): if is_admin: flash('Cannot delete the admin tool, sorry....') redirect('.') c.project.uninstall_app(self.app.config.options.mount_point) redirect('..') for opt in self.app.config_options: if opt in Application.config_options: # skip base options (mount_point, mount_label, ordinal) continue val = kw.get(opt.name, '') if opt.ming_type == bool: val = asbool(val or False) elif opt.ming_type == int: val = asint(val or 0) self.app.config.options[opt.name] = val if is_admin: # possibly moving admin mount point redirect('/' + c.project._id + self.app.config.options.mount_point + '/' + self.app.config.options.mount_point + '/') else: redirect(request.referer)
def process(self, **kw): """ Override and expose this to handle a project import. This should at a minimum create the stub project with the appropriate tools installed and redirect to the new project, presumably with a message indicating that some data will not be available immediately. """ try: with h.push_config(config, **{'project.verify_phone': 'false'}): c.project = self.neighborhood.register_project( kw['project_shortname'], project_name=kw['project_name']) except exceptions.ProjectOverlimitError: flash("You have exceeded the maximum number of projects you are allowed to create", 'error') redirect('.') except exceptions.ProjectRatelimitError: flash("Project creation rate limit exceeded. Please try again later.", 'error') redirect('.') except Exception: log.error('error registering project: %s', kw['project_shortname'], exc_info=True) flash('Internal Error. Please try again later.', 'error') redirect('.') self.after_project_create(c.project, **kw) tools = aslist(kw.get('tools')) for importer_name in tools: ToolImporter.by_name(importer_name).post(**kw) M.AuditLog.log('import project from %s' % self.source) flash('Welcome to the %s Project System! ' 'Your project data will be imported and should show up here shortly.' % config['site_name']) redirect(c.project.script_name + 'admin/overview')
def test_phone_verified_project_admin(self, has_access): has_access.return_value.return_value = False with h.push_config(tg.config, **{'project.verify_phone': 'true'}): self.user.set_projects([Mock()]) assert_false(self.p.phone_verified(self.user, self.nbhd)) self.user.set_projects([Mock(neighborhood_id=self.nbhd._id)]) assert_true(self.p.phone_verified(self.user, self.nbhd))
def import_tool( self, project, user, project_name=None, mount_point=None, mount_label=None, user_name=None, tool_option=None, **kw): """ Import a GitHub wiki into a new Wiki Allura tool. """ project_name = "%s/%s" % (user_name, project_name) extractor = GitHubProjectExtractor(project_name, user=user) wiki_avail = extractor.has_wiki() if not wiki_avail: return self.github_wiki_url = extractor.get_page_url( 'wiki_url').replace('.wiki', '/wiki') self.app = project.install_app( "Wiki", mount_point=mount_point or 'wiki', mount_label=mount_label or 'Wiki', import_id={ 'source': self.source, 'project_name': project_name, } ) with_history = tool_option == 'import_history' ThreadLocalORMSession.flush_all() self.github_markdown_converter = GitHubMarkdownConverter( user_name, project_name) try: M.session.artifact_orm_session._get().skip_mod_date = True with h.push_config(c, app=self.app): try: wiki_url = extractor.get_page_url('wiki_url') self.import_pages(wiki_url, history=with_history) except git.GitCommandError: log.error( 'Unable to clone GitHub wiki: ' 'wiki_url=%s; ' 'wiki_avail=%s; ' 'avail_url=%s', wiki_url, wiki_avail, extractor.get_page_url('project_info'), exc_info=True) raise ThreadLocalORMSession.flush_all() M.AuditLog.log( 'import tool %s from %s on %s' % ( self.app.config.options.mount_point, project_name, self.source), project=project, user=user, url=self.app.url) g.post_event('project_updated') return self.app except Exception: h.make_app_admin_only(self.app) raise finally: M.session.artifact_orm_session._get().skip_mod_date = False
def test_clone_url(self): assert_equal( self.repo.clone_url('file', 'nobody'), '/srv/git/p/test/testgit') with h.push_config(self.repo.app.config.options, external_checkout_url='https://[email protected]/'): assert_equal( self.repo.clone_url('https', 'user'), 'https://[email protected]/')
def test_hide_private_info(): assert_equals(h.hide_private_info(None), None) assert_equals(h.hide_private_info(''), '') assert_equals(h.hide_private_info('foo bar [email protected]'), 'foo bar baz@...') assert_equals(h.hide_private_info('some <*****@*****.**>\nor [email protected]'), 'some <1@...>\nor asdf+asdf.f@...') with h.push_config(h.tg.config, hide_private_info=False): assert_equals(h.hide_private_info('foo bar [email protected]'), 'foo bar [email protected]')
def configure(self, channel=None): with h.push_config(c, app=self.app): require_access(self.app, 'configure') chan = CM.ChatChannel.query.get( project_id=self.app.config.project_id, app_config_id=self.app.config._id) chan.channel = channel flash('Chat options updated') super(AdminController, self).configure(channel=channel)
def test_macro_download_button(): p_nbhd = M.Neighborhood.query.get(name='Projects') p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id) with h.push_config(c, project=p_test): r = g.markdown_wiki.convert('[[download_button]]') assert_equal( r, '<div class="markdown_content"><p><span class="download-button-%s" style="margin-bottom: 1em; display: block;"></span></p>\n</div>' % p_test._id)
def test_scm_host_url(self): assert_equal(self.repo.clone_url('rw', 'nobody'), 'svn+ssh://nobody@localhost:8022/scm-repo/p/test/test1/') assert_equal(self.repo.clone_url('https', 'nobody'), 'https://nobody@localhost:8022/scm-repo/p/test/test1/') with h.push_config(self.repo.app.config.options, external_checkout_url='https://[email protected]/'): assert_equal(self.repo.clone_url('https', 'user'), 'https://[email protected]/')
def test_rate_limit_comments(self): with h.push_config(config, **{'allura.rate_limits_per_user': '******'}): for i in range(0, 2): r = self._make_post('This is a post {}'.format(i)) assert 'rate limit exceeded' not in r.body r = self._make_post('This is a post that should fail.') assert 'rate limit exceeded' in r.body
def test_macro_gittip_button(): p_nbhd = M.Neighborhood.query.get(name='Projects') p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id) with h.push_config(c, project=p_test): r = g.markdown_wiki.convert('[[gittip_button username=test]]') assert_equal( r, u'<div class="markdown_content"><p><iframe height="22pt" src="https://www.gittip.com/test/widget.html" style="border: 0; margin: 0; padding: 0;" width="48pt"></iframe></p>\n</div>' )
def test_project_rate_limit(self): # Set rate limit to unlimit with h.push_config(config, **{'project.rate_limits': '{}'}): r = self.app.post('/p/register', params=dict(project_unixname='rateproject1', project_name='Rate project1', project_description='', neighborhood='Projects'), antispam=True, extra_environ=dict(username='******'), status=302) assert '/p/rateproject1/admin' in r.location # Set rate limit to 1 in first hour of user account with h.push_config(config, **{'project.rate_limits': '{"3600": 1}'}): r = self.app.post('/p/register', params=dict(project_unixname='rateproject2', project_name='Rate project2', project_description='', neighborhood='Projects'), antispam=True, extra_environ=dict(username='******')) while isinstance(r.response, HTTPFound): r = r.follow() assert 'Project creation rate limit exceeded. Please try again later.' in r
def upsert_root(self, new_root): p = WM.Page.query.get(app_config_id=self.config._id, title=new_root, deleted=False) if p is None: with h.push_config(c, app=self): p = WM.Page.upsert(new_root) p.viewable_by = ['all'] p.text = self.default_root_page_text() p.commit()
def test_send_limit_reached(self, send_webhook, log): sender = RepoPushWebhookSender() sender.get_payload = Mock() self.wh.enforce_limit = Mock(return_value=False) with h.push_config(c, app=self.git): sender.send(dict(arg1=1, arg2=2)) assert_equal(send_webhook.post.call_count, 0) log.warn.assert_called_once_with( 'Webhook fires too often: %s. Skipping', self.wh)
def test_rate_limit_form(self): with h.push_config(tg.config, **{'forgeblog.rate_limits': '{"3600": 0}'}): r = self.app.get('/blog/new') wf = json.loads(self.webflash(r)) assert_equal(wf['status'], 'error') assert_equal( wf['message'], 'Create/edit rate limit exceeded. Please try again later.')
def upsert_root(self, new_root, notify=True): p = WM.Page.query.get(app_config_id=self.config._id, title=new_root, deleted=False) if p is None: with h.push_config(c, app=self), h.notifications_disabled(c.project, disabled=not notify): p = WM.Page.upsert(new_root) p.viewable_by = ['all'] p.text = self.default_root_page_text() p.commit()
def configure_project(self, users=None, apps=None, is_user_project=False, is_private_project=False): from allura import model as M self.notifications_disabled = True if users is None: users = [c.user] if apps is None: apps = [] if is_user_project: apps += [ ('Wiki', 'wiki', 'Wiki'), ('profile', 'profile', 'Profile'), ] apps += [ ('admin', 'admin', 'Admin'), ('search', 'search', 'Search'), ] if asbool(config.get('activitystream.enabled', False)): apps.append(('activity', 'activity', 'Activity')) with h.push_config(c, project=self, user=users[0]): # Install default named roles (#78) root_project_id = self.root_project._id role_admin = M.ProjectRole.upsert(name='Admin', project_id=root_project_id) role_developer = M.ProjectRole.upsert(name='Developer', project_id=root_project_id) role_member = M.ProjectRole.upsert(name='Member', project_id=root_project_id) role_auth = M.ProjectRole.upsert(name='*authenticated', project_id=root_project_id) role_anon = M.ProjectRole.upsert(name='*anonymous', project_id=root_project_id) # Setup subroles role_admin.roles = [role_developer._id] role_developer.roles = [role_member._id] self.acl = [ ACE.allow(role_developer._id, 'read'), ACE.allow(role_member._id, 'read') ] self.acl += [ M.ACE.allow(role_admin._id, perm) for perm in self.permissions ] self.private = is_private_project for user in users: pr = user.project_role() pr.roles = [role_admin._id] session(self).flush(self) # Setup apps for i, (ep_name, mount_point, label) in enumerate(apps): self.install_app(ep_name, mount_point, label, ordinal=i) self.database_configured = True self.notifications_disabled = False ThreadLocalORMSession.flush_all()
def test_macro_project_admins_one_br(): p_nbhd = M.Neighborhood.query.get(name='Projects') p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id) p_test.add_user(M.User.by_username('test-user'), ['Admin']) ThreadLocalORMSession.flush_all() with h.push_config(c, project=p_test): r = g.markdown_wiki.convert('[[project_admins]]\n[[download_button]]') assert '</a><br/><br/><a href=' not in r, r assert '</a></li><li><a href=' in r, r
def test_send_with_list(self, send_webhook): sender = RepoPushWebhookSender() sender.get_payload = Mock(side_effect=[1, 2]) self.wh.enforce_limit = Mock(return_value=True) with h.push_config(c, app=self.git): sender.send([dict(arg1=1, arg2=2), dict(arg1=3, arg2=4)]) assert_equal(send_webhook.post.call_count, 2) assert_equal(send_webhook.post.call_args_list, [call(self.wh._id, 1), call(self.wh._id, 2)]) assert_equal(self.wh.enforce_limit.call_count, 1)
def test_rate_limit_new_page(self): # Set rate limit to unlimit with h.push_config(config, **{'forgewiki.rate_limits': '{}'}): r = self.app.get('/p/test/wiki/new-page-title/') assert_equal(r.status_int, 302) assert_equal( r.location, 'http://localhost/p/test/wiki/new-page-title/edit') assert_equal(self.webflash(r), '') # Set rate limit to 1 in first hour of project with h.push_config(config, **{'forgewiki.rate_limits': '{"3600": 1}'}): r = self.app.get('/p/test/wiki/new-page-title/') assert_equal(r.status_int, 302) assert_equal(r.location, 'http://localhost/p/test/wiki/') wf = json.loads(self.webflash(r)) assert_equal(wf['status'], 'error') assert_equal( wf['message'], 'Page creation rate limit exceeded. Please try again later.')
def sitemap(self): menu_id = self.config.options.mount_label.title() with h.push_config(c, app=self): pages = [ SitemapEntry(p.title, p.url()) for p in WM.Page.query.find(dict( app_config_id=self.config._id, deleted=False)) ] return [ SitemapEntry(menu_id, '.')[SitemapEntry('Pages')[pages]] ]
def test_create_post_limit_by_project(self): data = { 'title': 'test against limit', 'text': 'test text', 'state': 'published', 'labels': 'label1, label2' } # Set rate limit to 0 in first hour of project with h.push_config(tg.config, **{'forgeblog.rate_limits': '{"3600": 0}'}): self.api_post('/rest/p/test/blog/', status=429, **data)
def test_last_commit_ids_threaded_error(self, _git): with h.push_config(tg.config, lcd_thread_chunk_size=1, lcd_timeout=2): repo_dir = pkg_resources.resource_filename( 'forgegit', 'tests/data/testrename.git') repo = mock.Mock(full_fs_path=repo_dir) _git.side_effect = ValueError impl = GM.git_repo.GitImplementation(repo) lcds = impl.last_commit_ids( mock.Mock(_id='13951944969cf45a701bf90f83647b309815e6d5'), ['f2.txt', 'f3.txt']) self.assertEqual(lcds, {})
def test_missing_logo_height(self): self.logo_data = { "link": "/", "path": "user.png", "width": 20} with h.push_config(config, **self._set_config()): response = self.app.get('/').follow() nav_logo = response.html.find(*self.logo_pattern) width = self.width % self.logo_data["width"] assert nav_logo.find( 'img', style='%s ' % width) is not None
def test_new_topic_rate_limit(self): with h.push_config( config, **{'forgediscussion.rate_limits_per_user': '******'}): # first one should succeed self.test_posting() # second should fail with assert_raises(Exception): self.test_posting()
def route_email(peer, mailfrom, rcpttos, data): '''Route messages according to their destination: <topic>@<mount_point>.<subproj2>.<subproj1>.<project>.projects.sourceforge.net gets sent to c.app.handle_message(topic, message) ''' try: msg = mail_util.parse_message(data) except: # pragma no cover log.exception('Parse Error: (%r,%r,%r)', peer, mailfrom, rcpttos) return mail_user = mail_util.identify_sender(peer, mailfrom, msg['headers'], msg) with h.push_config(c, user=mail_user): log.info('Received email from %s', c.user.username) # For each of the addrs, determine the project/app and route appropriately for addr in rcpttos: try: userpart, project, app = mail_util.parse_address(addr) with h.push_config(c, project=project, app=app): if not app.has_access(c.user, userpart): log.info('Access denied for %s to mailbox %s', c.user, userpart) else: if msg['multipart']: msg_hdrs = msg['headers'] for part in msg['parts']: if part.get('content_type', '').startswith('multipart/'): continue msg = dict(headers=dict( msg_hdrs, **part['headers']), message_id=part['message_id'], in_reply_to=part['in_reply_to'], references=part['references'], filename=part['filename'], content_type=part['content_type'], payload=part['payload']) c.app.handle_message(userpart, msg) else: c.app.handle_message(userpart, msg) except exc.MailError, e: log.error('Error routing email to %s: %s', addr, e) except:
def test_additional_fields(self, search): search.site_admin_search.return_value = self.TEST_HIT with h.push_config(config, **{'search.user.additional_search_fields': 'email_addresses, url', 'search.user.additional_display_fields': 'url'}): r = self.app.get('/nf/admin/search_users?q=fake&f=username') options = [o['value'] for o in r.html.findAll('option')] assert_equal(options, ['username', 'display_name', 'email_addresses', 'url', '__custom__']) ths = [th.text for th in r.html.findAll('th')] assert_equal(ths, ['Username', 'Display name', 'Email', 'Registered', 'Status', 'url', 'Details'])
def create(self, task, task_args=None, user=None, path=None): """Post a new task""" args = task_args.get("args", ()) kw = task_args.get("kwargs", {}) config_dict = path if user: config_dict['user'] = user with h.push_config(c, **config_dict): task = task.post(*args, **kw) redirect('view/%s' % task._id)
def import_tool(self, project, user, project_name, mount_point=None, mount_label=None, **kw): import_id_converter = ImportIdConverter.get() project_name = '%s/%s' % (kw['user_name'], project_name) extractor = GitHubProjectExtractor(project_name, user=user) if not extractor.has_tracker(): return app = project.install_app('tickets', mount_point, mount_label, EnableVoting=False, open_status_names='open', closed_status_names='closed', import_id={ 'source': self.source, 'project_name': project_name, }) self.github_markdown_converter = GitHubMarkdownConverter( kw['user_name'], project_name) ThreadLocalORMSession.flush_all() try: M.session.artifact_orm_session._get().skip_mod_date = True with h.push_config(c, user=M.User.anonymous(), app=app): for ticket_num, issue in extractor.iter_issues(): self.max_ticket_num = max(ticket_num, self.max_ticket_num) ticket = TM.Ticket(app_config_id=app.config._id, custom_fields=dict(), ticket_num=ticket_num, import_id=import_id_converter.expand( ticket_num, app)) self.process_fields(extractor, ticket, issue) self.process_comments(extractor, ticket, issue) self.process_events(extractor, ticket, issue) self.process_milestones(ticket, issue) session(ticket).flush(ticket) session(ticket).expunge(ticket) app.globals.custom_fields = self.postprocess_milestones() app.globals.last_ticket_num = self.max_ticket_num ThreadLocalORMSession.flush_all() M.AuditLog.log( 'import tool %s from %s on %s' % (app.config.options.mount_point, project_name, self.source), project=project, user=user, url=app.url) g.post_event('project_updated') app.globals.invalidate_bin_counts() return app finally: M.session.artifact_orm_session._get().skip_mod_date = False
def test_enableediting_setting(self): def check_access(username=None, status=None): self.app.get('/categories/', status=status, extra_environ=dict(username=str(username))) cfg = {'trovecategories.enableediting': 'true'} with h.push_config(config, **cfg): check_access(username='******', status=200) check_access(username='******', status=200) cfg['trovecategories.enableediting'] = 'false' with h.push_config(config, **cfg): check_access(username='******', status=403) check_access(username='******', status=403) cfg['trovecategories.enableediting'] = 'admin' with h.push_config(config, **cfg): check_access(username='******', status=403) check_access(username='******', status=200)
def test_icon_url(self): p = M.Project( shortname='myproj', neighborhood=M.Neighborhood(url_prefix='/nbhd/'), ) self.assertEqual(p.icon_url(), '/nbhd/myproj/icon') with h.push_config(config, **{'static.icon_base': 'https://mycdn.com/mysite'}): self.assertEqual(p.icon_url(), 'https://mycdn.com/mysite/nbhd/myproj/icon')
def test_create_duplicates(self): assert_equal(M.Webhook.query.find().count(), len(self.webhooks)) data = {u'url': self.webhooks[0].hook_url} limit = json.dumps({'git': 10}) with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}): r = self.api_post(self.url + '/repo-push', status=400, **data) expected = {u'result': u'error', u'error': u'_the_form: "repo-push" webhook already ' u'exists for Git http://httpbin.org/post/0'} assert_equal(r.json, expected) assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
def test_not_spam_but_has_no_unmoderated_post_permission(notify_moderators, spam_checker): spam_checker.check.return_value = False d = M.Discussion(shortname='test', name='test') t = M.Thread(discussion_id=d._id, subject='Test Thread') role = M.ProjectRole.by_name('*anonymous')._id post_permission = M.ACE.allow(role, 'post') t.acl.append(post_permission) with h.push_config(c, user=M.User.anonymous()): post = t.post('Hey') assert_equal(post.status, 'pending') assert_equal(notify_moderators.call_count, 1)
def test_logo_image_width_and_height(self): self.logo_data = { "link": "", "path": "user.png", "width": 20, "height": 20} with h.push_config(config, **self._set_config()): response = self.app.get('/').follow() nav_logo = response.html.find(*self.logo_pattern) width = self.width % self.logo_data["width"] height = self.height % self.logo_data["height"] assert nav_logo.find( 'img', style='%s %s' % (width, height)) is not None
def test_merge_request_commits_tmp_dir(self): """ repo.merge_request_commits should return the same result with and without scm.merge_list.git.use_tmp_dir option enabled """ mr = self.merge_request res_without_tmp = self.repo.merge_request_commits(mr) opt = {'scm.merge_list.git.use_tmp_dir': True} with h.push_config(tg.config, **opt): res_with_tmp = self.repo.merge_request_commits(mr) assert_equals(res_without_tmp, res_with_tmp)