Esempio n. 1
0
    def import_tool(self,
                    project,
                    user,
                    project_name=None,
                    mount_point=None,
                    mount_label=None,
                    user_name=None,
                    **kw):
        """ Import a GitHub repo into a new Git Allura tool.

        """
        project_name = "%s/%s" % (user_name, project_name)
        extractor = GitHubProjectExtractor(project_name, user=user)
        repo_url = extractor.get_repo_url()
        app = project.install_app("Git",
                                  mount_point=mount_point or 'code',
                                  mount_label=mount_label or 'Code',
                                  init_from_url=repo_url,
                                  import_id={
                                      'source': self.source,
                                      'project_name': project_name,
                                  })
        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')
        return app
Esempio n. 2
0
    def import_tool(self, project, user, project_name=None, mount_point=None,
                    mount_label=None, user_name=None, **kw):
        """ Import a GitHub repo into a new Git Allura tool.

        """
        project_name = "%s/%s" % (user_name, project_name)
        extractor = GitHubProjectExtractor(project_name, user=user)
        repo_url = extractor.get_repo_url()
        app = project.install_app(
            "Git",
            mount_point=mount_point or 'code',
            mount_label=mount_label or 'Code',
            init_from_url=repo_url,
            import_id={
                'source': self.source,
                'project_name': project_name,
            }
        )
        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')
        return app
Esempio n. 3
0
 def edit_screenshot(self, id=None, caption=None, **kw):
     require_access(c.project, 'update')
     if id is not None and id != '':
         M.ProjectFile.query.get(
             project_id=c.project._id, _id=ObjectId(id)).caption = caption
         g.post_event('project_updated')
     redirect('screenshots')
Esempio n. 4
0
 def success(self, app):
     with h.push_config(c, project=self.project, app=app):
         g.post_event(
             'import_tool_task_succeeded',
             self.importer.source,
             self.importer.tool_label,
         )
Esempio n. 5
0
 def test_post_event_from_script(self):
     # simulate post_event being called from a paster script command:
     with mock.patch.dict(tg.request.environ, PATH_INFO='--script--'):
         g.post_event('my_event3')
         # event task is flushed to db right away:
         assert M.MonQTask.query.get(
             task_name='allura.tasks.event_tasks.event', args=['my_event3'])
Esempio n. 6
0
    def add_screenshot(self, screenshot=None, caption=None, **kw):
        require_access(c.project, 'update')
        screenshots = c.project.get_screenshots()
        if len(screenshots) >= 6:
            flash('You may not have more than 6 screenshots per project.',
                  'error')
        elif screenshot is not None and screenshot != '':
            future_bmp = False
            e_filename, e_fileext = os.path.splitext(screenshot.filename)
            for screen in screenshots:
                c_filename, c_fileext = os.path.splitext(screen.filename)
                if c_fileext == '.png' and e_fileext.lower() == '.bmp' and e_filename == c_filename:
                    future_bmp = True
                    # If both filename(without ext.) equals and exiting file ext. is png and given file ext is bmp, there will be two similar png files.

                if screen.filename == screenshot.filename or future_bmp:
                    screenshot.filename = re.sub('(.*)\.(.*)', r'\1-' + str(randint(1000,9999)) + r'.\2', screenshot.filename)
                    # if filename already exists append a random number
                    break
            M.AuditLog.log('add screenshot')
            sort = 1 + max([ss.sort or 0 for ss in screenshots] or [0])
            M.ProjectFile.save_image(
                screenshot.filename, screenshot.file, content_type=screenshot.type,
                save_original=True,
                original_meta=dict(
                    project_id=c.project._id,
                    category='screenshot',
                    caption=caption,
                    sort=sort),
                square=True, thumbnail_size=(150, 150),
                thumbnail_meta=dict(project_id=c.project._id, category='screenshot_thumb'), convert_bmp=True)
            g.post_event('project_updated')
        redirect('screenshots')
Esempio n. 7
0
    def test_post_event_explicit_flush(self):
        g.post_event('my_event1', flush_immediately=True)
        assert M.MonQTask.query.get(task_name='allura.tasks.event_tasks.event', args=['my_event1'])

        g.post_event('my_event2', flush_immediately=False)
        assert not M.MonQTask.query.get(task_name='allura.tasks.event_tasks.event', args=['my_event2'])
        ThreadLocalORMSession.flush_all()
        assert M.MonQTask.query.get(task_name='allura.tasks.event_tasks.event', args=['my_event2'])
Esempio n. 8
0
    def update_label(self, mount_label):
        """Handles POST to update the Application's ``mount_label``.

        """
        require_access(self.app, 'configure')
        self.app.config.options['mount_label'] = mount_label
        g.post_event('project_menu_updated')
        redirect(six.ensure_text(request.referer or '/'))
Esempio n. 9
0
 def create(self, name=None, **kw):
     if M.ProjectRole.by_name(name):
         flash('%s already exists' % name, 'error')
     else:
         M.ProjectRole(project_id=c.project._id, name=name)
     M.AuditLog.log('create group %s', name)
     g.post_event('project_updated')
     redirect('.')
Esempio n. 10
0
 def delete_screenshot(self, id=None, **kw):
     require_access(c.project, 'update')
     if id is not None and id != '':
         M.AuditLog.log('remove screenshot')
         M.ProjectFile.query.remove(
             dict(project_id=c.project._id, _id=ObjectId(id)))
         g.post_event('project_updated')
     redirect('screenshots')
Esempio n. 11
0
def import_project_info(project_name):
    from forgeimporters.github.project import GitHubProjectImporter
    importer = GitHubProjectImporter(None)
    with ImportErrorHandler(importer, project_name, c.project) as handler:
        extractor = GitHubProjectExtractor(project_name, user=c.user)
        c.project.summary = extractor.get_summary()
        c.project.external_homepage = extractor.get_homepage()
        ThreadLocalORMSession.flush_all()
        g.post_event('project_updated')
Esempio n. 12
0
def import_project_info(project_name):
    from forgeimporters.github.project import GitHubProjectImporter
    importer = GitHubProjectImporter(None)
    with ImportErrorHandler(importer, project_name, c.project) as handler:
        extractor = GitHubProjectExtractor(project_name, user=c.user)
        c.project.summary = extractor.get_summary()
        c.project.external_homepage = extractor.get_homepage()
        ThreadLocalORMSession.flush_all()
        g.post_event('project_updated')
Esempio n. 13
0
 def delete_group(self, group_name, **kw):
     role = M.ProjectRole.by_name(group_name)
     if not role:
         flash('Group "%s" does not exist.' % group_name, 'error')
     else:
         role.delete()
         M.AuditLog.log('delete group %s', group_name)
         flash('Group "%s" deleted successfully.' % group_name)
         g.post_event('project_updated')
     redirect('.')
Esempio n. 14
0
 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
Esempio n. 15
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     if hasattr(self.importer, 'clear_pending'):
         self.importer.clear_pending(self.project)
     if exc_type:
         g.post_event('import_tool_task_failed',
                      error=str(exc_val),
                      traceback=traceback.format_exc(),
                      importer_source=self.importer.source,
                      importer_tool_label=self.importer.tool_label,
                      project_name=self.project_name,
                      )
Esempio n. 16
0
 def delete(self):
     require_access(self.neighborhood, 'admin')
     if self.award:
         grants = M.AwardGrant.query.find(dict(award_id=self.award._id))
         for grant in grants:
             grant.delete()
             with h.push_context(grant.granted_to_project_id):
                 g.post_event('project_updated')
         M.AwardFile.query.remove(dict(award_id=self.award._id))
         self.award.delete()
     redirect(request.referer or '/')
Esempio n. 17
0
 def delete(self):
     require_access(self.neighborhood, 'admin')
     if self.award:
         grants = M.AwardGrant.query.find(dict(award_id=self.award._id))
         for grant in grants:
             grant.delete()
             with h.push_context(grant.granted_to_project_id):
                 g.post_event('project_updated')
         M.AwardFile.query.remove(dict(award_id=self.award._id))
         self.award.delete()
     redirect(request.referer or '/')
Esempio n. 18
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     if hasattr(self.importer, 'clear_pending'):
         self.importer.clear_pending(self.project)
     if exc_type:
         g.post_event(
             'import_tool_task_failed',
             error=str(exc_val),
             traceback=traceback.format_exc(),
             importer_source=self.importer.source,
             importer_tool_label=self.importer.tool_label,
             project_name=self.project_name,
         )
Esempio n. 19
0
 def delete_trove(self, type, trove, **kw):
     require_access(c.project, 'update')
     trove_obj = M.TroveCategory.query.get(trove_cat_id=int(trove))
     current_troves = getattr(c.project, 'trove_%s' % type)
     if trove_obj is not None and trove_obj._id in current_troves:
         M.AuditLog.log('remove trove %s: %s', type, trove_obj.fullpath)
         current_troves.remove(trove_obj._id)
         # just in case the event handling is super fast
         ThreadLocalORMSession.flush_all()
         c.project.last_updated = datetime.utcnow()
         g.post_event('project_updated')
     redirect('trove')
Esempio n. 20
0
    def configure_tool_grouping(self, grouping_threshold='1', **kw):
        try:
            grouping_threshold = int(grouping_threshold)
            if grouping_threshold < 1 or grouping_threshold > 10:
                raise exc.HTTPBadRequest('Invalid threshold. Expected a value between 1 and 10')
            c.project.set_tool_data(
                'allura', grouping_threshold=grouping_threshold)
        except ValueError:
            raise exc.HTTPBadRequest('Invalid threshold. Expected a value between 1 and 10')

        M.AuditLog.log('Updated tool grouping threshold')
        g.post_event('project_menu_updated')
        return {'status': 'ok'}
Esempio n. 21
0
    def sort_screenshots(self, **kw):
        """Sort project screenshots.

        Called via ajax when screenshots are reordered via drag/drop on
        the Screenshots admin page.

        ``kw`` is a mapping of (screenshot._id, sort_order) pairs.

        """
        for s in c.project.get_screenshots():
            if str(s._id) in kw:
                s.sort = int(kw[str(s._id)])
        g.post_event('project_updated')
Esempio n. 22
0
    def import_tool(self,
                    project,
                    user,
                    project_name=None,
                    mount_point=None,
                    mount_label=None,
                    trac_url=None,
                    user_map=None,
                    **kw):
        """ Import Trac tickets into a new Allura Tracker tool.

        """
        mount_point = mount_point or 'tickets'
        app = project.install_app(
            'Tickets',
            mount_point=mount_point,
            mount_label=mount_label or 'Tickets',
            open_status_names='new assigned accepted reopened',
            closed_status_names='closed',
            import_id={
                'source': self.source,
                'trac_url': trac_url,
            },
        )
        session(app.config).flush(app.config)
        session(app.globals).flush(app.globals)
        try:
            with h.push_config(c, app=app):
                TracImportSupport().perform_import(
                    json.dumps(export(trac_url), cls=DateJSONEncoder),
                    json.dumps({
                        'user_map':
                        json.loads(user_map) if user_map else {},
                        'usernames_match':
                        self.usernames_match(trac_url),
                    }),
                )
            AuditLog.log(
                'import tool %s from %s' % (
                    app.config.options.mount_point,
                    trac_url,
                ),
                project=project,
                user=user,
                url=app.url,
            )
            g.post_event('project_updated')
            return app
        except Exception:
            h.make_app_admin_only(app)
            raise
Esempio n. 23
0
    def update(self, card=None, **kw):
        """Handle POST to update permissions for the Application.

        """
        old_acl = self.app.config.acl
        self.app.config.acl = []
        for args in card:
            perm = args['id']
            new_group_ids = args.get('new', [])
            del_group_ids = []
            group_ids = args.get('value', [])
            if isinstance(new_group_ids, six.string_types):
                new_group_ids = [new_group_ids]
            if isinstance(group_ids, six.string_types):
                group_ids = [group_ids]

            for acl in old_acl:
                if (acl['permission'] == perm
                        and str(acl['role_id']) not in group_ids
                        and acl['access'] != model.ACE.DENY):
                    del_group_ids.append(str(acl['role_id']))

            def get_role(_id):
                return model.ProjectRole.query.get(_id=ObjectId(_id))

            groups = list(map(get_role, group_ids))
            new_groups = list(map(get_role, new_group_ids))
            del_groups = list(map(get_role, del_group_ids))

            def group_names(groups):
                return ', '.join(
                    (role.name or '<Unnamed>') for role in groups if role)

            if new_groups or del_groups:
                model.AuditLog.log(
                    'updated "%s" permission: "%s" => "%s" for %s' %
                    (perm, group_names(groups + del_groups),
                     group_names(groups + new_groups),
                     self.app.config.options['mount_point']))

            role_ids = list(map(ObjectId, group_ids + new_group_ids))
            self.app.config.acl += [model.ACE.allow(r, perm) for r in role_ids]

            # Add all ACEs for user roles back
            for ace in old_acl:
                if (ace.permission == perm) and (ace.access == model.ACE.DENY):
                    self.app.config.acl.append(ace)
        g.post_event(
            'project_menu_updated'
        )  # since 'read' permission changes can affect what is visible in menu
        redirect(six.ensure_text(request.referer or '/'))
Esempio n. 24
0
 def change_perm(self, role_id, permission, allow="true", **kw):
     if allow == "true":
         M.AuditLog.log('granted permission %s to group %s', permission,
                        M.ProjectRole.query.get(_id=ObjectId(role_id)).name)
         c.project.acl.append(M.ACE.allow(ObjectId(role_id), permission))
     else:
         admin_group_id = str(M.ProjectRole.by_name('Admin')._id)
         if admin_group_id == role_id and permission == 'admin':
             return dict(error='You cannot remove the admin permission from the admin group.')
         M.AuditLog.log('revoked permission %s from group %s', permission,
                        M.ProjectRole.query.get(_id=ObjectId(role_id)).name)
         c.project.acl.remove(M.ACE.allow(ObjectId(role_id), permission))
     g.post_event('project_updated')
     return self._map_group_permissions()
Esempio n. 25
0
def clone(cloned_from_path, cloned_from_name, cloned_from_url):
    from allura import model as M
    try:
        c.app.repo.init_as_clone(cloned_from_path, cloned_from_name,
                                 cloned_from_url)
        M.Notification.post_user(
            c.user,
            c.app.repo,
            'created',
            text='Repository %s/%s created' %
            (c.project.shortname, c.app.config.options.mount_point))
    except Exception:
        g.post_event('repo_clone_task_failed', cloned_from_url,
                     cloned_from_path, traceback.format_exc())
Esempio n. 26
0
def clone(cloned_from_path, cloned_from_name, cloned_from_url):
    from allura import model as M
    try:
        c.app.repo.init_as_clone(
            cloned_from_path,
            cloned_from_name,
            cloned_from_url)
        M.Notification.post_user(
            c.user, c.app.repo, 'created',
            text='Repository %s/%s created' % (
                c.project.shortname, c.app.config.options.mount_point))
    except Exception:
        g.post_event('repo_clone_task_failed', cloned_from_url,
                     cloned_from_path, traceback.format_exc())
Esempio n. 27
0
 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
Esempio n. 28
0
 def update(self, icon=None, short=None, full=None):
     require_access(self.neighborhood, 'admin')
     self.award.short = short
     self.award.full = full
     if hasattr(icon, 'filename'):
         if self.award.icon:
             self.award.icon.delete()
         M.AwardFile.save_image(
             icon.filename, icon.file, content_type=icon.type,
             square=True, thumbnail_size=(48, 48),
             thumbnail_meta=dict(award_id=self.award._id))
     for grant in M.AwardGrant.query.find(dict(award_id=self.award._id)):
         with h.push_context(grant.granted_to_project_id):
             g.post_event('project_updated')
     flash('Award updated.')
     redirect(self.award.longurl())
Esempio n. 29
0
 def remove_user(self, role_id, username, **kw):
     group = M.ProjectRole.query.get(_id=ObjectId(role_id))
     user = M.User.by_username(username.strip())
     if group.name == 'Admin' and len(group.users_with_role()) == 1:
         return dict(error='You must have at least one user with the Admin role.')
     if not group:
         return dict(error='Could not find group with id %s' % role_id)
     if not user:
         return dict(error='User %s not found' % username)
     user_role = M.ProjectRole.by_user(user)
     if not user_role or group._id not in user_role.roles:
         return dict(error='%s (%s) is not in the group %s.' % (user.display_name, username, group.name))
     M.AuditLog.log('remove user %s from %s', username, group.name)
     user_role.roles.remove(group._id)
     g.post_event('project_updated')
     return dict()
Esempio n. 30
0
 def update(self, icon=None, short=None, full=None):
     require_access(self.neighborhood, 'admin')
     self.award.short = short
     self.award.full = full
     if hasattr(icon, 'filename'):
         if self.award.icon:
             self.award.icon.delete()
         M.AwardFile.save_image(
             icon.filename, icon.file, content_type=icon.type,
             square=True, thumbnail_size=(48, 48),
             thumbnail_meta=dict(award_id=self.award._id))
     for grant in M.AwardGrant.query.find(dict(award_id=self.award._id)):
         with h.push_context(grant.granted_to_project_id):
             g.post_event('project_updated')
     flash('Award updated.')
     redirect(self.award.longurl())
Esempio n. 31
0
def reclone_repo(*args, **kwargs):
    from allura import model as M
    try:
        nbhd = M.Neighborhood.query.get(url_prefix='/%s/' % kwargs['prefix'])
        c.project = M.Project.query.get(
            shortname=kwargs['shortname'], neighborhood_id=nbhd._id)
        c.app = c.project.app_instance(kwargs['mount_point'])
        source_url = c.app.config.options.get('init_from_url')
        source_path = c.app.config.options.get('init_from_path')
        c.app.repo.init_as_clone(source_path, None, source_url)
        M.Notification.post_user(
            c.user, c.app.repo, 'created',
            text='Repository %s/%s created' % (
                c.project.shortname, c.app.config.options.mount_point))
    except Exception:
        g.post_event('repo_clone_task_failed', source_url,
                     source_path, traceback.format_exc())
Esempio n. 32
0
def reclone_repo(*args, **kwargs):
    from allura import model as M
    try:
        nbhd = M.Neighborhood.query.get(url_prefix='/%s/' % kwargs['prefix'])
        c.project = M.Project.query.get(
            shortname=kwargs['shortname'], neighborhood_id=nbhd._id)
        c.app = c.project.app_instance(kwargs['mount_point'])
        source_url = c.app.config.options.get('init_from_url')
        source_path = c.app.config.options.get('init_from_path')
        c.app.repo.init_as_clone(source_path, None, source_url)
        M.Notification.post_user(
            c.user, c.app.repo, 'created',
            text='Repository %s/%s created' % (
                c.project.shortname, c.app.config.options.mount_point))
    except Exception:
        g.post_event('repo_clone_task_failed', source_url,
                     source_path, traceback.format_exc())
Esempio n. 33
0
 def grant(self, grant=None, recipient=None, url=None, comment=None):
     require_access(self.neighborhood, 'admin')
     grant_q = M.Award.query.find(dict(short=grant,
                                       created_by_neighborhood_id=self.neighborhood._id)).first()
     recipient_q = M.Project.query.find(dict(
         neighborhood_id=self.neighborhood._id, shortname=recipient,
         deleted=False)).first()
     if grant_q and recipient_q:
         app_config_id = ObjectId()
         award = M.AwardGrant(app_config_id=app_config_id)
         award.award_id = grant_q._id
         award.granted_to_project_id = recipient_q._id
         award.granted_by_neighborhood_id = self.neighborhood._id
         award.award_url = url
         award.comment = comment
         with h.push_context(recipient_q._id):
             g.post_event('project_updated')
     redirect(six.ensure_text(request.referer or '/'))
Esempio n. 34
0
 def grant(self, grant=None, recipient=None, url=None, comment=None):
     require_access(self.neighborhood, 'admin')
     grant_q = M.Award.query.find(dict(short=grant,
                                       created_by_neighborhood_id=self.neighborhood._id)).first()
     recipient_q = M.Project.query.find(dict(
         neighborhood_id=self.neighborhood._id, shortname=recipient,
         deleted=False)).first()
     if grant_q and recipient_q:
         app_config_id = ObjectId()
         award = M.AwardGrant(app_config_id=app_config_id)
         award.award_id = grant_q._id
         award.granted_to_project_id = recipient_q._id
         award.granted_by_neighborhood_id = self.neighborhood._id
         award.award_url = url
         award.comment = comment
         with h.push_context(recipient_q._id):
             g.post_event('project_updated')
     redirect(request.referer or '/')
Esempio n. 35
0
 def _add_trove(self, type, new_trove):
     current_troves = getattr(c.project, 'trove_%s' % type)
     trove_obj = M.TroveCategory.query.get(trove_cat_id=int(new_trove))
     error_msg = None
     if type in ['license', 'audience', 'developmentstatus', 'language'] and len(current_troves) >= 6:
         error_msg = 'You may not have more than 6 of this category.'
     elif type in ['topic'] and len(current_troves) >= 3:
         error_msg = 'You may not have more than 3 of this category.'
     elif trove_obj is not None:
         if trove_obj._id not in current_troves:
             current_troves.append(trove_obj._id)
             M.AuditLog.log('add trove %s: %s', type, trove_obj.fullpath)
             # just in case the event handling is super fast
             ThreadLocalORMSession.flush_all()
             c.project.last_updated = datetime.utcnow()
             g.post_event('project_updated')
         else:
             error_msg = 'This category has already been assigned to the project.'
     return (trove_obj, error_msg)
Esempio n. 36
0
def main(options):
    log.addHandler(logging.StreamHandler(sys.stdout))
    log.setLevel(getattr(logging, options.log_level.upper()))

    nbhd = M.Neighborhood.query.get(name=options.neighborhood)
    if not nbhd:
        return 'Invalid neighborhood "%s".' % options.neighborhood
    admin_role = M.ProjectRole.by_name('Admin',
                                       project=nbhd.neighborhood_project)
    nbhd_admin = admin_role.users_with_role(
        project=nbhd.neighborhood_project)[0].user
    log.info('Making updates as neighborhood admin "%s"' % nbhd_admin.username)

    q = {
        'neighborhood_id': nbhd._id,
        'is_nbhd_project': False,
        'deleted': False
    }
    private_count = public_count = 0
    for projects in utils.chunked_find(M.Project, q):
        for p in projects:
            role_anon = M.ProjectRole.upsert(name='*anonymous',
                                             project_id=p.root_project._id)
            if M.ACE.allow(role_anon._id, 'read') not in p.acl:
                if options.test:
                    log.info('Would be made public: "%s"' % p.shortname)
                else:
                    log.info('Making public: "%s"' % p.shortname)
                    p.acl.append(M.ACE.allow(role_anon._id, 'read'))
                    with h.push_config(c, project=p, user=nbhd_admin):
                        ThreadLocalORMSession.flush_all()
                        g.post_event('project_updated')
                private_count += 1
            else:
                log.info('Already public: "%s"' % p.shortname)
                public_count += 1

    log.info('Already public: %s' % public_count)
    if options.test:
        log.info('Would be made public: %s' % private_count)
    else:
        log.info('Made public: %s' % private_count)
    return 0
Esempio n. 37
0
    def add_user(self, role_id, username, **kw):
        if not username or username == '*anonymous':
            return dict(error='You must choose a user to add.')
        group = M.ProjectRole.query.get(_id=ObjectId(role_id))
        user = M.User.query.get(username=username.strip(), pending=False)

        if not group:
            return dict(error='Could not find group with id %s' % role_id)
        if not user:
            return dict(error='User %s not found' % username)
        user_role = M.ProjectRole.by_user(user, upsert=True)
        if group._id in user_role.roles:
            return dict(error='%s (%s) is already in the group %s.' % (user.display_name, username, group.name))
        M.AuditLog.log('add user %s to %s', username, group.name)
        user_role.roles.append(group._id)
        if group.name == 'Admin':
            for ac in c.project.app_configs:
                c.project.app_instance(ac).subscribe(user)
        g.post_event('project_updated')
        return dict(username=username, displayname=user.display_name)
Esempio n. 38
0
    def mount_order(self, **kw):
        if not kw:
            raise exc.HTTPBadRequest('Expected kw params in the form of "ordinal: mount_point"')
        try:
            sorted_tools = sorted(list(kw.items()), key=lambda x: int(x[0]))
        except ValueError:
            raise exc.HTTPBadRequest('Invalid kw: expected "ordinal: mount_point"')

        for ordinal, mount_point in sorted_tools:
            try:
                c.project.app_config(mount_point).options.ordinal = int(ordinal)
            except AttributeError as e:
                # Handle sub project
                p = M.Project.query.get(shortname="{}/{}".format(c.project.shortname, mount_point),
                                        neighborhood_id=c.project.neighborhood_id)
                if p:
                    p.ordinal = int(ordinal)
        M.AuditLog.log('Updated tool order')
        g.post_event('project_menu_updated')
        return {'status': 'ok'}
Esempio n. 39
0
    def import_tool(self, project, user, project_name=None, mount_point=None,
                    mount_label=None, trac_url=None, user_map=None, **kw):
        """ Import Trac tickets into a new Allura Tracker tool.

        """
        mount_point = mount_point or 'tickets'
        app = project.install_app(
            'Tickets',
            mount_point=mount_point,
            mount_label=mount_label or 'Tickets',
            open_status_names='new assigned accepted reopened',
            closed_status_names='closed',
            import_id={
                'source': self.source,
                'trac_url': trac_url,
            },
        )
        session(app.config).flush(app.config)
        session(app.globals).flush(app.globals)
        try:
            with h.push_config(c, app=app):
                TracImportSupport().perform_import(
                    json.dumps(export(trac_url), cls=DateJSONEncoder),
                    json.dumps({
                        'user_map': json.loads(user_map) if user_map else {},
                        'usernames_match': self.usernames_match(trac_url),
                    }),
                )
            AuditLog.log(
                'import tool %s from %s' % (
                    app.config.options.mount_point,
                    trac_url,
                ),
                project=project, user=user, url=app.url,
            )
            g.post_event('project_updated')
            return app
        except Exception:
            h.make_app_admin_only(app)
            raise
Esempio n. 40
0
def main(options):
    log.addHandler(logging.StreamHandler(sys.stdout))
    log.setLevel(getattr(logging, options.log_level.upper()))

    nbhd = M.Neighborhood.query.get(name=options.neighborhood)
    if not nbhd:
        return 'Invalid neighborhood "%s".' % options.neighborhood
    admin_role = M.ProjectRole.by_name(
        'Admin', project=nbhd.neighborhood_project)
    nbhd_admin = admin_role.users_with_role(
        project=nbhd.neighborhood_project)[0].user
    log.info('Making updates as neighborhood admin "%s"' % nbhd_admin.username)

    q = {'neighborhood_id': nbhd._id,
         'is_nbhd_project': False, 'deleted': False}
    private_count = public_count = 0
    for projects in utils.chunked_find(M.Project, q):
        for p in projects:
            role_anon = M.ProjectRole.upsert(name='*anonymous',
                                             project_id=p.root_project._id)
            if M.ACE.allow(role_anon._id, 'read') not in p.acl:
                if options.test:
                    log.info('Would be made public: "%s"' % p.shortname)
                else:
                    log.info('Making public: "%s"' % p.shortname)
                    p.acl.append(M.ACE.allow(role_anon._id, 'read'))
                    with h.push_config(c, project=p, user=nbhd_admin):
                        ThreadLocalORMSession.flush_all()
                        g.post_event('project_updated')
                private_count += 1
            else:
                log.info('Already public: "%s"' % p.shortname)
                public_count += 1

    log.info('Already public: %s' % public_count)
    if options.test:
        log.info('Would be made public: %s' % private_count)
    else:
        log.info('Made public: %s' % private_count)
    return 0
Esempio n. 41
0
 def update(self, card=None, **kw):
     permissions = self._index_permissions()
     old_permissions = dict(permissions)
     for args in card:
         perm = args['id']
         new_group_ids = args.get('new', [])
         group_ids = args.get('value', [])
         if isinstance(new_group_ids, six.string_types):
             new_group_ids = [new_group_ids]
         if isinstance(group_ids, six.string_types):
             group_ids = [group_ids]
         # make sure the admin group has the admin permission
         if perm == 'admin':
             if c.project.is_root:
                 pid = c.project._id
             else:
                 pid = c.project.parent_id
             admin_group_id = str(
                 M.ProjectRole.query.get(project_id=pid, name='Admin')._id)
             if admin_group_id not in group_ids + new_group_ids:
                 flash(
                     'You cannot remove the admin group from the admin permission.', 'warning')
                 group_ids.append(admin_group_id)
         permissions[perm] = []
         role_ids = list(map(ObjectId, group_ids + new_group_ids))
         permissions[perm] = role_ids
     c.project.acl = []
     for perm, role_ids in six.iteritems(permissions):
         role_names = lambda ids: ','.join(sorted(
             pr.name for pr in M.ProjectRole.query.find(dict(_id={'$in': ids}))))
         old_role_ids = old_permissions.get(perm, [])
         if old_role_ids != role_ids:
             M.AuditLog.log('updated "%s" permissions: "%s" => "%s"',
                            perm, role_names(old_role_ids), role_names(role_ids))
         c.project.acl += [M.ACE.allow(rid, perm) for rid in role_ids]
     g.post_event('project_updated')
     redirect('.')
Esempio n. 42
0
    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()
        # has_wiki only indicates that wiki is enabled, but it does not mean
        # that it has any pages, so we should check if wiki repo actually
        # exists
        wiki_url = extractor.get_page_url('wiki_url')
        if not wiki_avail or not self.has_wiki_repo(wiki_url):
            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:
                    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
Esempio n. 43
0
 def success(self, app):
     with h.push_config(c, project=self.project, app=app):
         g.post_event('import_tool_task_succeeded',
                      self.importer.source,
                      self.importer.tool_label,
                      )
Esempio n. 44
0
 def revoke(self):
     require_access(self.neighborhood, 'admin')
     self.grant.delete()
     with h.push_context(self.project._id):
         g.post_event('project_updated')
     redirect(request.referer or '/')
Esempio n. 45
0
    project.tool_data.update(p.tool_data)

    for a in p.awards:
        M.AwardGrant(app_config_id=bson.ObjectId(),
                     award_id=a._id,
                     granted_to_project_id=project._id,
                     granted_by_neighborhood_id=nbhd._id)

    if p.icon:
        with open(p.icon) as icon_file:
            project.save_icon(p.icon, icon_file)

    project.notifications_disabled = False
    with h.push_config(c, project=project, user=p.admin):
        ThreadLocalORMSession.flush_all()
        g.post_event('project_updated')
    session(project).clear()
    return 0


def create_projects(projects, nbhd, options):
    for p in projects:
        r = create_project(Object(p), nbhd, options)
        if r != 0:
            sys.exit(r)


def main(options):
    log.addHandler(logging.StreamHandler(sys.stdout))
    log.setLevel(getattr(logging, options.log_level.upper()))
    log.debug(options)
Esempio n. 46
0
 def import_tool(self, project, user, mount_point=None,
                 mount_label=None, **kw):
     import_id_converter = ImportIdConverter.get()
     tracker_json = self._load_json(project)
     tracker_json['tracker_config']['options'].pop('ordinal', None)
     tracker_json['tracker_config']['options'].pop('mount_point', None)
     tracker_json['tracker_config']['options'].pop('mount_label', None)
     tracker_json['tracker_config']['options'].pop('import_id', None)
     app = project.install_app('tickets', mount_point, mount_label,
                               import_id={
                                   'source': self.source,
                                   'app_config_id': tracker_json['tracker_config']['_id'],
                               },
                               open_status_names=tracker_json[
                                   'open_status_names'],
                               closed_status_names=tracker_json[
                                   'closed_status_names'],
                               **tracker_json['tracker_config']['options']
                               )
     ThreadLocalORMSession.flush_all()
     try:
         M.session.artifact_orm_session._get().skip_mod_date = True
         for ticket_json in tracker_json['tickets']:
             reporter = self.get_user(ticket_json['reported_by'])
             owner = self.get_user(ticket_json['assigned_to'])
             with h.push_config(c, user=reporter, app=app):
                 self.max_ticket_num = max(
                     ticket_json['ticket_num'], self.max_ticket_num)
                 ticket = TM.Ticket(
                     app_config_id=app.config._id,
                     import_id=import_id_converter.expand(
                         ticket_json['ticket_num'], app),
                     description=self.annotate(
                         self.annotate(
                             ticket_json['description'],
                             owner, ticket_json[
                                 'assigned_to'], label=' owned'),
                         reporter, ticket_json[
                             'reported_by'], label=' created'),
                     created_date=dateutil.parser.parse(
                         ticket_json['created_date']),
                     mod_date=dateutil.parser.parse(
                         ticket_json['mod_date']),
                     ticket_num=ticket_json['ticket_num'],
                     summary=ticket_json['summary'],
                     custom_fields=ticket_json['custom_fields'],
                     status=ticket_json['status'],
                     labels=ticket_json['labels'],
                     votes_down=ticket_json['votes_down'],
                     votes_up=ticket_json['votes_up'],
                     votes=ticket_json['votes_up'] -
                     ticket_json['votes_down'],
                     assigned_to_id=owner._id,
                 )
                 # add an attachment to the ticket
                 ticket.add_multiple_attachments([File(a['url'])
                                                 for a in ticket_json['attachments']])
                 # trigger the private property
                 ticket.private = ticket_json['private']
                 self.process_comments(
                     ticket, ticket_json['discussion_thread']['posts'])
                 session(ticket).flush(ticket)
                 session(ticket).expunge(ticket)
         app.globals.custom_fields = tracker_json['custom_fields']
         self.process_bins(app, tracker_json['saved_bins'])
         app.globals.last_ticket_num = self.max_ticket_num
         M.AuditLog.log(
             'import tool %s from exported Allura JSON' % (
                 app.config.options.mount_point,
             ),
             project=project,
             user=user,
             url=app.url,
         )
         g.post_event('project_updated')
         app.globals.invalidate_bin_counts()
         ThreadLocalORMSession.flush_all()
         return app
     except Exception:
         h.make_app_admin_only(app)
         raise
     finally:
         M.session.artifact_orm_session._get().skip_mod_date = False
Esempio n. 47
0
def refresh_repo(repo, all_commits=False, notify=True, new_clone=False, commits_are_new=None):
    if commits_are_new is None:
        commits_are_new = not all_commits and not new_clone

    all_commit_ids = commit_ids = list(repo.all_commit_ids())
    if not commit_ids:
        # the repo is empty, no need to continue
        return
    new_commit_ids = unknown_commit_ids(commit_ids)
    stats_log = h.log_action(log, 'commit')
    for ci in new_commit_ids:
        stats_log.info(
            '',
            meta=dict(
                module='scm-%s' % repo.repo_id,
                read='0'))
    if not all_commits:
        # Skip commits that are already in the DB
        commit_ids = new_commit_ids
    log.info('Refreshing %d commits on %s', len(commit_ids), repo.full_fs_path)

    # Refresh commits
    seen = set()
    for i, oid in enumerate(commit_ids):
        repo.refresh_commit_info(oid, seen, not all_commits)
        if (i + 1) % 100 == 0:
            log.info('Refresh commit info %d: %s', (i + 1), oid)

    refresh_commit_repos(all_commit_ids, repo)

    # Refresh child references
    for i, oid in enumerate(commit_ids):
        ci = CommitDoc.m.find(dict(_id=oid), validate=False).next()
        refresh_children(ci)
        if (i + 1) % 100 == 0:
            log.info('Refresh child info %d for parents of %s',
                     (i + 1), ci._id)

    # Clear any existing caches for branches/tags
    if repo.cached_branches:
        repo.cached_branches = []
        session(repo).flush()

    if repo.cached_tags:
        repo.cached_tags = []
        session(repo).flush()
    # The first view can be expensive to cache,
    # so we want to do it here instead of on the first view.
    repo.get_branches()
    repo.get_tags()

    if commits_are_new:
        for commit in commit_ids:
            new = repo.commit(commit)
            user = User.by_email_address(new.committed.email)
            if user is None:
                user = User.by_username(new.committed.name)
            if user is not None:
                g.statsUpdater.newCommit(new, repo.app_config.project, user)
            actor = user or TransientActor(
                    activity_name=new.committed.name or new.committed.email)
            g.director.create_activity(actor, 'committed', new,
                                       related_nodes=[repo.app_config.project],
                                       tags=['commit', repo.tool.lower()])

        from allura.webhooks import RepoPushWebhookSender
        by_branches, by_tags = _group_commits(repo, commit_ids)
        params = []
        for b, commits in by_branches.iteritems():
            ref = u'refs/heads/{}'.format(b) if b != '__default__' else None
            params.append(dict(commit_ids=commits, ref=ref))
        for t, commits in by_tags.iteritems():
            ref = u'refs/tags/{}'.format(t)
            params.append(dict(commit_ids=commits, ref=ref))
        if params:
            RepoPushWebhookSender().send(params)

    log.info('Refresh complete for %s', repo.full_fs_path)
    g.post_event('repo_refreshed', len(commit_ids), all_commits, new_clone)

    # Send notifications
    if notify:
        send_notifications(repo, reversed(commit_ids))