def render_admin_panel(self, req, cat, page, path_info): if not req.perm.has_permission('SITEUPLOAD_MANAGE') and \ not req.perm.has_permission('SITEUPLOAD_UPLOAD'): raise PermissionError('SITEUPLOAD_MANAGE or SITEUPLOAD_UPLOAD') target_path = os.path.join(self.env.path, 'htdocs') readonly = False if not (os.path.exists(target_path) and \ os.path.isdir(target_path) and \ os.access(target_path, os.F_OK + os.W_OK)): readonly = True if req.method == 'POST': if req.args.has_key('delete'): if not req.perm.has_permission('SITEUPLOAD_MANAGE'): raise PermissionError('SITEUPLOAD_MANAGE') self._do_delete(req) elif req.args.has_key('upload'): if not req.perm.has_permission('SITEUPLOAD_UPLOAD'): raise PermissionError('SITEUPLOAD_UPLOAD') self._do_upload(req) else: self.log.warning('Unknown POST request: %s', req.args) req.redirect(self.env.href.admin(cat, page)) data = {'siteupload': {'readonly': readonly}} self._render_view(req, data) return 'upload.html', data
def reparent_resource_tags(self, req, old_resource, resource, comment=u''): assert old_resource.realm == self.realm assert resource.realm == self.realm if not self.check_permission(req.perm(old_resource), 'modify'): raise PermissionError(resource=old_resource, env=self.env) if not self.check_permission(req.perm(resource), 'modify'): raise PermissionError(resource=resource, env=self.env) tag_resource(self.env, self.realm, to_unicode(old_resource.id), to_unicode(resource.id))
def require(self, action, realm_or_resource=None, id=False, version=False, message=None): if message is None: raise PermissionError(action) else: raise PermissionError(msg=message)
def check_permission(self, req, realm, key_str=None, operation='set', name=None, value=None): if 'TEST_VIEW' not in req.perm: raise PermissionError('TEST_VIEW', realm) if operation == 'set' and 'TEST_MODIFY' not in req.perm: raise PermissionError('TEST_MODIFY', realm)
def require(self, action, realm_or_resource=None, id=False, version=False): if action in self.grant: return if action in self.revoke: resource = self._normalize_resource(realm_or_resource, id, version) raise PermissionError(action, resource, self.perm.env) self.perm.require(action, realm_or_resource, id, version)
def process_request(self, req): """Process the request.""" id = int(req.args.get('id')) req.perm('ticket', id).require('TICKET_VIEW') if 'TICKET_REMINDER_MODIFY' not in req.perm and \ 'TICKET_ADMIN' not in req.perm: raise PermissionError('TICKET_REMINDER_MODIFY', req.perm._resource, self.env) ticket = Ticket(self.env, id) if 'cancel' in req.args: req.redirect(get_resource_url(self.env, ticket.resource, req.href)) ticket_name = get_resource_name(self.env, ticket.resource) ticket_url = get_resource_url(self.env, ticket.resource, req.href) add_link(req, 'up', ticket_url, ticket_name) add_ctxtnav(req, _('Back to %(ticket)s', ticket=ticket_name), ticket_url) add_stylesheet(req, 'ticketreminder/css/ticketreminder.css') if req.args['action'] == "addreminder": return self._process_add(req, ticket) elif req.args['action'] == "deletereminder": return self._process_delete(req, ticket) else: raise ValueError('Unknown action "%s"' % (req.args['action'], ))
def process_request(self, req): try: if req.method == 'POST': ctype = req.get_header('Content-Type') ctype, options = cgi.parse_header(ctype) if ctype not in ('application/x-www-form-urlencoded', 'multipart/form-data'): if not self._is_xhr(req): raise PermissionError() req.args['attachment'] = PseudoAttachmentObject( self.env, req) req.args['compact'] = req.get_header( 'X-TracDragDrop-Compact') if req.get_header('X-TracDragDrop-Replace'): req.args['replace'] = '1' # XXX dirty hack req.redirect_listeners.insert(0, self._redirect_listener) action = req.args['action'] if action == 'new': return self._delegate_new_request(req) if action == 'delete': return self._delegate_delete_request(req) raise TracError('Invalid request') except RequestDone: raise except TracError, e: return self._send_message_on_except(req, e, 500)
def process_request(self, req): link = req.args.get('link', '') parts = link.split(':', 1) if len(parts) > 1: resolver, target = parts if target[:1] + target[-1:] not in ('""', "''"): link = '%s:"%s"' % (resolver, target) from trac.web.chrome import web_context link_frag = extract_link(self.env, web_context(req), link) def get_first_href(item): """Depth-first search for the first `href` attribute.""" if isinstance(item, Element): href = item.attrib.get('href') if href is not None: return href if isinstance(item, Fragment): for each in item.children: href = get_first_href(each) if href is not None: return href if isinstance(link_frag, (Element, Fragment)): href = get_first_href(link_frag) if href is None: # most probably no permissions to view raise PermissionError(_("Can't view %(link)s:", link=link)) else: href = req.href(link.rstrip(':')) req.redirect(href)
def set_resource_tags(self, req, ticket_or_resource, tags, comment=u'', when=None): try: resource = ticket_or_resource.resource except AttributeError: resource = ticket_or_resource assert resource.realm == self.realm if not self._check_permission(req, resource, 'modify'): raise PermissionError(resource=resource, env=self.env) tag_set = set(tags) # Processing a call from TracTags, try to alter the ticket. tkt = Ticket(self.env, resource.id) all = self._ticket_tags(tkt) # Avoid unnecessary ticket changes, considering comments below. if tag_set != all: # Will only alter tags in 'keywords' ticket field. keywords = split_into_tags(tkt['keywords']) # Assume, that duplication is depreciated and consolitation # wanted to primarily affect 'keywords' ticket field. # Consequently updating ticket tags and reducing (tag) # 'ticket_fields' afterwards may result in undesired tag loss. tag_set.difference_update(all.difference(keywords)) tkt['keywords'] = u' '.join(sorted(map(to_unicode, tag_set))) tkt.save_changes(get_reporter_id(req), comment) else: # Processing a change listener event. tags = self._ticket_tags(ticket_or_resource) super(TicketTagProvider, self).set_resource_tags(req, resource, tags)
def process_request(self, req): req.perm.require('CHANGESET_DELETE') rm = RepositoryManager(self.env) repos = rm.get_repository(req.args['reponame'], True) if not repos: raise TracError(_('Repository "%(name)s" does not exist.', name=req.args['reponame'])) if not (repos.owner == req.authname or 'REPOSITORY_ADMIN' in req.perm): message = _('You (%(user)s) are not the owner of "%(name)s"', user=req.authname, name=repos.reponame) raise PermissionError(message) if req.args.get('confirm'): display_rev = repos.display_rev(req.args['rev']) rm.delete_changeset(repos, req.args['rev'], req.args.get('ban')) add_notice(req, _('The changeset "%(rev)s" has been removed.', rev=display_rev)) req.redirect(req.href.log(repos.reponame)) elif req.args.get('cancel'): LoginModule(self.env)._redirect_back(req) data = {'repository': repos, 'rev': req.args['rev'], 'cannot_ban': not rm.can_ban_changesets(repos.type)} add_stylesheet(req, 'common/css/admin.css') return 'changeset_delete.html', data, None
def pre_process_request(self, req, handler): for path in self.paths: if req.perm is None: # at least in Trac 0.10.2 req.perm seems to be always None ... raise TracError("To use the RestrictedAreaPlugin you need at least Trac 0.10.3.") if (req.path_info == path or req.path_info.startswith(path + '/')) and not req.perm.has_permission(self.__action_name): raise HTTPForbidden(to_unicode(PermissionError(self.__action_name))) return handler
def remove_resource_tags(self, req, resource, comment=u''): assert resource.realm == self.realm if not self.check_permission(req.perm(resource), 'modify'): raise PermissionError(resource=resource, env=self.env) tag_resource(self.env, resource, author=self._get_author(req), log=self.revisable)
def set_resource_tags(self, req, resource, tags, comment=u'', when=None): assert resource.realm == self.realm if not self.check_permission(req.perm(resource), 'modify'): raise PermissionError(resource=resource, env=self.env) tag_resource(self.env, resource, author=self._get_author(req), tags=tags, log=self.revisable, when=when)
def process_request(self, req): if not self._authorize(req): raise PermissionError('BOOKMARK_VIEW') match = self.path_match.match(self._get_resource_uri(req)) if match: action, resource = match.groups() resource = "/" + resource # add bookmark if action == 'add': self.set_bookmark(req, resource) if self._is_ajax(req): content = '&'.join( ('on', req.href.bookmark('delete', resource), _('Delete bookmark'))) if isinstance(content, unicode): content = content.encode('utf-8') req.send(content) req.redirect(resource) # delete bookmark elif action == 'delete' or action == 'delete_in_page': self.delete_bookmark(req, resource) if action == 'delete_in_page': add_notice(req, _('Bookmark is deleted.')) req.redirect(req.href.bookmark()) if self._is_ajax(req): content = '&'.join( ('off', req.href.bookmark('add', resource), _('Bookmark this page'))) if isinstance(content, unicode): content = content.encode('utf-8') req.send(content) req.redirect(resource) # listing bookmarks if self._is_ajax(req): menu = self._get_bookmarks_menu(req) content = tag(tag.a(_('Bookmarks'), href=req.href.bookmark()), menu) req.send(unicode(content).encode('utf-8')) add_stylesheet(req, 'bookmark/css/tracbookmark.css') bookmarks = [ self._format_name(req, url) for url, name, username in self.get_bookmarks(req) ] return 'bookmark_list.html', {'bookmarks': bookmarks}, None
def validate_host(self, admin, host): if host == '<broadcast>': if not admin: raise PermissionError('Broadcast: GROWL_ADMIN') return True # TODO: implement host validation try: r = gethostbyname(host) self.log.info("Address of %s: %s" % (host, r)) except gaierror: raise TracError("Host '%s' is invalid" % host) return True
def remove_resource_tags(self, req, resource): assert resource.realm == self.realm if not self.check_permission(req.perm(resource), 'modify'): raise PermissionError(resource=resource, env=self.env) db = self.env.get_db_cnx() try: cursor = db.cursor() cursor.execute('DELETE FROM tags WHERE tagspace=%s AND name=%s', (self.realm, resource.id)) db.commit() except: db.rollback() raise
def _has_permission(perm, repos, path, rev=None, raise_error=False): if hasattr(repos, 'authz'): if not repos.authz.has_permission(path): if not raise_error: return False repos.authz.assert_permission(path) else: node = repos.get_node(path, rev) if not node.can_view(perm): if not raise_error: return False raise PermissionError('BROWSER_VIEW', node.resource) return True
def _send_csv(self, req, cols, rows, sep=',', mimetype='text/plain', filename=None): self.env.log.debug("T&E: In Wrapped _send_csv") id = report_id_from_filename(filename) reports = get_billing_reports(self) if id in reports and not req.perm.has_permission("TIME_VIEW"): raise PermissionError( "You must have TIME_VIEW permission in order to view this report") unwrapped_send_csv(self, req, cols, rows, sep, mimetype, filename)
def _get_checked_repository(self, req, name, owner=True, permission=None): """Check if a repository exists and the user is the owner and has the given permission. Finally return the repository. """ if not name: raise TracError(_("Repository not specified")) rm = RepositoryManager(self.env) repository = rm.get_repository(name, True) if not repository: raise TracError(_('Repository "%(name)s" does not exist.', name=name)) if owner and not (repository.owner == req.authname or 'REPOSITORY_ADMIN' in req.perm): message = _('You (%(user)s) are not the owner of "%(name)s"', user=req.authname, name=name) raise PermissionError(message) if permission and not permission in req.perm: raise PermissionError(permission, None, self.env) return repository
def remove_user(self, req): """ Show removal form and handle POST as remove action """ username = req.args.get('username') # Check method and permissions if not req.method.upper() == 'POST' or not username: raise PermissionError() # Load user userstore = get_userstore() user = userstore.getUser(req.authname) account = userstore.getUser(username) if not account: add_warning(req, "Could not find user '{0}' from service".format(account.username)) return req.redirect(req.href('admin/users/manage')) # Check permissions req.perm.require('USER_AUTHOR', Resource('user', id=account.id)) # If removable user is project author, change the ownership to person who deletes the user papi = projects.Projects() for project in papi.get_authored_projects(account): project.author = user project.save() # Check if user has TRAC_ADMIN rights for the new project, if not, try setting if not req.perm.has_permission('TRAC_ADMIN', Resource('project', id=project.id)): groupstore = CQDEUserGroupStore(project.trac_environment_key) # Iterate existing project groups and put user into group with TRAC_ADMIN rights for gname, pname in groupstore.get_all_group_permissions(): if pname == 'TRAC_ADMIN': groupstore.add_user_to_group(project.author.username, gname) self.log.info('Added TRAC_ADMIN permissions to {0} at {0}'.format(project.author, project)) self.log.info('Changed ownership of project {0} from {0} to {0}'.format(project, project.author, user)) add_notice(req, tag(_("Changed ownership of the project to you: "), tag.a(project.project_name, href=req.href('..', project.env_name)))) if userstore.deleteUser(account): add_notice(req, "Removed user '{0}' successfully from local store".format(account.username)) else: add_warning(req, "Failed to remove user '{0}' from local store".format(account.username)) # Redirect to user listing return req.redirect(req.href('admin/users/manage'))
def process_request(self, req): if req.method == 'POST': ctype = req.get_header('Content-Type') ctype, options = cgi.parse_header(ctype) if ctype not in ('application/x-www-form-urlencoded', 'multipart/form-data'): if not self._is_xhr(req): req.send(unicode(PermissionError()).encode('utf-8'), status=403) req.args['attachment'] = PseudoAttachmentObject(req) req.args['compact'] = req.get_header('X-TracDragDrop-Compact') action = req.args['action'] if action in ('new', 'delete'): return self._delegate_request(req, action) req.send('', content_type='text/plain', status=500)
def process_request(self, req): link = req.args.get('link', '') parts = link.split(':', 1) if len(parts) > 1: resolver, target = parts if target[:1] + target[-1:] not in ('""', "''"): link = '%s:"%s"' % (resolver, target) from trac.web.chrome import web_context link_frag = extract_link(self.env, web_context(req), link) if isinstance(link_frag, (Element, Fragment)): elt = find_element(link_frag, 'href') if elt is None: # most probably no permissions to view raise PermissionError(_("Can't view %(link)s:", link=link)) href = elt.attrib.get('href') else: href = req.href(link.rstrip(':')) req.redirect(href)
def set_resource_tags(self, req, resource, tags): assert resource.realm == self.realm if not self.check_permission(req.perm(resource), 'modify'): raise PermissionError(resource=resource, env=self.env) db = self.env.get_db_cnx() try: cursor = db.cursor() cursor.execute('DELETE FROM tags WHERE tagspace=%s AND name=%s', (self.realm, resource.id)) for tag in tags: cursor.execute( 'INSERT INTO tags (tagspace, name, tag) ' 'VALUES (%s, %s, %s)', (self.realm, resource.id, tag)) db.commit() except: db.rollback() raise
def __require_permissions_for_cloning(self, authname, parent_project): """ Checks that user have permissions to clone project :param authname: Current user name :param parent_project: Project class instance :raises: PermissionError if no permission """ clone_env = parent_project.get_env() perms = clone_env[PermissionSystem].get_user_permissions(authname) if not perms.get('VERSION_CONTROL_VIEW', False): self.log.error("Intrusive version control clone from " + parent_project.env_name + " requested by " + authname + " !") raise PermissionError(msg=_( "You need to have permissions to read repository to clone it.") )
def remove_resource_tags(self, req, ticket_or_resource, comment=u''): try: resource = ticket_or_resource.resource except AttributeError: resource = ticket_or_resource assert resource.realm == self.realm if not self._check_permission(req, resource, 'modify'): raise PermissionError(resource=resource, env=self.env) # Processing a call from TracTags, try to alter the ticket. ticket = Ticket(self.env, resource.id) # Can only alter tags in 'keywords' ticket field. # DEVEL: Time to differentiate managed and sticky/unmanaged tags? ticket['keywords'] = u'' ticket.save_changes(get_reporter_id(req), comment) else: # Processing a change listener event. super(TicketTagProvider, self).remove_resource_tags(req, resource)
def render_preference_panel(self, req, panel): """Process a request for a preference panel.""" notifier = self.env[GrowlNotifierSystem] sources = notifier.get_available_sources() if req.method == 'POST': if 'GROWL_MODIFY' not in req.perm: raise PermissionError("No permission to change Growl settings") host = req.args.get('host') if notifier.validate_host('GROWL_ADMIN' in req.perm, host): req.session['growl.host'] = host # send a registration request to the host notifier.register_notifications([host]) if True: for source in sources: key = 'growl.source.%s' % source if source in req.args: req.session[key] = '1' elif key in req.session: del req.session[key] req.redirect(req.href.prefs(panel or None)) data = {} data['sources'] = [] for source in sources: label = '%s%s' % (source[0].upper(), source[1:]) key = 'growl.source.%s' % source enabled = req.session.has_key(key) and req.session[key] data['sources'].append({ 'name': source, 'label': label, 'enabled': enabled }) data['host'] = req.session.has_key('growl.host') and \ req.session['growl.host'] data['settings'] = {'session': req.session} # add custom stylesheet add_stylesheet(req, 'growl/css/growl.css') return 'pref_growl.html', data
def _do_save(self, req, attachment): req.perm(attachment.resource).require('ATTACHMENT_CREATE') parent_resource = attachment.resource.parent if 'cancel' in req.args: req.redirect(get_resource_url(self.env, parent_resource, req.href)) upload = req.args.getfirst('attachment') if not hasattr(upload, 'filename') or not upload.filename: raise TracError(_("No file uploaded")) if hasattr(upload.file, 'fileno'): size = os.fstat(upload.file.fileno())[6] else: upload.file.seek(0, 2) # seek to end of file size = upload.file.tell() upload.file.seek(0) if size == 0: raise TracError(_("Can't upload empty file")) # Maximum attachment size (in bytes) max_size = self.max_size if 0 <= max_size < size: raise TracError( _("Maximum attachment size: %(num)s", num=pretty_size(max_size)), _("Upload failed")) filename = _normalized_filename(upload.filename) if not filename: raise TracError(_("No file uploaded")) # Now the filename is known, update the attachment resource attachment.filename = filename attachment.description = req.args.get('description', '') attachment.author = get_reporter_id(req, 'author') attachment.ipnr = req.remote_addr # Validate attachment valid = True for manipulator in self.manipulators: for field, message in manipulator.validate_attachment( req, attachment): valid = False if field: add_warning( req, tag_( "Attachment field %(field)s is invalid: " "%(message)s", field=tag.strong(field), message=message)) else: add_warning( req, tag_("Invalid attachment: %(message)s", message=message)) if not valid: # Display the attach form with pre-existing data # NOTE: Local file path not known, file field cannot be repopulated add_warning(req, _('Note: File must be selected again.')) data = self._render_form(req, attachment) data['is_replace'] = req.args.get('replace') return data if req.args.get('replace'): try: old_attachment = Attachment(self.env, attachment.resource(id=filename)) if not (req.authname and req.authname != 'anonymous' and old_attachment.author == req.authname) \ and 'ATTACHMENT_DELETE' \ not in req.perm(attachment.resource): raise PermissionError(msg=_( "You don't have permission to " "replace the attachment %(name)s. You can only " "replace your own attachments. Replacing other's " "attachments requires ATTACHMENT_DELETE permission.", name=filename)) if (not attachment.description.strip() and old_attachment.description): attachment.description = old_attachment.description old_attachment.delete() except TracError: pass # don't worry if there's nothing to replace attachment.insert(filename, upload.file, size) req.redirect( get_resource_url(self.env, attachment.resource(id=None), req.href))
def _do_action(self, req, modes, group, forum, topic, message, is_moderator): # Get database access. db = self.env.get_db_cnx() cursor = db.cursor() for mode in modes: self.log.debug('doing %s mode action' % (mode, )) if mode == 'group-list': req.perm.assert_permission('DISCUSSION_VIEW') # Display groups. req.hdf['discussion.groups'] = self.get_groups(req, cursor) elif mode == 'admin-group-list': req.perm.assert_permission('DISCUSSION_ADMIN') # Get form values order = req.args.get('order') or 'id' desc = req.args.get('desc') # Display groups. req.hdf['discussion.order'] = order req.hdf['discussion.desc'] = desc if group: req.hdf['discussion.name'] = group['name'] req.hdf['discussion.description'] = \ group['description'] req.hdf['discussion.groups'] = self.get_groups( req, cursor, order, desc) elif mode == 'group-add': req.perm.assert_permission('DISCUSSION_ADMIN') elif mode == 'group-post-add': req.perm.assert_permission('DISCUSSION_ADMIN') # Get form values. new_name = req.args.get('name') new_description = req.args.get('description') # Add new group. self.add_group(cursor, new_name, new_description) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'group-post-edit': req.perm.assert_permission('DISCUSSION_ADMIN') # Get form values. new_group = int(req.args.get('group') or 0) new_name = req.args.get('name') new_description = req.args.get('description') # Edit group. self.edit_group(cursor, new_group, new_name, new_description) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'group-delete': req.perm.assert_permission('DISCUSSION_ADMIN') elif mode == 'groups-delete': req.perm.assert_permission('DISCUSSION_ADMIN') # Get selected groups. selection = req.args.get('selection') if isinstance(selection, (str, unicode)): selection = [selection] # Delete selected groups. if selection: for group_id in selection: self.delete_group(cursor, int(group_id)) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'forum-list': req.perm.assert_permission('DISCUSSION_VIEW') # Get form values order = req.args.get('order') or 'id' asc = req.args.get('asc') # default to ASCending order here: if asc == None: asc = 1 # Display forums. req.hdf['discussion.order'] = order req.hdf['discussion.asc'] = asc req.hdf['discussion.groups'] = self.get_groups(req, cursor) req.hdf['discussion.forums'] = self.get_forums( req, cursor, asc, order) elif mode == 'admin-forum-list': req.perm.assert_permission('DISCUSSION_ADMIN') # Get form values order = req.args.get('order') or 'id' asc = req.args.get('asc') # Default to ASCending order here if asc == None: asc = 1 # Display forums. req.hdf['discussion.order'] = order req.hdf['discussion.asc'] = asc if forum: req.hdf['discussion.name'] = forum['name'] req.hdf['discussion.subject'] = forum['subject'] req.hdf['discussion.description'] = \ forum['description'] req.hdf['discussion.moderators'] = forum['moderators'] req.hdf['discussion.group'] = forum['group'] req.hdf['discussion.users'] = self.get_users() req.hdf['discussion.groups'] = self.get_groups(req, cursor) req.hdf['discussion.forums'] = self.get_forums( req, cursor, asc, order) elif mode == 'forum-add': req.perm.assert_permission('DISCUSSION_ADMIN') # Display Add Forum form. req.hdf['discussion.users'] = self.get_users() req.hdf['discussion.groups'] = self.get_groups(req, cursor) elif mode == 'forum-post-add': req.perm.assert_permission('DISCUSSION_ADMIN') # Get form values new_name = req.args.get('name') new_author = req.authname new_subject = req.args.get('subject') new_description = req.args.get('description') new_moderators = req.args.get('moderators') new_group = int(req.args.get('group') or 0) if not new_moderators: new_moderators = [] if not isinstance(new_moderators, list): new_moderators = [new_moderators] # Perform new forum add. self.add_forum(cursor, new_name, new_author, new_subject, new_description, new_moderators, new_group) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'forum-post-edit': req.perm.assert_permission('DISCUSSION_ADMIN') # Get form values. new_forum = int(req.args.get('forum') or 0) new_name = req.args.get('name') new_subject = req.args.get('subject') new_description = req.args.get('description') new_moderators = req.args.get('moderators') new_group = int(req.args.get('group') or 0) if not new_moderators: new_moderators = [] if not isinstance(new_moderators, list): new_moderators = [new_moderators] # Perform forum edit. self.edit_forum(cursor, new_forum, new_name, new_subject, new_description, new_moderators, new_group) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'forum-delete': req.perm.assert_permission('DISCUSSION_ADMIN') # Delete forum self.delete_forum(cursor, forum['id']) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'forums-delete': req.perm.assert_permission('DISCUSSION_ADMIN') # Get selected forums. selection = req.args.get('selection') if isinstance(selection, (str, unicode)): selection = [selection] # Delete selected forums. if selection: for forum_id in selection: self.delete_forum(cursor, int(forum_id)) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'topic-list': req.perm.assert_permission('DISCUSSION_VIEW') # Get form values order = req.args.get('order') or 'lastreply' asc = req.args.get('asc') or 0 start = int(req.args.get('start') or 0) if start < 0: start = 0 # Display topics. req.hdf['discussion.order'] = order req.hdf['discussion.asc'] = asc req.hdf['discussion.topics'] = self.get_topics( req, cursor, forum['id'], start, order, asc) topic_count = self.get_topic_count(req, cursor, forum['id']) req.hdf['discussion.topic_count'] = int(topic_count) # Create the paging links if start + self.topics_per_page < topic_count: req.hdf[ 'discussion.next_page'] = start + self.topics_per_page else: req.hdf['discussion.next_page'] = '' if start > 0: prev_start = start - self.topics_per_page if prev_start < 0: prev_start = 0 req.hdf['discussion.prev_page'] = prev_start else: req.hdf['discussion.prev_page'] = '' elif mode == 'topic-add': req.perm.assert_permission('DISCUSSION_APPEND') # Get form values. new_subject = req.args.get('subject') new_author = req.args.get('author') new_body = req.args.get('body') # Display Add Topic form. if new_subject: req.hdf['discussion.subject'] = wiki_to_oneliner( new_subject, self.env) if new_author: req.hdf['discussion.author'] = wiki_to_oneliner( new_author, self.env) if new_body: req.hdf['discussion.body'] = wiki_to_html( new_body, self.env, req, None, False, True) elif mode == 'topic-quote': req.perm.assert_permission('DISCUSSION_APPEND') # Prepare old content. lines = topic['body'].splitlines() for I in xrange(len(lines)): lines[I] = '> %s' % (lines[I]) req.hdf['args.body'] = '\n'.join(lines) elif mode == 'topic-post-add': req.perm.assert_permission('DISCUSSION_APPEND') # Get form values. new_subject = req.args.get('subject') new_author = req.args.get('author') new_body = req.args.get('body') new_time = int(time.time()) # Add topic. self.add_topic(cursor, forum['id'], new_subject, new_time, new_author, new_body) # Get new topic and notify about creation. new_topic = self.get_topic_by_time(cursor, new_time) to = self.get_topic_to_recipients(cursor, new_topic['id']) cc = self.get_topic_cc_recipients(cursor, new_topic['id']) notifier = DiscussionNotifyEmail(self.env) notifier.notify(req, cursor, mode, forum, new_topic, None, to, cc) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'topic-edit': req.perm.assert_permission('DISCUSSION_APPEND') if not is_moderator and (topic['author'] != req.authname): raise PermissionError('Topic edit') # Prepare form values. req.args['subject'] = topic['subject'] req.args['body'] = topic['body'] req.hdf['args.subject'] = topic['subject'] req.hdf['args.body'] = topic['body'] elif mode == 'topic-post-edit': req.perm.assert_permission('DISCUSSION_APPEND') if not is_moderator and (topic['author'] != req.authname): raise PermissionError('Topic edit') # Get form values. new_subject = req.args.get('subject') new_body = req.args.get('body') # Edit topic. topic['subject'] = new_subject topic['body'] = new_body self.edit_topic(cursor, topic['id'], topic['forum'], new_subject, new_body) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'topic-move': req.perm.assert_permission('DISCUSSION_MODERATE') if not is_moderator: raise PermissionError('Forum moderate') # Display Move Topic form req.hdf['discussion.forums'] = self.get_forums(req, cursor) elif mode == 'topic-post-move': req.perm.assert_permission('DISCUSSION_MODERATE') if not is_moderator: raise PermissionError('Forum moderate') # Get form values new_forum = int(req.args.get('new_forum') or 0) # Move topic. self.set_forum(cursor, topic['id'], new_forum) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'topic-delete': req.perm.assert_permission('DISCUSSION_MODERATE') if not is_moderator: raise PermissionError('Forum moderate') # Delete topic. self.delete_topic(cursor, topic['id']) # Redirect request to prevent re-submit. db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'message-list': req.perm.assert_permission('DISCUSSION_VIEW') self._prepare_message_list(req, cursor, topic) elif mode == 'wiki-message-list': if topic: self._prepare_message_list(req, cursor, topic) elif mode == 'message-quote': req.perm.assert_permission('DISCUSSION_APPEND') # Prepare old content. lines = message['body'].splitlines() for I in xrange(len(lines)): lines[I] = '> %s' % (lines[I]) req.hdf['args.body'] = '\n'.join(lines) elif mode == 'message-post-add': req.perm.assert_permission('DISCUSSION_APPEND') # Get form values. new_author = req.args.get('author') new_body = req.args.get('body') new_time = int(time.time()) # Add message. if message: self.add_message(cursor, forum['id'], topic['id'], message['id'], new_time, new_author, new_body) else: self.add_message(cursor, forum['id'], topic['id'], '-1', new_time, new_author, new_body) # Get inserted message and notify about its creation. new_message = self.get_message_by_time(cursor, new_time) to = self.get_topic_to_recipients(cursor, topic['id']) cc = self.get_topic_cc_recipients(cursor, topic['id']) notifier = DiscussionNotifyEmail(self.env) notifier.notify(req, cursor, mode, forum, topic, new_message, to, cc) # Redirect request to prevent re-submit. if req.args.get('component') != 'wiki': db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'message-edit': req.perm.assert_permission('DISCUSSION_APPEND') if not is_moderator and (message['author'] != req.authname): raise PermissionError('Message edit') # Prepare form values. req.args['body'] = message['body'] req.hdf['args.body'] = message['body'] elif mode == 'message-post-edit': req.perm.assert_permission('DISCUSSION_APPEND') if not is_moderator and (message['author'] != req.authname): raise PermissionError('Message edit') # Get form values. new_body = req.args.get('body') # Edit message. message['body'] = new_body self.edit_message(cursor, message['id'], message['forum'], message['topic'], message['replyto'], new_body) # Redirect request to prevent re-submit. if req.args.get('component') != 'wiki': db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'message-delete': req.perm.assert_permission('DISCUSSION_MODERATE') if not is_moderator: raise PermissionError('Forum moderate') # Delete message. self.delete_message(cursor, message['id']) # Redirect request to prevent re-submit. if req.args.get('component') != 'wiki': db.commit() req.redirect( req.href.discussion('redirect', href=req.path_info)) elif mode == 'message-set-display': req.perm.assert_permission('DISCUSSION_VIEW') # Get form values display = req.args.get('display') # Set message list display mode to session req.session['message-list-display'] = display # Commit database changes. db.commit()
def process_request(self, req): req.entered_process_request = True raise PermissionError("No permission to view")
def process_request(self, req): presel = req.args.get('preselected') if presel and (presel + '/').startswith(req.href.browser() + '/'): req.redirect(presel) path = req.args.get('path', '/') rev = req.args.get('rev', '') if rev.lower() in ('', 'head'): rev = None format = req.args.get('format') order = req.args.get('order', 'name').lower() desc = 'desc' in req.args rm = RepositoryManager(self.env) all_repositories = rm.get_all_repositories() reponame, repos, path = rm.get_repository_by_path(path) # Repository index show_index = not reponame and path == '/' if show_index: if repos and (as_bool(all_repositories[''].get('hidden')) or not repos.is_viewable(req.perm)): repos = None if not repos and reponame: raise ResourceNotFound(_("Repository '%(repo)s' not found", repo=reponame)) if reponame and reponame != repos.reponame: # Redirect alias qs = req.query_string req.redirect(req.href.browser(repos.reponame or None, path) + ('?' + qs if qs else '')) reponame = repos.reponame if repos else None # Find node for the requested path/rev context = web_context(req) node = None changeset = None display_rev = lambda rev: rev if repos: try: if rev: rev = repos.normalize_rev(rev) # If `rev` is `None`, we'll try to reuse `None` consistently, # as a special shortcut to the latest revision. rev_or_latest = rev or repos.youngest_rev node = get_existing_node(req, repos, path, rev_or_latest) except NoSuchChangeset as e: raise ResourceNotFound(e, _('Invalid changeset number')) if node: try: # use changeset instance to retrieve branches and tags changeset = repos.get_changeset(node.rev) except NoSuchChangeset: pass context = context.child(repos.resource.child(self.realm, path, version=rev_or_latest)) display_rev = repos.display_rev # Prepare template data path_links = get_path_links(req.href, reponame, path, rev, order, desc) repo_data = dir_data = file_data = None if show_index: repo_data = self._render_repository_index( context, all_repositories, order, desc) if node: if not node.is_viewable(req.perm): raise PermissionError('BROWSER_VIEW' if node.isdir else 'FILE_VIEW', node.resource, self.env) if node.isdir: if format in ('zip',): # extension point here... self._render_zip(req, context, repos, node, rev) # not reached dir_data = self._render_dir(req, repos, node, rev, order, desc) elif node.isfile: file_data = self._render_file(req, context, repos, node, rev) if not repos and not (repo_data and repo_data['repositories']): # If no viewable repositories, check permission instead of # repos.is_viewable() req.perm.require('BROWSER_VIEW') if show_index: raise ResourceNotFound(_("No viewable repositories")) else: raise ResourceNotFound(_("No node %(path)s", path=path)) quickjump_data = properties_data = None if node and not req.is_xhr: properties_data = self.render_properties( 'browser', context, node.get_properties()) quickjump_data = list(repos.get_quickjump_entries(rev)) data = { 'context': context, 'reponame': reponame, 'repos': repos, 'repoinfo': all_repositories.get(reponame or ''), 'path': path, 'rev': node and node.rev, 'stickyrev': rev, 'display_rev': display_rev, 'changeset': changeset, 'created_path': node and node.created_path, 'created_rev': node and node.created_rev, 'properties': properties_data, 'path_links': path_links, 'order': order, 'desc': 1 if desc else None, 'repo': repo_data, 'dir': dir_data, 'file': file_data, 'quickjump_entries': quickjump_data, 'wiki_format_messages': self.config['changeset'].getbool('wiki_format_messages'), } if req.is_xhr: # render and return the content only return 'dir_entries.html', data if dir_data or repo_data: add_script(req, 'common/js/expand_dir.js') add_script(req, 'common/js/keyboard_nav.js') # Links for contextual navigation if node: if node.isfile: prev_rev = repos.previous_rev(rev=node.created_rev, path=node.created_path) if prev_rev: href = req.href.browser(reponame, node.created_path, rev=prev_rev) add_link(req, 'prev', href, _('Revision %(num)s', num=display_rev(prev_rev))) if rev is not None: add_link(req, 'up', req.href.browser(reponame, node.created_path)) next_rev = repos.next_rev(rev=node.created_rev, path=node.created_path) if next_rev: href = req.href.browser(reponame, node.created_path, rev=next_rev) add_link(req, 'next', href, _('Revision %(num)s', num=display_rev(next_rev))) prevnext_nav(req, _('Previous Revision'), _('Next Revision'), _('Latest Revision')) else: if path != '/': add_link(req, 'up', path_links[-2]['href'], _('Parent directory')) add_ctxtnav(req, tag.a(_('Last Change'), href=req.href.changeset(node.created_rev, reponame, node.created_path))) if node.isfile: annotate = data['file']['annotate'] if annotate: add_ctxtnav(req, _('Normal'), title=_('View file without annotations'), href=req.href.browser(reponame, node.created_path, rev=rev)) if annotate != 'blame': add_ctxtnav(req, _('Blame'), title=_('Annotate each line with the last ' 'changed revision ' '(this can be time consuming...)'), href=req.href.browser(reponame, node.created_path, rev=rev, annotate='blame')) add_ctxtnav(req, _('Revision Log'), href=req.href.log(reponame, path, rev=rev)) path_url = repos.get_path_url(path, rev) if path_url: if path_url.startswith('//'): path_url = req.scheme + ':' + path_url add_ctxtnav(req, _('Repository URL'), href=path_url) add_stylesheet(req, 'common/css/browser.css') return 'browser.html', data