def test_grouped_navbar_threshold(self): p = M.Project() sitemap_entries = [ SitemapEntry('bugs', url='bugs url', tool_name='Tickets'), SitemapEntry('wiki', url='wiki url', tool_name='Wiki'), SitemapEntry('discuss', url='discuss url', tool_name='Discussion'), SitemapEntry('subproject', url='subproject url'), SitemapEntry('features', url='features url', tool_name='Tickets'), SitemapEntry('help', url='help url', tool_name='Discussion'), SitemapEntry('support reqs', url='support url', tool_name='Tickets'), ] p.url = Mock(return_value='proj_url/') p.sitemap = Mock(return_value=sitemap_entries) p.tool_data['allura'] = {'grouping_threshold': 2} entries = p.grouped_navbar_entries() expected = [ (u'Tickets \u25be', 'proj_url/_list/tickets', 3), (u'wiki', 'wiki url', 0), (u'discuss', 'discuss url', 0), (u'subproject', 'subproject url', 0), (u'help', 'help url', 0), ] expected_ticket_urls = ['bugs url', 'features url', 'support url'] actual = [(e.label, e.url, len(e.matching_urls)) for e in entries] self.assertEqual(expected, actual) self.assertEqual(entries[0].matching_urls, expected_ticket_urls)
def register_neighborhood_project(self, neighborhood, users, allow_register=False): from allura import model as M shortname = '--init--' name = 'Home Project for %s' % neighborhood.name database_uri = M.Project.default_database_uri(shortname) p = M.Project(neighborhood_id=neighborhood._id, shortname=shortname, name=name, short_description='', description=('You can edit this description in the admin page'), homepage_title = '# ' + name, database_uri=database_uri, last_updated = datetime.utcnow(), is_nbhd_project=True, is_root=True) try: p.configure_project( users=users, is_user_project=False, apps=[ ('Wiki', 'wiki', 'Wiki'), ('admin', 'admin', 'Admin')]) except: ThreadLocalORMSession.close_all() log.exception('Error registering project %s' % p) raise if allow_register: role_auth = M.ProjectRole.authenticated(p) security.simple_grant(p.acl, role_auth._id, 'register') state(p).soil() return p
def test_social_account(self): p = M.Project() self.assertIsNone(p.social_account('Twitter')) p.set_social_account('Twitter', 'http://twitter.com/allura') self.assertEqual( p.social_account('Twitter').accounturl, 'http://twitter.com/allura') self.assertEqual(p.twitter_handle, 'http://twitter.com/allura')
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 setUp(self): super(TestProjectsSearch, self).setUp() # Create project that matches TEST_HIT id _id = ObjectId('53ccf6e8100d2b0741746e9f') p = M.Project.query.get(_id=_id) if not p: M.Project( _id=_id, neighborhood_id=M.Neighborhood.query.get(url_prefix='/u/')._id, shortname='test-project', ) ThreadLocalORMSession().flush_all()
def test_should_update_index(self): p = M.Project() self.assertFalse(p.should_update_index({}, {})) old = {'last_updated': 1} new = {'last_updated': 2} self.assertFalse(p.should_update_index(old, new)) old = {'last_updated': 1, 'a': 1} new = {'last_updated': 2, 'a': 1} self.assertFalse(p.should_update_index(old, new)) old = {'last_updated': 1, 'a': 1} new = {'last_updated': 2, 'a': 2} self.assertTrue(p.should_update_index(old, new))
def register_subproject(self, project, name, user, install_apps): from allura import model as M assert h.re_path_portion.match(name), 'Invalid subproject shortname' shortname = project.shortname + '/' + name sp = M.Project(parent_id=project._id, neighborhood_id=project.neighborhood_id, shortname=shortname, name=name, database_uri=project.database_uri, last_updated=datetime.utcnow(), is_root=False) with h.push_config(c, project=sp): M.AppConfig.query.remove(dict(project_id=c.project._id)) if install_apps: sp.install_app('admin', 'admin', ordinal=1) sp.install_app('search', 'search', ordinal=2) g.post_event('project_created') return sp
def register_subproject(self, project, name, user, install_apps, project_name=None): from allura import model as M assert h.re_project_name.match(name), 'Invalid subproject shortname' shortname = project.shortname + '/' + name ordinal = int(project.ordered_mounts(include_hidden=True)[-1]['ordinal']) + 1 sp = M.Project( parent_id=project._id, neighborhood_id=project.neighborhood_id, shortname=shortname, name=project_name or name, database_uri=project.database_uri, last_updated = datetime.utcnow(), is_root=False, ordinal=ordinal, ) with h.push_config(c, project=sp): M.AppConfig.query.remove(dict(project_id=c.project._id)) if install_apps: sp.install_app('admin', 'admin', ordinal=1) sp.install_app('search', 'search', ordinal=2) g.post_event('project_created') return sp
def test_only_shortname_multiple_projects_matched(self): adobe_n = M.Neighborhood.query.get(url_prefix='/adobe/') M.Project(shortname='test', neighborhood_id=adobe_n._id) ThreadLocalORMSession.flush_all() assert_equal((None, u'Too many matches for project: 2'), self.parse('test'))
def _create_project(self, neighborhood, shortname, project_name, user, user_project, private_project, apps): ''' Actually create the project, no validation. This should not be called directly under normal circumstances. ''' from allura import model as M project_template = neighborhood.get_project_template() p = M.Project(neighborhood_id=neighborhood._id, shortname=shortname, name=project_name, short_description='', description=('You can edit this description in the admin page'), homepage_title=shortname, database_uri=M.Project.default_database_uri(shortname), last_updated = datetime.utcnow(), is_nbhd_project=False, is_root=True) p.configure_project( users=[user], is_user_project=user_project, is_private_project=private_project or project_template.get('private', False), apps=apps or [] if 'tools' in project_template else None) # Setup defaults from neighborhood project template if applicable offset = p.next_mount_point(include_hidden=True) if 'groups' in project_template: for obj in project_template['groups']: name = obj.get('name') permissions = set(obj.get('permissions', [])) & \ set(p.permissions) usernames = obj.get('usernames', []) # Must provide a group name if not name: continue # If the group already exists, we'll add users to it, # but we won't change permissions on the group group = M.ProjectRole.by_name(name, project=p) if not group: # If creating a new group, *must* specify permissions if not permissions: continue group = M.ProjectRole(project_id=p._id, name=name) p.acl += [M.ACE.allow(group._id, perm) for perm in permissions] for username in usernames: guser = M.User.by_username(username) if not (guser and guser._id): continue pr = guser.project_role(project=p) if group._id not in pr.roles: pr.roles.append(group._id) if 'tools' in project_template: for i, tool in enumerate(project_template['tools'].keys()): tool_config = project_template['tools'][tool] tool_options = tool_config.get('options', {}) for k, v in tool_options.iteritems(): if isinstance(v, basestring): tool_options[k] = \ string.Template(v).safe_substitute( p.__dict__.get('root_project', {})) if p.app_instance(tool) is None: app = p.install_app(tool, mount_label=tool_config['label'], mount_point=tool_config['mount_point'], ordinal=i + offset, **tool_options) if tool == 'wiki': from forgewiki import model as WM text = tool_config.get('home_text', '[[members limit=20]]\n[[download_button]]') WM.Page.query.get(app_config_id=app.config._id).text = text if 'tool_order' in project_template: for i, tool in enumerate(project_template['tool_order']): p.app_config(tool).options.ordinal = i if 'labels' in project_template: p.labels = project_template['labels'] if 'trove_cats' in project_template: for trove_type in project_template['trove_cats'].keys(): troves = getattr(p, 'trove_%s' % trove_type) for trove_id in project_template['trove_cats'][trove_type]: troves.append(M.TroveCategory.query.get(trove_cat_id=trove_id)._id) if 'icon' in project_template: icon_file = StringIO(urlopen(project_template['icon']['url']).read()) M.ProjectFile.save_image( project_template['icon']['filename'], icon_file, square=True, thumbnail_size=(48, 48), thumbnail_meta=dict(project_id=p._id, category='icon')) if user_project: # Allow for special user-only tools p._extra_tool_status = ['user'] # add user project informative text to home from forgewiki import model as WM home_app = p.app_instance('wiki') home_page = WM.Page.query.get(app_config_id=home_app.config._id) home_page.text = ("This is the personal project of %s." " This project is created automatically during user registration" " as an easy place to store personal data that doesn't need its own" " project such as cloned repositories.") % user.display_name # clear the RoleCache for the user so this project will # be picked up by user.my_projects() g.credentials.clear_user(user._id, None) # unnamed roles for this user g.credentials.clear_user(user._id, p._id) # named roles for this project + user with h.push_config(c, project=p, user=user): ThreadLocalORMSession.flush_all() # have to add user to context, since this may occur inside auth code # for user-project reg, and c.user isn't set yet g.post_event('project_created') return p
def register_project(self, neighborhood, shortname, project_name, user, user_project, private_project, apps=None): '''Register a new project in the neighborhood. The given user will become the project's superuser. ''' from allura import model as M # Check for private project rights if neighborhood.features['private_projects'] == False and private_project: raise ValueError("You can't create private projects for %s neighborhood" % neighborhood.name) # Check for project limit creation pq = M.Project.query.find(dict( neighborhood_id=neighborhood._id, deleted=False, is_nbhd_project=False, )) count = pq.count() nb_max_projects = neighborhood.get_max_projects() if nb_max_projects is not None and count >= nb_max_projects: log.exception('Error registering project %s' % project_name) raise forge_exc.ProjectOverlimitError() if not h.re_path_portion.match(shortname.replace('/', '')): raise ValueError('Invalid project shortname: %s' % shortname) try: p = M.Project.query.get(shortname=shortname, neighborhood_id=neighborhood._id) if p: raise forge_exc.ProjectConflict() project_template = neighborhood.get_project_template() p = M.Project(neighborhood_id=neighborhood._id, shortname=shortname, name=project_name, short_description='', description=('You can edit this description in the admin page'), homepage_title=shortname, database_uri=M.Project.default_database_uri(shortname), last_updated = datetime.utcnow(), is_nbhd_project=False, is_root=True) p.configure_project( users=[user], is_user_project=user_project, is_private_project=private_project or project_template.get('private', False), apps=apps or [] if 'tools' in project_template else None) # Setup defaults from neighborhood project template if applicable offset = p.next_mount_point(include_hidden=True) if 'groups' in project_template: for obj in project_template['groups']: name = obj.get('name') permissions = set(obj.get('permissions', [])) & \ set(p.permissions) usernames = obj.get('usernames', []) # Must provide a group name if not name: continue # If the group already exists, we'll add users to it, # but we won't change permissions on the group group = M.ProjectRole.by_name(name, project=p) if not group: # If creating a new group, *must* specify permissions if not permissions: continue group = M.ProjectRole(project_id=p._id, name=name) p.acl += [M.ACE.allow(group._id, perm) for perm in permissions] for username in usernames: user = M.User.by_username(username) if not (user and user._id): continue pr = user.project_role(project=p) if group._id not in pr.roles: pr.roles.append(group._id) if 'tools' in project_template: for i, tool in enumerate(project_template['tools'].keys()): tool_config = project_template['tools'][tool] tool_options = tool_config.get('options', {}) for k, v in tool_options.iteritems(): if isinstance(v, basestring): tool_options[k] = \ string.Template(v).safe_substitute( p.__dict__.get('root_project', {})) app = p.install_app(tool, mount_label=tool_config['label'], mount_point=tool_config['mount_point'], ordinal=i + offset, **tool_options) if tool == 'wiki': from forgewiki import model as WM text = tool_config.get('home_text', '[[project_admins]]\n[[download_button]]') WM.Page.query.get(app_config_id=app.config._id).text = text if 'tool_order' in project_template: for i, tool in enumerate(project_template['tool_order']): p.app_config(tool).options.ordinal = i if 'labels' in project_template: p.labels = project_template['labels'] if 'trove_cats' in project_template: for trove_type in project_template['trove_cats'].keys(): troves = getattr(p, 'trove_%s' % trove_type) for trove_id in project_template['trove_cats'][trove_type]: troves.append(M.TroveCategory.query.get(trove_cat_id=trove_id)._id) if 'icon' in project_template: icon_file = StringIO(urlopen(project_template['icon']['url']).read()) M.ProjectFile.save_image( project_template['icon']['filename'], icon_file, square=True, thumbnail_size=(48, 48), thumbnail_meta=dict(project_id=p._id, category='icon')) except forge_exc.ProjectConflict: raise except: ThreadLocalORMSession.close_all() log.exception('Error registering project %s' % p) raise with h.push_config(c, project=p, user=user): ThreadLocalORMSession.flush_all() # have to add user to context, since this may occur inside auth code # for user-project reg, and c.user isn't set yet g.post_event('project_created') return p