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 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
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_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
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
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')
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')
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
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')