diff --git a/actions/searx b/actions/searx
index a41ad11cb..3398b40d6 100755
--- a/actions/searx
+++ b/actions/searx
@@ -20,11 +20,11 @@ Configuration helper for searx.
"""
import argparse
-import augeas
import os
import secrets
import shutil
+import augeas
import yaml
from plinth import action_utils
@@ -45,6 +45,12 @@ def parse_arguments():
subparsers.add_parser(
'setup', help='Perform post-installation operations for Searx')
+ subparsers.add_parser('enable-public-access',
+ help='Enable public access to the Searx application')
+ subparsers.add_parser(
+ 'disable-public-access',
+ help='Disable public access to the Searx application')
+
safe_search = subparsers.add_parser(
'set-safe-search',
help='Set the default filter for safe search on Searx')
@@ -81,7 +87,8 @@ def _update_uwsgi_configuration():
aug.set('/augeas/load/inifile/lens', 'Puppet.lns')
aug.set('/augeas/load/inifile/incl[last() + 1]', UWSGI_FILE)
aug.load()
- aug.set('/files/etc/uwsgi/apps-available/searx.ini/uwsgi/autoload', 'false')
+ aug.set('/files/etc/uwsgi/apps-available/searx.ini/uwsgi/autoload',
+ 'false')
aug.save()
@@ -153,14 +160,26 @@ def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.uwsgi_enable('searx')
action_utils.webserver_enable('searx-freedombox')
+ action_utils.webserver_enable('searx-freedombox-auth')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.webserver_disable('searx-freedombox')
+ action_utils.webserver_disable('searx-freedombox-auth')
action_utils.uwsgi_disable('searx')
+def subcommand_enable_public_access(_):
+ """Enable public access to the SearX application."""
+ action_utils.webserver_disable('searx-freedombox-auth')
+
+
+def subcommand_disable_public_access(_):
+ """Disable public access to the SearX application."""
+ action_utils.webserver_enable('searx-freedombox-auth')
+
+
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()
diff --git a/functional_tests/features/searx.feature b/functional_tests/features/searx.feature
index 72e507d46..266607720 100644
--- a/functional_tests/features/searx.feature
+++ b/functional_tests/features/searx.feature
@@ -38,3 +38,18 @@ Scenario: Disable searx application
Given the searx application is enabled
When I disable the searx application
Then the searx site should not be available
+
+Scenario: Enable public access
+ Given the searx application is enabled
+ And I enable public access in searx
+ And I'm a logged out user
+ Then searx app should be visible on the front page
+ And the searx site should be available
+
+Scenario: Disable public access
+ Given the searx application is enabled
+ And I disable public access in searx
+ And I'm a logged out user
+ Then searx app should not be visible on the front page
+ And the searx site should not be available
+
diff --git a/functional_tests/step_definitions/application.py b/functional_tests/step_definitions/application.py
index f64dd87a7..cb0cd4fab 100644
--- a/functional_tests/step_definitions/application.py
+++ b/functional_tests/step_definitions/application.py
@@ -423,3 +423,26 @@ def openvpn_profile_downloadable(browser):
def openvpn_profile_download_compare(browser, openvpn_download_profile):
new_profile = application.openvpn_download_profile(browser)
assert openvpn_download_profile == new_profile
+
+
+@given('I enable public access in searx')
+def searx_enable_public_access(browser):
+ application.searx_enable_public_access(browser)
+
+
+@given('I disable public access in searx')
+def searx_disable_public_access(browser):
+ application.searx_disable_public_access(browser)
+
+
+@then(parsers.parse('{app_name:w} app should be visible on the front page'))
+def app_visible_on_front_page(browser, app_name):
+ shortcuts = application.find_on_front_page(browser, app_name)
+ assert len(shortcuts) == 1
+
+
+@then(
+ parsers.parse('{app_name:w} app should not be visible on the front page'))
+def app_visible_on_front_page(browser, app_name):
+ shortcuts = application.find_on_front_page(browser, app_name)
+ assert len(shortcuts) == 0
diff --git a/functional_tests/support/application.py b/functional_tests/support/application.py
index 72bf7a34a..f14dc205a 100644
--- a/functional_tests/support/application.py
+++ b/functional_tests/support/application.py
@@ -469,3 +469,23 @@ def openvpn_download_profile(browser):
interface.nav_to_module(browser, 'openvpn')
url = browser.find_by_css('.form-profile')['action']
return _download_file(browser, url)
+
+
+def searx_enable_public_access(browser):
+ """Enable Public Access in SearX"""
+ interface.nav_to_module(browser, 'searx')
+ browser.find_by_id('id_public_access').check()
+ interface.submit(browser, form_class='form-configuration')
+
+
+def searx_disable_public_access(browser):
+ """Enable Public Access in SearX"""
+ interface.nav_to_module(browser, 'searx')
+ browser.find_by_id('id_public_access').uncheck()
+ interface.submit(browser, form_class='form-configuration')
+
+
+def find_on_front_page(browser, app_name):
+ browser.visit(default_url)
+ shortcuts = browser.find_link_by_href(f'/{app_name}/')
+ return shortcuts
diff --git a/functional_tests/support/site.py b/functional_tests/support/site.py
index a0f1ec027..123866575 100644
--- a/functional_tests/support/site.py
+++ b/functional_tests/support/site.py
@@ -21,7 +21,6 @@ import pathlib
import time
import requests
-
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
@@ -45,10 +44,14 @@ def get_site_url(site_name):
def is_available(browser, site_name):
- browser.visit(config['DEFAULT']['url'] + get_site_url(site_name))
+ url_to_visit = config['DEFAULT']['url'] + get_site_url(site_name)
+ browser.visit(url_to_visit)
time.sleep(3)
browser.reload()
- return '404' not in browser.title
+ not_404 = '404' not in browser.title
+ # A trailing slash might be appended by Apache redirect rules
+ no_redirect = url_to_visit.strip('/') == browser.url.strip('/')
+ return not_404 and no_redirect
def access_url(browser, site_name):
diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py
index d997b2c94..3d5200cc1 100644
--- a/plinth/modules/searx/__init__.py
+++ b/plinth/modules/searx/__init__.py
@@ -30,7 +30,7 @@ from .manifest import backup, clients
clients = clients
-version = 2
+version = 3
managed_services = ['searx']
@@ -68,10 +68,17 @@ class SearxApp(app_module.App):
shortcut = frontpage.Shortcut(
'shortcut-searx', name, short_description=short_description,
- icon='searx', url='/searx/', clients=clients, login_required=True,
+ icon='searx', url='/searx/', clients=clients,
+ login_required=(not is_public_access_enabled()),
allowed_groups=[group[0]])
self.add(shortcut)
+ def set_shortcut_login_required(self, login_required):
+ """Change the login_required property of shortcut."""
+ shortcut = self.remove('shortcut-searx')
+ shortcut.login_required = login_required
+ self.add(shortcut)
+
def init():
"""Intialize the module."""
@@ -95,8 +102,12 @@ def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'searx', ['setup'])
- if not old_version:
+ if not old_version or old_version < 3:
helper.call('post', actions.superuser_run, 'searx', ['enable'])
+ helper.call('post', actions.superuser_run, 'searx',
+ ['disable-public-access'])
+ app.set_shortcut_login_required(True)
+ app.enable()
global service
if service is None:
@@ -108,11 +119,16 @@ def setup(helper, old_version=None):
def get_safe_search_setting():
- """Get the current value of the safe search setting for Seax."""
+ """Get the current value of the safe search setting for Searx."""
value = actions.superuser_run('searx', ['get-safe-search'])
return int(value.strip())
+def is_public_access_enabled():
+ """Check whether public access is enabled for Searx."""
+ return not action_utils.webserver_is_enabled('searx-freedombox-auth')
+
+
def is_enabled():
"""Return whether the module is enabled."""
return (action_utils.webserver_is_enabled('searx-freedombox')
diff --git a/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox-auth.conf b/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox-auth.conf
new file mode 100644
index 000000000..86c4e727b
--- /dev/null
+++ b/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox-auth.conf
@@ -0,0 +1,9 @@
+
+ Include includes/freedombox-single-sign-on.conf
+
+
+ TKTAuthToken "web-search" "admin"
+
+
+ ProxyPass unix:/run/uwsgi/app/searx/socket|uwsgi://uwsgi-uds-searx/
+
diff --git a/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox.conf b/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox.conf
index 2efe558f6..ceaa0b176 100644
--- a/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox.conf
+++ b/plinth/modules/searx/data/etc/apache2/conf-available/searx-freedombox.conf
@@ -9,12 +9,6 @@
- Include includes/freedombox-single-sign-on.conf
-
-
- TKTAuthToken "web-search" "admin"
-
-
ProxyPass unix:/run/uwsgi/app/searx/socket|uwsgi://uwsgi-uds-searx/
diff --git a/plinth/modules/searx/forms.py b/plinth/modules/searx/forms.py
index 89f95ddf5..22203cd4f 100644
--- a/plinth/modules/searx/forms.py
+++ b/plinth/modules/searx/forms.py
@@ -26,8 +26,11 @@ from plinth.forms import ServiceForm
class SearxForm(ServiceForm):
"""Searx configuration form."""
- safe_search = forms.ChoiceField(label=_('Safe Search'), help_text=_(
- 'Select the default family filter to apply to your search results.'),
- choices=((0, _('None')),
- (1, _('Moderate')),
- (2, _('Strict'))))
+ safe_search = forms.ChoiceField(
+ label=_('Safe Search'), help_text=_(
+ 'Select the default family filter to apply to your search results.'
+ ), choices=((0, _('None')), (1, _('Moderate')), (2, _('Strict'))))
+ public_access = forms.BooleanField(
+ label=_('Public Access'), help_text=_(
+ 'Allow this application to be used by anyone who can reach it.'),
+ required=False)
diff --git a/plinth/modules/searx/views.py b/plinth/modules/searx/views.py
index 9e285477d..1c9e3421a 100644
--- a/plinth/modules/searx/views.py
+++ b/plinth/modules/searx/views.py
@@ -23,8 +23,9 @@ from django.utils.translation import ugettext as _
from plinth import actions, views
from plinth.errors import ActionError
-from plinth.modules.searx import (clients, description,
- get_safe_search_setting, manual_page)
+from plinth.modules.searx import (add_shortcut, clients, description,
+ get_safe_search_setting,
+ is_public_access_enabled, manual_page)
from .forms import SearxForm
@@ -43,6 +44,7 @@ class SearxServiceView(views.ServiceView):
"""Return the status of the service to fill in the form."""
initial = super().get_initial()
initial['safe_search'] = get_safe_search_setting()
+ initial['public_access'] = is_public_access_enabled()
return initial
def form_valid(self, form):
@@ -59,4 +61,16 @@ class SearxServiceView(views.ServiceView):
messages.error(self.request,
_('An error occurred during configuration.'))
+ if old_data['public_access'] != form_data['public_access']:
+ try:
+ if form_data['public_access']:
+ actions.superuser_run('searx', ['enable-public-access'])
+ else:
+ actions.superuser_run('searx', ['disable-public-access'])
+ add_shortcut()
+ messages.success(self.request, _('Configuration updated.'))
+ except ActionError as e:
+ messages.error(self.request,
+ _('An error occurred during configuration.'))
+
return super().form_valid(form)