diff --git a/plinth/__main__.py b/plinth/__main__.py index dc189411d..a633d0054 100644 --- a/plinth/__main__.py +++ b/plinth/__main__.py @@ -24,14 +24,14 @@ import stat import sys import warnings +import axes +import cherrypy import django.conf import django.core.management import django.core.wsgi from django.contrib.messages import constants as message_constants -import axes -import cherrypy -from plinth import cfg, menu, module_loader, service, setup +from plinth import cfg, frontpage, menu, module_loader, service, setup axes.default_app_config = "plinth.axes_app_config.AppConfig" precedence_commandline_arguments = ["server_dir", "develop"] @@ -47,9 +47,10 @@ def parse_arguments(): # TODO: server_dir is actually a url prefix; use a better variable name parser.add_argument('--server_dir', default=None, help='web server path under which to serve') - parser.add_argument('--develop', action='store_true', default=None, - help=('run Plinth *insecurely* from current folder; ' - 'enable auto-reloading and debugging options')) + parser.add_argument( + '--develop', action='store_true', default=None, + help=('run Plinth *insecurely* from current folder; ' + 'enable auto-reloading and debugging options')) parser.add_argument( '--setup', default=False, nargs='*', help='run setup tasks on all essential modules and exit') @@ -283,7 +284,7 @@ def configure_django(): DEBUG=cfg.develop, FORCE_SCRIPT_NAME=cfg.server_dir, INSTALLED_APPS=applications, - IPWARE_META_PRECEDENCE_ORDER=('HTTP_X_FORWARDED_FOR',), + IPWARE_META_PRECEDENCE_ORDER=('HTTP_X_FORWARDED_FOR', ), LOGGING=logging_configuration, LOGIN_URL='users:login', LOGIN_REDIRECT_URL='index', @@ -301,7 +302,8 @@ def configure_django(): 'plinth.middleware.AdminRequiredMiddleware', 'plinth.middleware.FirstSetupMiddleware', 'plinth.modules.first_boot.middleware.FirstBootMiddleware', - 'plinth.middleware.SetupMiddleware', ), + 'plinth.middleware.SetupMiddleware', + ), ROOT_URLCONF='plinth.urls', SECURE_BROWSER_XSS_FILTER=True, SECURE_CONTENT_TYPE_NOSNIFF=True, @@ -314,7 +316,8 @@ def configure_django(): 'captcha-image', 'captcha-image-2x', 'captcha-audio', - 'captcha-refresh', ), + 'captcha-refresh', + ), TEMPLATES=templates, USE_L10N=True, USE_X_FORWARDED_HOST=cfg.use_x_forwarded_host) @@ -422,6 +425,7 @@ def main(): menu.init() module_loader.load_modules() + frontpage.add_custom_shortcuts() if arguments.setup is not False: run_setup_and_exit(arguments.setup, allow_install=True) diff --git a/plinth/frontpage.py b/plinth/frontpage.py index e3429bb99..d5397b6aa 100644 --- a/plinth/frontpage.py +++ b/plinth/frontpage.py @@ -17,6 +17,11 @@ """ Manage application shortcuts on front page. """ +import json +import os + +from plinth import cfg + from . import actions shortcuts = {} @@ -51,6 +56,37 @@ def get_shortcuts(username=None, web_apps_only=False, sort_by='label'): return sorted(shortcuts_to_return.values(), key=lambda item: item[sort_by]) +def add_custom_shortcuts(): + custom_shortcuts = get_custom_shortcuts() + + if custom_shortcuts: + for shortcut in custom_shortcuts['shortcuts']: + web_app_url = _extract_web_app_url(shortcut) + if web_app_url: + add_shortcut(None, shortcut['name'], + shortcut['short_description'], + icon=shortcut['icon_url'], url=web_app_url) + + +def _extract_web_app_url(custom_shortcut): + if custom_shortcut.get('clients'): + for client in custom_shortcut['clients']: + if client.get('platforms'): + for platform in client['platforms']: + if platform['type'] == 'web': + return platform['url'] + + +def get_custom_shortcuts(): + cfg_dir = os.path.dirname(cfg.config_file) + shortcuts_file = os.path.join(cfg_dir, 'custom-shortcuts.json') + if os.path.isfile(shortcuts_file) and os.stat(shortcuts_file).st_size: + with open(shortcuts_file) as shortcuts: + custom_shortcuts = json.load(shortcuts) + return custom_shortcuts + return None + + def add_shortcut(shortcut_id, name, short_description="", login_required=False, icon=None, url=None, details=None, configure_url=None, allowed_groups=None): diff --git a/plinth/modules/api/views.py b/plinth/modules/api/views.py index 4433ed0b1..2ddbc5032 100644 --- a/plinth/modules/api/views.py +++ b/plinth/modules/api/views.py @@ -20,13 +20,12 @@ FreedomBox app for api for android app. import copy import json -import os from django.core.serializers.json import DjangoJSONEncoder from django.http import HttpResponse from django.templatetags.static import static -from plinth import cfg, frontpage, module_loader +from plinth import frontpage, module_loader from plinth.modules import names @@ -54,24 +53,14 @@ def shortcuts(request, **kwargs): def get_shortcuts_as_json(username=None): shortcuts = [ _get_shortcut_data(shortcut['id'].split('_')[0], shortcut) - for shortcut in frontpage.get_shortcuts(username) + for shortcut in frontpage.get_shortcuts(username) if shortcut['id'] ] - custom_shortcuts = get_custom_shortcuts() + custom_shortcuts = frontpage.get_custom_shortcuts() if custom_shortcuts: shortcuts += custom_shortcuts['shortcuts'] return {'shortcuts': shortcuts} -def get_custom_shortcuts(): - cfg_dir = os.path.dirname(cfg.config_file) - shortcuts_file = os.path.join(cfg_dir, 'custom-shortcuts.json') - if os.path.isfile(shortcuts_file) and os.stat(shortcuts_file).st_size: - with open(shortcuts_file) as shortcuts: - custom_shortcuts = json.load(shortcuts) - return custom_shortcuts - return None - - def _get_shortcut_data(module_name, shortcut): """Return detailed information about a shortcut.""" module = module_loader.loaded_modules[module_name] diff --git a/plinth/modules/config/forms.py b/plinth/modules/config/forms.py index 734abe1cb..0d457478c 100644 --- a/plinth/modules/config/forms.py +++ b/plinth/modules/config/forms.py @@ -44,7 +44,8 @@ def domain_label_validator(domainname): def get_default_app_choices(): shortcuts = frontpage.get_shortcuts(web_apps_only=True, sort_by='name') - apps = [(shortcut['id'], shortcut['name']) for shortcut in shortcuts] + apps = [(shortcut['id'], shortcut['name']) for shortcut in shortcuts + if shortcut['id']] return [('plinth', 'FreedomBox Service (Plinth)')] + apps diff --git a/plinth/templates/index.html b/plinth/templates/index.html index 03dedd75e..93967258f 100644 --- a/plinth/templates/index.html +++ b/plinth/templates/index.html @@ -87,7 +87,11 @@ {{ shortcut.name }}
- + {% if "custom" in shortcut.icon %} + + {% else %} + + {% endif %}
{{ shortcut.short_description }} diff --git a/plinth/tests/data/etc/plinth/custom-shortcuts.json b/plinth/tests/data/etc/plinth/custom-shortcuts.json index dde31ee29..9937b576f 100644 --- a/plinth/tests/data/etc/plinth/custom-shortcuts.json +++ b/plinth/tests/data/etc/plinth/custom-shortcuts.json @@ -1 +1 @@ -{"shortcuts": [{"name": "NextCloud", "short_description": "File Hosting Service", "description": "Nextcloud is a suite of client-server software for creating and using file hosting services.", "icon_url": "/plinth/custom/static/themes/default/icons/nextcloud.png", "clients": [{"name": "nextcloud", "platforms": [{"type": "web", "url": "/nextcloud"}]}]}]} \ No newline at end of file +{"shortcuts": [{"name": "NextCloud", "short_description": "File Hosting Service", "description": ["Nextcloud is a suite of client-server software for creating and using file hosting services."], "icon_url": "/plinth/custom/static/themes/default/icons/nextcloud.png", "clients": [{"name": "nextcloud", "platforms": [{"type": "web", "url": "/nextcloud"}]}]}]} \ No newline at end of file diff --git a/plinth/tests/test_custom_shortcuts.py b/plinth/tests/test_custom_shortcuts.py index be8e7240b..5ff44a000 100644 --- a/plinth/tests/test_custom_shortcuts.py +++ b/plinth/tests/test_custom_shortcuts.py @@ -37,9 +37,10 @@ NEXTCLOUD_SHORTCUT = { 'NextCloud', 'short_description': 'File Hosting Service', - 'description': + 'description': [ 'Nextcloud is a suite of client-server software for creating ' - 'and using file hosting services.', + 'and using file hosting services.' + ], 'icon_url': '/plinth/custom/static/themes/default/icons/nextcloud.png', 'clients': [{