Mercurial > wikked
view wikked/webimpl/edit.py @ 451:6cd51ea6dfcf
auth: Rewrite permission system and improve support for it.
- More proper ACL model for permissions.
- Page-level ACL is only specified locally, not inherited anymore.
- Protect more API and UI routes with permission checks.
- Improve error handling and error pages.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 07 Jan 2018 11:11:04 -0800 |
parents | 8ca8c2713c92 |
children | faa4c8467291 |
line wrap: on
line source
import os.path import logging import urllib.parse from werkzeug.utils import secure_filename from wikked.page import Page, PageData from wikked.formatter import PageFormatter, FormattingContext from wikked.resolver import PageResolver from wikked.utils import PageNotFoundError from wikked.webimpl import ( get_page_or_raise, get_page_meta, make_page_title) logger = logging.getLogger(__name__) class DummyPage(Page): """ A dummy page for previewing in-progress editing. """ def __init__(self, wiki, url, text): data = self._loadData(wiki, url, text) super(DummyPage, self).__init__(wiki, data) def _loadData(self, wiki, url, text): data = PageData() extension = wiki.fs.default_extension data.url = url data.path = '__preview__.' + extension data.raw_text = text ctx = FormattingContext(url) f = PageFormatter() data.formatted_text = f.formatText(ctx, data.raw_text) data.local_meta = ctx.meta data.local_links = ctx.out_links data.title = (data.local_meta.get('title') or make_page_title(url)) if isinstance(data.title, list): data.title = data.title[0] return data def get_edit_page(wiki, user, url, author=None, custom_data=None): page = None try: page = get_page_or_raise(wiki, url, check_perms=(user, 'edit')) except PageNotFoundError: # Only catch errors about the page not existing. Permission # errors still go through. page = None if page is None: result = { 'meta': { 'url': urllib.parse.quote(url.encode('utf-8')), 'title': make_page_title(url) }, 'text': '' } else: result = { 'meta': get_page_meta(page, True), 'text': page.raw_text } result['commit_meta'] = { 'author': author, 'desc': 'Editing ' + result['meta']['title'] } if custom_data: result.update(custom_data) return result def do_edit_page(wiki, user, url, text, author=None, message=None): try: get_page_or_raise(wiki, url, check_perms=(user, 'edit')) except PageNotFoundError: # Only catch errors about the page not existing. Permission # errors still go through. pass author = author or user if author is None: raise Exception("No author or user was specified.") message = message or 'Edited ' + url page_fields = { 'text': text, 'author': author, 'message': message } wiki.setPage(url, page_fields) def preview_edited_page(wiki, url, raw_text): dummy = DummyPage(wiki, url, raw_text) # We can pass `can_use_resolved_meta` since we know we have the only # resolver running right now... this will speed things up dramatically. resolver = PageResolver(dummy, can_use_resolved_meta=True) dummy._setExtendedData(resolver.run()) return dummy.text def do_upload_file(wiki, user, reqfile, for_url=None, submit=True): if not reqfile: raise Exception("No file was specified.") if not reqfile.filename: raise Exception("No file name was specified.") # TODO: check permissions for the user. filename = secure_filename(reqfile.filename) files_dir = os.path.join(wiki.root, '_files') upload_dir = files_dir if for_url: upload_dir = os.path.join(wiki.root, for_url) path = os.path.join(upload_dir, filename) path = os.path.normpath(path) if not path.startswith(wiki.root): raise Exception("Don't try anything weird, please.") # Save to disk. os.makedirs(os.path.dirname(path), exist_ok=True) reqfile.save(path) # Commit the file to the source-control. if submit: commit_meta = { 'author': user, 'message': "Uploaded '%s'." % filename} wiki.scm.commit([path], commit_meta) if for_url: example = './%s' % filename else: example = os.path.relpath(path, files_dir) result = { 'example': example } return result