mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-04-29 10:10:19 +00:00
Add file-sharing application Coquelicot to FreedomBox
- Add settings in Service View - Fixes for maximum file setting - Don't allow negative values for max. file size in UI - Minor text changes to django messages - Minor correction to maximum file size calculation - Rename apache conf file to coquelicot-freedombox.conf - Remove all hacks to adjust file size. - Fix permissions issues for settings file - Show status block in UI - try-restart on settings change instead of restart Signed-off-by: Joseph Nuthalapati <njoseph@thoughtworks.com> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
5b37d0df8d
commit
ff9d061e98
137
actions/coquelicot
Executable file
137
actions/coquelicot
Executable file
@ -0,0 +1,137 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- mode: python -*-
|
||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Configuration helper for coquelicot.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
from plinth import action_utils
|
||||||
|
|
||||||
|
SETTINGS_FILE = '/etc/coquelicot/settings.yml'
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arguments():
|
||||||
|
"""Return parsed command line arguments as dictionary."""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||||
|
|
||||||
|
subparsers.add_parser('setup',
|
||||||
|
help='Post-installation operations for coquelicot')
|
||||||
|
subparsers.add_parser('enable', help='Enable coquelicot')
|
||||||
|
subparsers.add_parser('disable', help='Disable coquelicot')
|
||||||
|
|
||||||
|
subparsers.add_parser(
|
||||||
|
'set-upload-password',
|
||||||
|
help='Set a new global, pre-shared password for uploading files')
|
||||||
|
|
||||||
|
max_file_size = subparsers.add_parser(
|
||||||
|
'set-max-file-size',
|
||||||
|
help='Change the maximum size of the files that can be uploaded to '
|
||||||
|
'Coquelicot')
|
||||||
|
max_file_size.add_argument('size', type=int, help='upload file size in MB')
|
||||||
|
|
||||||
|
subparsers.add_parser(
|
||||||
|
'get-max-file-size',
|
||||||
|
help='Print the maximum size of the files that can be uploaded to '
|
||||||
|
'Coquelicot')
|
||||||
|
|
||||||
|
subparsers.required = True
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_setup(_):
|
||||||
|
"""Perform post-installation operations for coquelicot."""
|
||||||
|
settings = read_settings()
|
||||||
|
settings['path'] = "/coquelicot"
|
||||||
|
settings['max_file_size'] = mebibytes(1024)
|
||||||
|
write_settings(settings)
|
||||||
|
action_utils.service_restart('coquelicot')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_enable(_):
|
||||||
|
"""Enable web configuration and reload."""
|
||||||
|
action_utils.service_enable('coquelicot')
|
||||||
|
action_utils.webserver_enable('coquelicot-freedombox')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_disable(_):
|
||||||
|
"""Disable web configuration and reload."""
|
||||||
|
action_utils.webserver_disable('coquelicot-freedombox')
|
||||||
|
action_utils.service_disable('coquelicot')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_set_upload_password(arguments):
|
||||||
|
"""Set a new upload password for Coquelicot."""
|
||||||
|
upload_password = ''.join(sys.stdin)
|
||||||
|
settings = read_settings()
|
||||||
|
hashed_pw = hashlib.sha1(upload_password.encode()).hexdigest()
|
||||||
|
settings['authentication_method']['upload_password'] = hashed_pw
|
||||||
|
write_settings(settings)
|
||||||
|
action_utils.service_try_restart('coquelicot')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_set_max_file_size(arguments):
|
||||||
|
"""Set a new maximum file size for Coquelicot."""
|
||||||
|
size_in_bytes = mebibytes(arguments.size)
|
||||||
|
settings = read_settings()
|
||||||
|
settings['max_file_size'] = size_in_bytes
|
||||||
|
write_settings(settings)
|
||||||
|
action_utils.service_try_restart('coquelicot')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_get_max_file_size(_):
|
||||||
|
"""Print the maximum file size to stdout."""
|
||||||
|
if os.path.exists(SETTINGS_FILE):
|
||||||
|
settings = read_settings()
|
||||||
|
print(int(settings['max_file_size'] / (1024 * 1024)))
|
||||||
|
else:
|
||||||
|
print(-1)
|
||||||
|
|
||||||
|
|
||||||
|
def read_settings():
|
||||||
|
with open(SETTINGS_FILE, 'rb') as settings_file:
|
||||||
|
return yaml.load(settings_file)
|
||||||
|
|
||||||
|
|
||||||
|
def write_settings(settings):
|
||||||
|
with open(SETTINGS_FILE, 'w') as settings_file:
|
||||||
|
yaml.dump(settings, settings_file)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Parse arguments and perform all duties."""
|
||||||
|
arguments = parse_arguments()
|
||||||
|
|
||||||
|
subcommand = arguments.subcommand.replace('-', '_')
|
||||||
|
subcommand_method = globals()['subcommand_' + subcommand]
|
||||||
|
subcommand_method(arguments)
|
||||||
|
|
||||||
|
|
||||||
|
def mebibytes(size):
|
||||||
|
"""Return the given size of mebibytes in bytes."""
|
||||||
|
return size * 1024 * 1024
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<Location /coquelicot>
|
||||||
|
ProxyPass http://127.0.0.1:51161/coquelicot
|
||||||
|
SetEnv proxy-sendchunks 1
|
||||||
|
RequestHeader set X-Forwarded-SSL "on"
|
||||||
|
</Location>
|
||||||
1
data/etc/plinth/modules-enabled/coquelicot
Normal file
1
data/etc/plinth/modules-enabled/coquelicot
Normal file
@ -0,0 +1 @@
|
|||||||
|
plinth.modules.coquelicot
|
||||||
@ -99,41 +99,36 @@ def service_unmask(service_name):
|
|||||||
|
|
||||||
def service_start(service_name):
|
def service_start(service_name):
|
||||||
"""Start a service with systemd or sysvinit."""
|
"""Start a service with systemd or sysvinit."""
|
||||||
if is_systemd_running():
|
service_action(service_name, 'start')
|
||||||
subprocess.run(['systemctl', 'start', service_name],
|
|
||||||
stdout=subprocess.DEVNULL)
|
|
||||||
else:
|
|
||||||
subprocess.run(['service', service_name, 'start'],
|
|
||||||
stdout=subprocess.DEVNULL)
|
|
||||||
|
|
||||||
|
|
||||||
def service_stop(service_name):
|
def service_stop(service_name):
|
||||||
"""Stop a service with systemd or sysvinit."""
|
"""Stop a service with systemd or sysvinit."""
|
||||||
if is_systemd_running():
|
service_action(service_name, 'stop')
|
||||||
subprocess.run(['systemctl', 'stop', service_name],
|
|
||||||
stdout=subprocess.DEVNULL)
|
|
||||||
else:
|
|
||||||
subprocess.run(['service', service_name, 'stop'],
|
|
||||||
stdout=subprocess.DEVNULL)
|
|
||||||
|
|
||||||
|
|
||||||
def service_restart(service_name):
|
def service_restart(service_name):
|
||||||
"""Restart a service with systemd or sysvinit."""
|
"""Restart a service with systemd or sysvinit."""
|
||||||
if is_systemd_running():
|
service_action(service_name, 'restart')
|
||||||
subprocess.run(['systemctl', 'restart', service_name],
|
|
||||||
stdout=subprocess.DEVNULL)
|
|
||||||
else:
|
def service_try_restart(service_name):
|
||||||
subprocess.run(['service', service_name, 'restart'],
|
"""Try to restart a service with systemd or sysvinit."""
|
||||||
stdout=subprocess.DEVNULL)
|
service_action(service_name, 'try-restart')
|
||||||
|
|
||||||
|
|
||||||
def service_reload(service_name):
|
def service_reload(service_name):
|
||||||
"""Reload a service with systemd or sysvinit."""
|
"""Reload a service with systemd or sysvinit."""
|
||||||
|
service_action(service_name, 'reload')
|
||||||
|
|
||||||
|
|
||||||
|
def service_action(service_name, action):
|
||||||
|
"""Preform the given action on the service_name."""
|
||||||
if is_systemd_running():
|
if is_systemd_running():
|
||||||
subprocess.run(['systemctl', 'reload', service_name],
|
subprocess.run(['systemctl', action, service_name],
|
||||||
stdout=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL)
|
||||||
else:
|
else:
|
||||||
subprocess.run(['service', service_name, 'reload'],
|
subprocess.run(['service', service_name, action],
|
||||||
stdout=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
133
plinth/modules/coquelicot/__init__.py
Normal file
133
plinth/modules/coquelicot/__init__.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Plinth module to configure coquelicot.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from plinth import service as service_module
|
||||||
|
from plinth import action_utils, actions, frontpage
|
||||||
|
from plinth.menu import main_menu
|
||||||
|
|
||||||
|
from .manifest import clients
|
||||||
|
|
||||||
|
clients = clients
|
||||||
|
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
managed_services = ['coquelicot']
|
||||||
|
|
||||||
|
managed_packages = ['coquelicot']
|
||||||
|
|
||||||
|
name = _('Coquelicot')
|
||||||
|
|
||||||
|
short_description = _('File Sharing')
|
||||||
|
|
||||||
|
description = [
|
||||||
|
_('Coquelicot is a “one-click” file sharing web application with a focus '
|
||||||
|
'on protecting users’ privacy. It is best used for quickly sharing a '
|
||||||
|
'single file. '),
|
||||||
|
_('This Coquelicot instance is exposed to the public but requires an '
|
||||||
|
'upload password to prevent unauthorized access. You can set a new '
|
||||||
|
'upload password in the form that will appear below after installation. '
|
||||||
|
'The default upload password is "test".')
|
||||||
|
]
|
||||||
|
|
||||||
|
service = None
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
"""Intialize the module."""
|
||||||
|
menu = main_menu.get('apps')
|
||||||
|
menu.add_urlname(name, 'glyphicon-open-file', 'coquelicot:index',
|
||||||
|
short_description)
|
||||||
|
|
||||||
|
global service
|
||||||
|
setup_helper = globals()['setup_helper']
|
||||||
|
if setup_helper.get_state() != 'needs-setup':
|
||||||
|
service = service_module.Service(managed_services[0], name, ports=[
|
||||||
|
'http', 'https'
|
||||||
|
], is_external=True, is_enabled=is_enabled, enable=enable,
|
||||||
|
disable=disable,
|
||||||
|
is_running=is_running)
|
||||||
|
|
||||||
|
if is_enabled():
|
||||||
|
add_shortcut()
|
||||||
|
|
||||||
|
|
||||||
|
def setup(helper, old_version=None):
|
||||||
|
"""Install and configure the module."""
|
||||||
|
helper.install(managed_packages)
|
||||||
|
helper.call('post', actions.superuser_run, 'coquelicot', ['setup'])
|
||||||
|
helper.call('post', actions.superuser_run, 'coquelicot', ['enable'])
|
||||||
|
global service
|
||||||
|
if service is None:
|
||||||
|
service = service_module.Service(managed_services[0], name, ports=[
|
||||||
|
'http', 'https'
|
||||||
|
], is_external=True, is_enabled=is_enabled, enable=enable,
|
||||||
|
disable=disable,
|
||||||
|
is_running=is_running)
|
||||||
|
helper.call('post', service.notify_enabled, None, True)
|
||||||
|
helper.call('post', add_shortcut)
|
||||||
|
|
||||||
|
|
||||||
|
def add_shortcut():
|
||||||
|
"""Helper method to add a shortcut to the frontpage."""
|
||||||
|
frontpage.add_shortcut('coquelicot', name,
|
||||||
|
short_description=short_description,
|
||||||
|
url='/coquelicot', login_required=True)
|
||||||
|
|
||||||
|
|
||||||
|
def is_running():
|
||||||
|
"""Return whether the service is running."""
|
||||||
|
return action_utils.service_is_running('coquelicot')
|
||||||
|
|
||||||
|
|
||||||
|
def is_enabled():
|
||||||
|
"""Return whether the module is enabled."""
|
||||||
|
return (action_utils.service_is_enabled('coquelicot')
|
||||||
|
and action_utils.webserver_is_enabled('coquelicot-freedombox'))
|
||||||
|
|
||||||
|
|
||||||
|
def enable():
|
||||||
|
"""Enable the module."""
|
||||||
|
actions.superuser_run('coquelicot', ['enable'])
|
||||||
|
add_shortcut()
|
||||||
|
|
||||||
|
|
||||||
|
def disable():
|
||||||
|
"""Disable the module."""
|
||||||
|
actions.superuser_run('coquelicot', ['disable'])
|
||||||
|
frontpage.remove_shortcut('coquelicot')
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_max_file_size():
|
||||||
|
"""Get the current value of maximum file size."""
|
||||||
|
size = actions.superuser_run('coquelicot', ['get-max-file-size'])
|
||||||
|
return int(size.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def diagnose():
|
||||||
|
"""Run diagnostics and return the results."""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
results.extend(
|
||||||
|
action_utils.diagnose_url_on_all('https://{host}/coquelicot',
|
||||||
|
check_certificate=False))
|
||||||
|
|
||||||
|
return results
|
||||||
37
plinth/modules/coquelicot/forms.py
Normal file
37
plinth/modules/coquelicot/forms.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Plinth form for configuring Coquelicot.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from plinth.forms import ServiceForm
|
||||||
|
|
||||||
|
|
||||||
|
class CoquelicotForm(ServiceForm): # pylint: disable=W0232
|
||||||
|
"""Coquelicot configuration form."""
|
||||||
|
upload_password = forms.CharField(
|
||||||
|
label=_('Upload Password'),
|
||||||
|
help_text=_('Set a new upload password for Coquelicot. '
|
||||||
|
'Leave this field blank to keep the current password.'),
|
||||||
|
required=False, widget=forms.PasswordInput)
|
||||||
|
max_file_size = forms.IntegerField(
|
||||||
|
label=_("Maximum File Size (in MiB)"), help_text=_(
|
||||||
|
'Set the maximum size of the files that can be uploaded to '
|
||||||
|
'Coquelicot.'), required=False, min_value=0)
|
||||||
28
plinth/modules/coquelicot/manifest.py
Normal file
28
plinth/modules/coquelicot/manifest.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from plinth.clients import validate
|
||||||
|
|
||||||
|
clients = validate([{
|
||||||
|
'name': _('coquelicot'),
|
||||||
|
'platforms': [{
|
||||||
|
'type': 'web',
|
||||||
|
'url': '/coquelicot'
|
||||||
|
}]
|
||||||
|
}])
|
||||||
27
plinth/modules/coquelicot/urls.py
Normal file
27
plinth/modules/coquelicot/urls.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
URLs for the coquelicot module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from .views import CoquelicotServiceView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^apps/coquelicot/$', CoquelicotServiceView.as_view(), name='index'),
|
||||||
|
]
|
||||||
72
plinth/modules/coquelicot/views.py
Normal file
72
plinth/modules/coquelicot/views.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Plinth views for Coquelicot.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
from plinth import actions, views
|
||||||
|
from plinth.errors import ActionError
|
||||||
|
from plinth.modules.coquelicot import (clients, description,
|
||||||
|
get_current_max_file_size)
|
||||||
|
|
||||||
|
from .forms import CoquelicotForm
|
||||||
|
|
||||||
|
|
||||||
|
class CoquelicotServiceView(views.ServiceView):
|
||||||
|
"""Serve configuration page."""
|
||||||
|
clients = clients
|
||||||
|
description = description
|
||||||
|
diagnostics_module_name = 'coquelicot'
|
||||||
|
service_id = 'coquelicot'
|
||||||
|
form_class = CoquelicotForm
|
||||||
|
show_status_block = True
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
"""Return the status of the service to fill in the form."""
|
||||||
|
initial = super().get_initial()
|
||||||
|
initial['max_file_size'] = get_current_max_file_size()
|
||||||
|
return initial
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
"""Apply the changes submitted in the form."""
|
||||||
|
form_data = form.cleaned_data
|
||||||
|
|
||||||
|
if form_data['upload_password']:
|
||||||
|
try:
|
||||||
|
actions.superuser_run(
|
||||||
|
'coquelicot', ['set-upload-password'],
|
||||||
|
input=form_data['upload_password'].encode())
|
||||||
|
messages.success(self.request, _('Upload password updated'))
|
||||||
|
except ActionError as e:
|
||||||
|
messages.error(self.request,
|
||||||
|
_('Failed to update upload password'))
|
||||||
|
|
||||||
|
max_file_size = form_data['max_file_size']
|
||||||
|
if max_file_size and max_file_size != get_current_max_file_size():
|
||||||
|
try:
|
||||||
|
actions.superuser_run(
|
||||||
|
'coquelicot', ['set-max-file-size',
|
||||||
|
str(max_file_size)])
|
||||||
|
messages.success(self.request, _('Maximum file size updated'))
|
||||||
|
except ActionError as e:
|
||||||
|
messages.error(self.request,
|
||||||
|
_('Failed to update maximum file size'))
|
||||||
|
|
||||||
|
return super().form_valid(form)
|
||||||
BIN
static/themes/default/icons/coquelicot.png
Normal file
BIN
static/themes/default/icons/coquelicot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Loading…
x
Reference in New Issue
Block a user