Example #1
0
    def render_admin_panel(self, req, cat, page, path_info):
        """
        Returns the admin view and handles the form actions
        """
        req.perm.require('TRAC_ADMIN')

        project = Project.get(self.env)

        if req.method == 'POST':
            myprojects_url = conf.url_home_path + "/myprojects"
            conf.log.exception("Redirect URL: %s" % myprojects_url)
            thisurl = Href(req.base_path)(req.path_info)
            context = Context.from_request(req)

            # Handle project remove
            if 'remove' in req.args:
                # Don't allow removing home
                if project.env_name == conf.sys_home_project_name:
                    add_warning(req, 'Cannot remove home project')
                    return req.redirect(thisurl)

                # Archive the project before removal
                archive = ProjectArchive()
                archived = archive.archive(project)

                if not archived:
                    add_warning(req, 'Could not archive project "%s". Will not remove the project' % project.project_name)
                    return req.redirect(thisurl)

                # Notify listeners. The project object still exists, but database does not
                for listener in self.project_change_listeners:
                    listener.project_archived(project)

                # Do the actual project removal
                projects = Projects()
                if projects.remove_project(project):
                    # Notify listeners. The project object still exists, but database does not
                    for listener in self.project_change_listeners:
                        listener.project_deleted(project)

                    # NOTE: We no longer have project tables/session etc available
                    req.redirect(myprojects_url)

                else:
                    add_warning(req, 'Could not remove project "%s". Try again later' % project.project_name)
                    return req.redirect(thisurl)

        add_script(req, 'multiproject/js/jquery-ui.js')
        add_script(req, 'multiproject/js/multiproject.js')
        add_script(req, 'multiproject/js/admin_system.js')
        add_stylesheet(req, 'multiproject/css/jquery-ui.css')

        # NOTE: Trac automatically puts 'project' dict in chrome thus it cannot be used
        data = {'multiproject': {
            'project':project,
            'home_url':conf.url_home_path
        }}
        return 'admin_system.html', data
Example #2
0
    def remove_project(self, req):
        """
        Handler for removing project

        :param Request req: Trac request

        Handler expects to have following arguments in it:

        - project: Name of the project env
        - goto: Optional URL where to go after project removal. Defaults to /home/myprojects

        """
        backurl = req.args.get('goto', ProjectListModule.home('myprojects'))
        short_name = req.args.get('project')
        if not short_name:
            return self.remove_failure(req)
        if req.args.get('cancel'):
            add_notice(req, 'Project deletion cancelled')
            return self.remove_failure(req)
        author = req.authname
        project = Project.get(env_name=short_name)

        if project is None:
            add_warning(req, 'Specified project does not exist!')
            return self.remove_failure(req)

        # Don't allow removing home
        if project.env_name == conf.sys_home_project_name:
            add_warning(req, 'Cannot remove home project')
            return self.remove_failure(req)
        if req.method != 'POST':
            return self.remove_failure(req, project=project)

        try:
            project.validate()
        except ProjectValidationException:
            req.redirect(backurl)

        # Check the permissions and method
        prjs = Projects()
        if ('TRAC_ADMIN' in req.perm or prjs.is_project_owner(project.env_name, author)) and req.method == 'POST':
            archive = ProjectArchive()
            # Archive the project before removal
            if not archive.archive(project):
                add_warning(req, 'Could not archive project "%s". Will not remove the project' % project.project_name)
            elif prjs.remove_project(project):
                # Notify listeners
                for listener in self.project_change_listeners:
                    listener.project_deleted(project)
                # Notify end user
                add_notice(req, 'Project "%s" removed' % project.project_name)
            else:
                add_warning(req, 'Could not remove project "%s". Try again later' % project.project_name)
        else:
            add_warning(req, 'You are not allowed to remove project "%s" (check permissions and method)' % project.project_name)

        req.redirect(backurl)
Example #3
0
    def render_admin_panel(self, req, cat, page, path_info):
        req.perm.require("TRAC_ADMIN")
        arch = ProjectArchive()
        projects = arch.list()

        if req.method == 'POST':
            archived_project_id = int(req.args.get('archived_project_id', 0))
            action = req.args.get('action', 'noop')

            try:
                if action == 'restore':
                    if arch.restore(archived_project_id, self.env):
                        add_notice(req, _('Restored project successfully'))

                elif action == 'remove':
                    if arch.remove(archived_project_id):
                        add_notice(req, _('Removed project successfully'))

                elif action == 'remove_expired':
                    if arch.remove_expired():
                        add_notice(req, _('Removed expired projects successfully'))

                else:
                    add_warning(req, _('Unknown action'))

            except Exception:
                add_warning(req, _('Failed to complete the action'))
                self.log.exception('Failed to {0} for project {1}'.format(action, archived_project_id))

            # After post method, redirect back to listing
            return req.redirect(req.href('/admin/projects/prjarchive'))

        add_script(req, 'multiproject/js/jquery-ui.js')
        add_stylesheet(req, 'multiproject/css/jquery-ui.css')
        add_script(req, 'multiproject/js/multiproject.js')
        add_script(req, 'multiproject/js/admin_project_archive.js')

        return 'multiproject_admin_project_archive.html', {'projects': projects}
Example #4
0
    def render_admin_panel(self, req, cat, page, path_info):
        req.perm.require("TRAC_ADMIN")
        arch = ProjectArchive()
        projects = arch.list()

        if req.method == 'POST':
            archived_project_id = int(req.args.get('archived_project_id', 0))
            action = req.args.get('action', 'noop')

            try:
                if action == 'restore':
                    if arch.restore(archived_project_id, self.env):
                        add_notice(req, _('Restored project successfully'))

                elif action == 'remove':
                    if arch.remove(archived_project_id):
                        add_notice(req, _('Removed project successfully'))

                elif action == 'remove_expired':
                    if arch.remove_expired():
                        add_notice(req,
                                   _('Removed expired projects successfully'))

                else:
                    add_warning(req, _('Unknown action'))

            except Exception:
                add_warning(req, _('Failed to complete the action'))
                self.log.exception('Failed to {0} for project {1}'.format(
                    action, archived_project_id))

            # After post method, redirect back to listing
            return req.redirect(req.href('/admin/projects/prjarchive'))

        add_script(req, 'multiproject/js/jquery-ui.js')
        add_stylesheet(req, 'multiproject/css/jquery-ui.css')
        add_script(req, 'multiproject/js/multiproject.js')
        add_script(req, 'multiproject/js/admin_project_archive.js')

        return 'multiproject_admin_project_archive.html', {
            'projects': projects
        }
Example #5
0
    def remove_project(self, req):
        """
        Handler for removing project

        :param Request req: Trac request

        Handler expects to have following arguments in it:

        - project: Name of the project env
        - goto: Optional URL where to go after project removal. Defaults to /home/myprojects

        """
        backurl = req.args.get('goto', ProjectListModule.home('myprojects'))
        short_name = req.args.get('project')
        if not short_name:
            return self.remove_failure(req)
        if req.args.get('cancel'):
            add_notice(req, 'Project deletion cancelled')
            return self.remove_failure(req)
        author = req.authname
        project = Project.get(env_name=short_name)

        if project is None:
            add_warning(req, 'Specified project does not exist!')
            return self.remove_failure(req)

        # Don't allow removing home
        if project.env_name == conf.sys_home_project_name:
            add_warning(req, 'Cannot remove home project')
            return self.remove_failure(req)
        if req.method != 'POST':
            return self.remove_failure(req, project=project)

        try:
            project.validate()
        except ProjectValidationException:
            req.redirect(backurl)

        # Check the permissions and method
        prjs = Projects()
        if ('TRAC_ADMIN' in req.perm or prjs.is_project_owner(
                project.env_name, author)) and req.method == 'POST':
            archive = ProjectArchive()
            # Archive the project before removal
            if not archive.archive(project):
                add_warning(
                    req,
                    'Could not archive project "%s". Will not remove the project'
                    % project.project_name)
            elif prjs.remove_project(project):
                # Notify listeners
                for listener in self.project_change_listeners:
                    listener.project_deleted(project)
                # Notify end user
                add_notice(req, 'Project "%s" removed' % project.project_name)
            else:
                add_warning(
                    req, 'Could not remove project "%s". Try again later' %
                    project.project_name)
        else:
            add_warning(
                req,
                'You are not allowed to remove project "%s" (check permissions and method)'
                % project.project_name)

        req.redirect(backurl)
Example #6
0
    def render_admin_panel(self, req, cat, page, path_info):
        """
        Returns the admin view and handles the form actions
        """
        req.perm.require('TRAC_ADMIN')

        project = Project.get(self.env)

        if req.method == 'POST':
            myprojects_url = conf.url_home_path + "/myprojects"
            conf.log.exception("Redirect URL: %s" % myprojects_url)
            thisurl = Href(req.base_path)(req.path_info)
            context = Context.from_request(req)

            # Handle project remove
            if 'remove' in req.args:
                # Don't allow removing home
                if project.env_name == conf.sys_home_project_name:
                    add_warning(req, 'Cannot remove home project')
                    return req.redirect(thisurl)

                # Archive the project before removal
                archive = ProjectArchive()
                archived = archive.archive(project)

                if not archived:
                    add_warning(
                        req,
                        'Could not archive project "%s". Will not remove the project'
                        % project.project_name)
                    return req.redirect(thisurl)

                # Notify listeners. The project object still exists, but database does not
                for listener in self.project_change_listeners:
                    listener.project_archived(project)

                # Do the actual project removal
                projects = Projects()
                if projects.remove_project(project):
                    # Notify listeners. The project object still exists, but database does not
                    for listener in self.project_change_listeners:
                        listener.project_deleted(project)

                    # NOTE: We no longer have project tables/session etc available
                    req.redirect(myprojects_url)

                else:
                    add_warning(
                        req, 'Could not remove project "%s". Try again later' %
                        project.project_name)
                    return req.redirect(thisurl)

        add_script(req, 'multiproject/js/jquery-ui.js')
        add_script(req, 'multiproject/js/multiproject.js')
        add_script(req, 'multiproject/js/admin_system.js')
        add_stylesheet(req, 'multiproject/css/jquery-ui.css')

        # NOTE: Trac automatically puts 'project' dict in chrome thus it cannot be used
        data = {
            'multiproject': {
                'project': project,
                'home_url': conf.url_home_path
            }
        }
        return 'admin_system.html', data
Example #7
0
class ProjectStatisticsAdminPanel(Component):
    """
    Trac admin component for project statistics: Admin > Statistics > Projects
    """
    implements(IAdminPanelProvider)

    def get_admin_panels(self, req):
        """
        Hook into admin panel by adding the Projects -section
        """
        if 'TRAC_ADMIN' in req.perm:
            yield ('statistics', _('Statistics'), 'projects', _('Projects'))

    def render_admin_panel(self, req, cat, page, path_info):
        """
        Handles the admin page requests
        """
        req.perm.require("TRAC_ADMIN")

        # Default values
        perm = 'PROJECT_VIEW'
        categories = []
        results = []
        resultsby = 'week'
        event_type = 'release_downloaded'
        maxresult_opts = [5, 10, 30, 50, 100, 0]
        maxresults = 10
        now = datetime.utcnow()
        weekday, endday = calendar.monthrange(now.year, now.month)
        starttime = datetime(year=now.year, month=now.month, day=1, hour=0, minute=0, second=0)
        endtime = datetime(year=now.year, month=now.month, day=endday, hour=23, minute=59, second=59)

        # This ain't timemachine
        if endtime > now:
            endtime = now

        # Set or reset filters back to defaults
        if 'update' in req.args.keys():
            # Try parsing the dates
            try:
                starttime = datetime.strptime(req.args.get('starttime', ''), DATEFORMATS['py'])
                endtime = datetime.strptime(req.args.get('endtime', ''), DATEFORMATS['py'])

                # Set the time to be from 00:00 -- 23:59:59
                starttime = datetime(
                    year=starttime.year,
                    month=starttime.month,
                    day=starttime.day,
                    hour=0, minute=0, second=0
                )
                endtime = datetime(
                    year=endtime.year,
                    month=endtime.month,
                    day=endtime.day,
                    hour=23, minute=59, second=59
                )

            except Exception, ex:
                self.log.warning('Date conversion failed: %s' % ex)
                add_warning(req, _('Please check the time range values as they seem inappropriate. The format is: MM/DD/YY'))

            # Set filters
            # NOTE: UI allows only one category atm
            categories_raw = req.args.get('categories', '')
            if categories_raw.strip():
                categories = [plaintext(categories_raw)]
            resultsby = req.args.get('resultsby', resultsby)

            # Get and check optional event type
            if req.args.get('event_type', '') in EVENT_DESCRIPTIONS.keys():
                event_type = req.args.get('event_type', event_type)

            # Get and check optional max results option
            maxresults = req.args.get('maxresults', maxresults)
            if isinstance(maxresults, basestring):
                maxresults = int(maxresults) if maxresults.isdigit() else 10

        # Fetch statistics: get project ids based on user rights and optional list of categories
        # NOTE: Set initial value to zero because otherwise it is considered as "fetch all"
        project_ids = [0]
        for project in Projects().get_projects_with_params(username=req.authname, perm=perm, categories=categories):
            project_ids.append(project.id)

        # Fetch project ids also from archived projects if category is not selected (archived projects no longer have one)
        if not categories:
            for archived_project in ProjectArchive().get_projects_with_params(username=req.authname, perm=perm):
                project_ids.append(archived_project.id)
        else:
            # Note about the archived project limitation
            add_warning(req, _("Archived projects are left out from statistics as they don't have category information"))

        # Fetch results either by week or project
        fetch_start = datetime.utcnow()
        if resultsby == 'project':
            results = self._get_activity_statistics_per_project(starttime, endtime, event_type, project_ids, max=maxresults)
        if resultsby == 'week':
            results = self._get_activity_statistics_per_week(starttime, endtime, event_type, project_ids, max=maxresults)

        self.log.info('Loaded statistics in %s msec' % (datetime.utcnow() - fetch_start).microseconds)

        summary = self._get_summary()

        # Calculate total
        total = sum([r['count'] for r in results])

        categories_desc = ','.join(categories) if categories else 'all'
        self.log.info('User %s is retrieving download statistics from %d projects (categories: %s), found: %d' %
                      (req.authname, len(project_ids), categories_desc, len(results)))

        # Event types, sorted by description
        event_types = sorted(EVENT_DESCRIPTIONS.items(), key=itemgetter(1))

        # Add resources
        add_script(req, 'multiproject/js/jquery-ui.js')
        add_stylesheet(req, 'multiproject/css/jquery-ui.css')
        add_stylesheet(req, 'multiproject/css/statistics.css')
        add_script(req, 'multiproject/js/raphael.js')
        add_script(req, 'multiproject/js/ico.js')
        add_script(req, 'multiproject/js/admin_analytics_projects.js')

        # Set parameters to view
        data = {
            'summary':summary,
            'perm':perm,
            'grouptypes': ['project', 'week'],
            'categories':categories,
            'resultsby':resultsby,
            'starttime':starttime,
            'endtime':endtime,
            'event_types':event_types,
            'event_type':event_type,
            'event':EVENT_DESCRIPTIONS[event_type],
            'dateformats':DATEFORMATS,
            'results':results,
            'results_json':json.dumps(results),
            'total':total,
            'categories_desc':categories_desc,
            'maxresults':maxresults,
            'maxresult_opts':maxresult_opts
        }

        return 'admin_analytics_projects.html', data