mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
- Uninstall deletes wikis & extensions - Use Skylark (v1.8.0) - Add option to upload existing wiki - Open wiki links in new tab. Since Feather Wiki modifies browser history, it takes several clicks to go back and reach the FreedomBox app for Feather Wiki if the user wants to switch to another wiki file. Opening in a new tab also makes it easy for the user to move text between wikis (i.e. the Refile use case). - Improve HTML file path handling. Extract only the HTML file name from the URL. Return a 404 status if the file cannot be found - Place featherwiki_nest.cgi file in /usr/lib/cgi-bin. The file is installed as part of the FreedomBox package, rather than a step in the installation of Feather Wiki. [sunil] - Reorganized description to complete the introduction before talking about FreedomBox implementation. - Update description to say that only users of 'wiki' group can access. - Update description to talk about where the wiki is downloaded from how to upgrade it. - Update short description to 'Personal Notebooks'. - Add UsersAndGroups component and to reuse 'wiki' group properly. - Reorder component to resemble other apps (could prove useful in future). - Restrict frontpage shortcut to 'wiki' group users. - Minor styling updates. Run isort. - Use pathlib.Path object where possible instead of os.path. - Perform sanitization in privileged methods instead of callers. This leads better security if the service is compromised. - Perform duplicate checking in privileged methods instead of callers. - Check in privileged action that uploaded file originates from temporary directory. Otherwise, arbitrary files can moved into DAV directory. - Switch storage path to /var/lib/ which is an application data folder from /var/www which is a user data folder. - Add extra security to the DAV folder by explicitly rejecting .htaccess directives, forcing mime type and removing all options. - Update SVG/PNG logo icons to adhere to our guidelines. - Minor template updates. Add required attributes. Improve i18n. Avoid <p> inside <p>. - Refactor tests for more code reuse and fewer globals. Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net> Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
158 lines
5.3 KiB
Python
158 lines
5.3 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""Django views for Feather Wiki."""
|
|
|
|
import tempfile
|
|
|
|
from django.contrib import messages
|
|
from django.contrib.messages.views import SuccessMessageMixin
|
|
from django.shortcuts import redirect
|
|
from django.template.response import TemplateResponse
|
|
from django.urls import reverse_lazy
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.views.generic import FormView
|
|
|
|
from plinth import app as app_module
|
|
from plinth import views
|
|
from plinth.modules import featherwiki
|
|
|
|
from . import privileged
|
|
from .forms import CreateWikiForm, RenameWikiForm, UploadWikiForm
|
|
|
|
DUPLICATE_FILE_ERROR = _('A wiki file with the given name already exists.')
|
|
|
|
|
|
class FeatherWikiAppView(views.AppView):
|
|
"""Serve configuration page."""
|
|
|
|
app_id = 'featherwiki'
|
|
template_name = 'featherwiki_configure.html'
|
|
|
|
def get_context_data(self, *args, **kwargs):
|
|
"""Add wikis to the context data."""
|
|
context = super().get_context_data(*args, **kwargs)
|
|
context['wikis'] = featherwiki.get_wiki_list()
|
|
return context
|
|
|
|
|
|
class CreateWikiView(SuccessMessageMixin, FormView):
|
|
"""View to create a new repository."""
|
|
|
|
form_class = CreateWikiForm
|
|
prefix = 'featherwiki'
|
|
template_name = 'form.html'
|
|
success_url = reverse_lazy('featherwiki:index')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""Return additional context for rendering the template."""
|
|
context = super().get_context_data(**kwargs)
|
|
context['title'] = _('Create Wiki')
|
|
return context
|
|
|
|
def form_valid(self, form):
|
|
"""Create the repository on valid form submission."""
|
|
try:
|
|
privileged.create_wiki(form.cleaned_data['name'])
|
|
self.success_message = _('Wiki created.')
|
|
except ValueError:
|
|
messages.error(self.request, DUPLICATE_FILE_ERROR)
|
|
except Exception as error:
|
|
messages.error(
|
|
self.request, "{0} {1}".format(
|
|
_('An error occurred while creating the wiki.'), error))
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
class RenameWikiView(SuccessMessageMixin, FormView):
|
|
"""View to edit an existing repository."""
|
|
|
|
form_class = RenameWikiForm
|
|
prefix = 'featherwiki'
|
|
template_name = 'form.html'
|
|
success_url = reverse_lazy('featherwiki:index')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""Return additional context for rendering the template."""
|
|
context = super().get_context_data(**kwargs)
|
|
context['title'] = _('Rename Wiki')
|
|
return context
|
|
|
|
def form_valid(self, form):
|
|
"""Rename the wiki on valid form submission."""
|
|
try:
|
|
privileged.rename_wiki(self.kwargs['old_name'],
|
|
form.cleaned_data['new_name'])
|
|
self.success_message = _('Wiki renamed.')
|
|
except ValueError:
|
|
messages.error(self.request, DUPLICATE_FILE_ERROR)
|
|
except Exception as error:
|
|
messages.error(
|
|
self.request, "{0} {1}".format(
|
|
_('An error occurred while renaming the wiki.'), error))
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
class UploadWikiView(SuccessMessageMixin, FormView):
|
|
"""View to upload an existing wiki file."""
|
|
|
|
form_class = UploadWikiForm
|
|
prefix = 'featherwiki'
|
|
template_name = 'featherwiki_upload_file.html'
|
|
success_url = reverse_lazy('featherwiki:index')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""Return additional context for rendering the template."""
|
|
context = super().get_context_data(**kwargs)
|
|
context['title'] = _('Upload Wiki File')
|
|
return context
|
|
|
|
def form_valid(self, form):
|
|
"""Add the wiki file on valid form submission."""
|
|
multipart_file = self.request.FILES['featherwiki-file']
|
|
|
|
try:
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
wiki_file_name = temp_dir + '/' + multipart_file.name
|
|
with open(wiki_file_name, 'wb+') as wiki_file:
|
|
for chunk in multipart_file.chunks():
|
|
wiki_file.write(chunk)
|
|
|
|
privileged.add_wiki_file(wiki_file_name)
|
|
|
|
self.success_message = _('Wiki file added.')
|
|
except ValueError:
|
|
messages.error(self.request, DUPLICATE_FILE_ERROR)
|
|
except Exception as error:
|
|
messages.error(
|
|
self.request, "{0} {1}".format(_('Failed to add wiki file.'),
|
|
error))
|
|
return redirect(reverse_lazy('featherwiki:index'))
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
def delete(request, name):
|
|
"""Handle deleting wikis, showing a confirmation dialog first.
|
|
|
|
On GET, display a confirmation page.
|
|
On POST, delete the wiki.
|
|
"""
|
|
app = app_module.App.get('featherwiki')
|
|
if request.method == 'POST':
|
|
try:
|
|
privileged.delete_wiki(name)
|
|
messages.success(request, _('{name} deleted.').format(name=name))
|
|
except Exception as error:
|
|
messages.error(
|
|
request,
|
|
_('Could not delete {name}: {error}').format(
|
|
name=name, error=error))
|
|
|
|
return redirect(reverse_lazy('featherwiki:index'))
|
|
|
|
return TemplateResponse(request, 'featherwiki_delete.html', {
|
|
'title': app.info.name,
|
|
'name': name
|
|
})
|