def _get_id_filename(self, param):
        if not param:
            return None, None

        if param.isdigit():
            where_cond = 'id = %s'
        else:
            where_cond = 'file = %s'
        query = "SELECT id, file FROM download WHERE {0} LIMIT 1".format(
            where_cond)
        try:
            db = self.env.get_read_db()
            cursor = db.cursor()
            cursor.execute(query, param)
            row = cursor.fetchone()
            if row:
                return row[0], row[1]

        except Exception as e:
            env_name = conf.resolveProjectName(self.env)
            # this is the only way, since there are no common exceptions
            if e.__class__.__name__ == 'ProgrammingError':
                self.log.info(
                    'Error: "%s". DownloadsGlue should be disabled for "%s".' %
                    (e, env_name))
            else:
                self.log.exception(
                    "Download link could not be resolved in %s" % env_name)

        return None, None
Beispiel #2
0
    def render_admin_panel(self, req, category, page, path_info):
        """
        Process a request for an admin panel.

        :Returns: A tuple of the form `(template, data)`,
        """
        # Ensure the user has project admin permissions
        req.perm.assert_permission('TRAC_ADMIN')

        backups = []
        backup_href = Href('%s/admin/general/backup' % req.base_path)

        # Load the user based on authname
        user = get_userstore().getUser(req.authname)

        # Get the current environment name
        env_name = conf.resolveProjectName(self.env)

        # Initiate ProjectBackup, containing the backup/restore implementation
        prj = Project.get(env_name=env_name)
        pb = ProjectBackup(prj)
        backups = pb.get_backups()

        # Do the backup
        if req.path_info.endswith('backup/backup') and req.method == 'POST':
            try:
                pb.backup(user_id=user.id, description=req.args.get('description'))
                add_notice(req, _('Backup created'))
            except TracError, e:
                add_warning(req, _('Backup failed: %s' % e))

            # Return back to default backup page
            return req.redirect(backup_href())
    def __init__(self):
        if not self.static_htdocs_plugin_dirs or not self.static_htdocs_location:
            return

        base_url = self.config.get('multiproject', 'url_projects_path', '/')
        base_url = base_url.rstrip('/') # base_url '/' will be ''
        self.chrome_url = "{0}/{1}/chrome/".format(base_url, conf.resolveProjectName(self.env))
    def _get_id_filename(self, param):
        if not param:
            return None, None

        if param.isdigit():
            where_cond = 'id = %s'
        else:
            where_cond = 'file = %s'
        query = "SELECT id, file FROM download WHERE {0} LIMIT 1".format(where_cond)
        try:
            db = self.env.get_read_db()
            cursor = db.cursor()
            cursor.execute(query, param)
            row = cursor.fetchone()
            if row:
                return row[0], row[1]

        except Exception as e:
            env_name = conf.resolveProjectName(self.env)
            # this is the only way, since there are no common exceptions
            if e.__class__.__name__ == 'ProgrammingError':
                self.log.info('Error: "%s". DownloadsGlue should be disabled for "%s".' % (e, env_name))
            else:
                self.log.exception("Download link could not be resolved in %s" % env_name)

        return None, None
    def create_co_command(self, scm, username, scheme, repository_name):
        if scheme == 'ssh':
            scm = 'gitssh'

        params = {
            'scheme': scheme,
            'username': username,
            'domain': conf.domain_name,
            'scm': scm,
            'project': conf.resolveProjectName(self.env),
            'repository_name': repository_name
        }

        # username was taken from use because of problems resolving nokia account id
        co_commands = {}
        co_commands[
            'git'] = 'git clone %(scheme)s://%(domain)s/%(project)s/git/%(repository_name)s'
        co_commands[
            'gitssh'] = 'git clone %(scheme)s://git@%(domain)s/%(project)s/git/%(repository_name)s'
        co_commands[
            'svn'] = 'svn co %(scheme)s://%(domain)s/%(project)s/%(scm)s/%(repository_name)s'
        co_commands[
            'hg'] = 'hg clone %(scheme)s://%(domain)s/%(project)s/%(scm)s/%(repository_name)s'

        return co_commands[scm] % params
Beispiel #6
0
    def __init__(self):
        if not self.static_htdocs_plugin_dirs or not self.static_htdocs_location:
            return

        base_url = self.config.get('multiproject', 'url_projects_path', '/')
        base_url = base_url.rstrip('/')  # base_url '/' will be ''
        self.chrome_url = "{0}/{1}/chrome/".format(
            base_url, conf.resolveProjectName(self.env))
Beispiel #7
0
 def get_navigation_items(self, req):
     home = Href(conf.url_home_path)
     if 'WIKI_VIEW' in req.perm('wiki'):
         # Show Wiki on project Help on home
         if conf.resolveProjectName(self.env) != 'home':
             yield ('mainnav', 'wiki',
                    tag.a(_('Wiki'), href=req.href.wiki(), accesskey=1))
         else:
             yield ('mainnav', 'wiki', tag.a('Help', href=req.href.wiki()))
         # Change metanav to direct home wiki
         yield ('metanav', 'help',
                tag.a(_('Help'), href=home('wiki'), accesskey=6))
    def get_download_data(self):
        platforms = {}
        downloads = []

        def download_from_sql_row(row):
            return {
                'id': row[0],
                'file': row[1],
                'description': row[2],
                'time': row[3],  # in timestamp, not in utimestamp
                'count': row[4],
                'author': row[5],
                'platform': row[6],  # Will be string instead
                'featured': row[7]
            }

        try:
            db = self.env.get_read_db()
            cursor = db.cursor()
            cursor.execute("SELECT id, name FROM platform")
            for row in cursor:
                platforms[row[0]] = row[1]
            cursor.execute(
                "SELECT id, file, description, time, count, author, platform, featured FROM download"
            )
            for row in cursor:
                downloads.append(download_from_sql_row(row))
        except Exception as e:
            env_name = conf.resolveProjectName(self.env)
            # this is the only way, since there are no common exceptions
            if e.__class__.__name__ == 'ProgrammingError':
                printout("{0}: Get download data failed: {1}".format(
                    env_name, e))
                return None
            else:
                raise
        userstore = get_userstore()
        for download in downloads:
            user = userstore.getUser(download['author'])
            if user:
                download['author_id'] = user.id
            else:
                download['author_id'] = None
            if not download['platform']:
                download['platform'] = ''
            else:
                download['platform'] = platforms[download['platform']]
        return downloads
 def _get_id_filename_by_filename(self, filename):
     try:
         db = self.env.get_read_db()
         cursor = db.cursor()
         cursor.execute("SELECT id, file FROM download WHERE file = %s", filename)
         row = cursor.fetchone()
         if row:
             return row[0]
     except Exception as e:
         env_name = conf.resolveProjectName(self.env)
         # this is the only way, since there are no common exceptions
         if e.__class__.__name__ == 'ProgrammingError':
             self.log.warning('Error: "%s". DownloadsGlue should be disabled for "%s".' % (e, env_name))
         else:
             self.log.exception("Download link could not be resolved in %s" % env_name)
     return None
    def get_download_data(self):
        platforms = {}
        downloads = []

        def download_from_sql_row(row):
            return {
                'id': row[0],
                'file': row[1],
                'description': row[2],
                'time': row[3], # in timestamp, not in utimestamp
                'count': row[4],
                'author': row[5],
                'platform': row[6], # Will be string instead
                'featured': row[7]
            }

        try:
            db = self.env.get_read_db()
            cursor = db.cursor()
            cursor.execute("SELECT id, name FROM platform")
            for row in cursor:
                platforms[row[0]] = row[1]
            cursor.execute("SELECT id, file, description, time, count, author, platform, featured FROM download")
            for row in cursor:
                downloads.append(download_from_sql_row(row))
        except Exception as e:
            env_name = conf.resolveProjectName(self.env)
            # this is the only way, since there are no common exceptions
            if e.__class__.__name__ == 'ProgrammingError':
                printout("{0}: Get download data failed: {1}".format(env_name, e))
                return None
            else:
                raise
        userstore = get_userstore()
        for download in downloads:
            user = userstore.getUser(download['author'])
            if user:
                download['author_id'] = user.id
            else:
                download['author_id'] = None
            if not download['platform']:
                download['platform'] = ''
            else:
                download['platform'] = platforms[download['platform']]
        return downloads
Beispiel #11
0
    def create_co_command(self, scm, username, scheme):
        if scheme == 'ssh':
            scm = 'gitssh'

        params = {'scheme': scheme,
                  'username': username,
                  'domain': conf.domain_name,
                  'scm': scm,
                  'project': conf.resolveProjectName(self.env)}

        # username was taken from use because of problems resolving nokia account id
        co_commands = {}
        co_commands['git'] = 'git clone %(scheme)s://%(domain)s/%(scm)s/%(project)s.git'
        co_commands['gitssh'] = 'git clone %(scheme)s://git@%(domain)s/%(project)s.git'
        co_commands['svn'] = 'svn co %(scheme)s://%(domain)s/%(scm)s/%(project)s'
        co_commands['hg'] = 'hg clone %(scheme)s://%(domain)s/%(scm)s/%(project)s'

        return co_commands[scm] % params
 def _get_id_filename_by_filename(self, filename):
     try:
         db = self.env.get_read_db()
         cursor = db.cursor()
         cursor.execute("SELECT id, file FROM download WHERE file = %s",
                        filename)
         row = cursor.fetchone()
         if row:
             return row[0]
     except Exception as e:
         env_name = conf.resolveProjectName(self.env)
         # this is the only way, since there are no common exceptions
         if e.__class__.__name__ == 'ProgrammingError':
             self.log.warning(
                 'Error: "%s". DownloadsGlue should be disabled for "%s".' %
                 (e, env_name))
         else:
             self.log.exception(
                 "Download link could not be resolved in %s" % env_name)
     return None
    def check_permission(self, action, username, resource, perm):
        """
        Checks permissions - Actual checking is done on CQDEPermissionPolicy class
        """
        # FIXME: Dirty hack to screw ILegacyAttachmentPolicy.
        perm_maps = {
            "ATTACHMENT_CREATE": {
                "ticket": "TICKET_APPEND",
                "wiki": "WIKI_MODIFY",
                "milestone": "MILESTONE_MODIFY",
                "discussion": "DISCUSSION_ATTACH",
            },
            "ATTACHMENT_VIEW": {
                "ticket": "TICKET_VIEW",
                "wiki": "WIKI_VIEW",
                "milestone": "MILESTONE_VIEW",
                "discussion": "DISCUSSION_ATTACH",
            },
            "ATTACHMENT_DELETE": {
                "ticket": "TICKET_ADMIN",
                "wiki": "WIKI_DELETE",
                "milestone": "MILESTONE_DELETE",
                "discussion": "DISCUSSION_ATTACH",
            },
        }
        perm_map = perm_maps.get(action)
        if perm_map and resource and resource.realm == "attachment":
            action = perm_map.get(resource.parent.realm)

        policy = CQDEPermissionPolicy(self.env)

        # Project context check
        if resource and resource.realm == "project":
            # NOTE: Load project to get environment key required by check_permission
            # NOTE: Internal TracEnvironment cannot be used because env can be home, whereas project id is not
            project = Project.get(id=resource.id)
            if project and policy.check_permission(project.trac_environment_key, action, username):
                return True
            return False

        # Ticket authors should be able to edit their own tickets
        # (excluding 'anonymous')
        if (
            username != "anonymous"
            and resource
            and resource.id
            and resource.realm == "ticket"
            and action in ("TICKET_CHGPROP", "TICKET_EDIT_DESCRIPTION")
        ):
            ticket = Ticket(self.env, int(resource.id))
            if ticket.exists and username == ticket["reporter"]:
                return True

        # Load lightweight trac environment to get environment id, required by internal check_permission
        env_name = conf.resolveProjectName(self.env)
        environment = TracEnvironment.read(env_name)

        # Check permission using global permission policy and storage
        if not policy.check_permission(environment.environment_id, action, username):
            return False

        # Additional, resources based checks

        # User author check
        if action in ("USER_ADMIN", "USER_AUTHOR", "USER_VIEW", "USER_MODIFY", "USER_DELETE") and resource:
            # Check if USER_ADMIN permission in home project
            home_perm = PermissionCache(conf.home_env, username)
            if "USER_ADMIN" in home_perm:
                return True

            userstore = conf.getUserStore()
            resource_user = userstore.getUserWhereId(resource.id)
            user = userstore.getUser(username)

            # Allow manage own and authored account
            if action in ("USER_ADMIN", "USER_AUTHOR"):
                return resource_user.author_id == user.id or resource_user.id == user.id

            # Allow to manage itself
            return resource_user.id == user.id

        return True
Beispiel #14
0
 def get_admin_panels(self, req):
     """ Introduce new item into admin navigation panel
     """
     if conf.resolveProjectName(self.env) == "home":
         if 'TRAC_ADMIN' in req.perm:
             yield ('general', 'General', 'migrations', 'Migrations')
Beispiel #15
0
    def process_request(self, req):
        """
        Handle the export requests

        :raises: TracError in case of failure
        """
        req.perm.require('BROWSER_VIEW')
        req.perm.require('FILE_VIEW')

        # Get default repository and its type
        rm = RepositoryManager(self.env)
        repo = rm.get_repository('')
        repo_type = rm.repository_type
        svn_path = 'trunk'
        format = plaintext(req.args.get('format', 'zip'))

        # Get revision info. For svn it's in format: <revnum>/<path>
        revision = plaintext(str(req.args.get('rev', repo.get_youngest_rev())))
        if repo_type == 'svn':
            revision = repo.get_youngest_rev()
            svn_path = req.args.get('rev', svn_path)

        # Validate if given revision really exists
        try:
            revision = repo.normalize_rev(revision)
        except NoSuchChangeset:
            raise HTTPNotFound('No such changeset')

        # Validate format
        if format not in self.formats:
            raise TracError('Format is not supported')

        # Load project object based on current environment
        env_name = conf.resolveProjectName(self.env)
        repo_type = self.env.config.get('trac', 'repository_type')
        repo_dir = conf.getEnvironmentVcsPath(env_name)
        project = Project.get(env_name=env_name)

        if repo_type not in conf.supported_scm_systems:
            raise TracError('Non-supported VCS type')

        # Create temporary directory with appropriate subdirectory where to export repository
        tempfd = tempfile.NamedTemporaryFile(delete=False)

        # Dump the repository per type, into defined location
        try:
            if repo_type == 'git':
                # Use short revision format
                revision = revision[:6]
                prefix = '%s-%s' % (env_name, revision[:6])
                self._archive_git(repo_dir, revision, format, tempfd.name, prefix)

            elif repo_type == 'hg':
                # In case of both local:global revision format, use only global
                if ':' in revision:
                    revision = revision.split(':', 1)[1]
                prefix = '%s-%s' % (env_name, revision[:6])
                self._archive_hg(repo_dir, revision, format, tempfd.name, prefix)

            elif repo_type == 'svn':
                assert format == 'zip', 'Only zip format is supported for subversion'

                # Redirect to Trac's internal changeset functionality
                # Example: https://localhost/svnproject/changeset/4/trunk?old_path=%2F&format=zip
                changeset_href = Href('/%s/changeset' % env_name)
                return req.redirect(changeset_href(revision, svn_path, old_path='/', format='zip'))

        # Redirect raises RequestDone: re-raise it
        except RequestDone:
            raise

        except Exception, err:
            self.env.log.exception('Repository dump failed: %s' % err)
            raise TracError('Repository archive failed - please try again later')
Beispiel #16
0
def _get_trac_project_name(env):
    """Helper for migrating to environment based constructors."""
    from multiproject.common.environment import TracEnvironment
    return TracEnvironment.read(conf.resolveProjectName(env)).identifier
Beispiel #17
0
    def process_request(self, req):
        """
        Handle the export requests

        :raises: TracError in case of failure
        """
        req.perm.require('BROWSER_VIEW')
        req.perm.require('FILE_VIEW')
        repository_name = req.path_info.split("/")[-1]
        # Get default repository and its type
        rm = RepositoryManager(self.env)
        list_repos = rm.get_real_repositories()
        repo = None
        repo_type = None
        for r in list_repos:
            if r.get_base().split("/")[-1].lower() == repository_name:
                repo = r
                break
        repo_type = repo.get_base().split(":")[0]
        svn_path = 'trunk'
        format = plaintext(req.args.get('format', 'zip'))
        conf.log.exception("Repotype at beginning: %s" % repo_type)
        # Get revision info. For svn it's in format: <revnum>/<path>
        revision = plaintext(str(req.args.get('rev', repo.get_youngest_rev())))

        # Validate if given revision really exists
        try:
            revision = repo.normalize_rev(revision)
        except NoSuchChangeset:
            raise HTTPNotFound('No such changeset')

        # Validate format
        if format not in self.formats:
            raise TracError('Format is not supported')

        # Load project object based on current environment
        env_name = conf.resolveProjectName(self.env)
        #repo_type = self.env.config.get('trac', 'repository_type')
        repo_dir = conf.getEnvironmentVcsPath(env_name, repo_type,
                                              repository_name)
        project = Project.get(env_name=env_name)

        if repo_type not in conf.supported_scm_systems:
            raise TracError('Non-supported VCS type')

        # Create temporary directory with appropriate subdirectory where to export repository
        tempfd = tempfile.NamedTemporaryFile(delete=False)

        # Dump the repository per type, into defined location
        conf.log.exception("Repotype: %s, repo_dir: %s" %
                           (repo_type, repo_dir))
        try:
            if repo_type == 'git':
                # Use short revision format
                revision = revision[:6]
                prefix = '%s-%s' % (env_name, revision[:6])
                self._archive_git(repo_dir, revision, format, tempfd.name,
                                  prefix)

            elif repo_type == 'hg':
                # In case of both local:global revision format, use only global
                if ':' in revision:
                    revision = revision.split(':', 1)[1]
                prefix = '%s-%s' % (env_name, revision[:6])
                self._archive_hg(repo_dir, revision, format, tempfd.name,
                                 prefix)

            elif repo_type == 'svn':
                assert format == 'zip', 'Only zip format is supported for subversion'

                # Redirect to Trac's internal changeset functionality
                # Example: https://localhost/svnproject/changeset/4/trunk?old_path=%2F&format=zip
                changeset_href = Href('/%s/changeset' % env_name)
                return req.redirect(
                    changeset_href(revision,
                                   repository_name + "/",
                                   format='zip'))

        # Redirect raises RequestDone: re-raise it
        except RequestDone:
            raise

        except Exception, err:
            self.env.log.exception('Repository dump failed: %s' % err)
            raise TracError(
                'Repository archive failed - please try again later')