mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-09-19 04:59:01 +00:00
searx: Use privileged decorator for actions
Tests: - Functional tests work - Initial setup works - UWSGI configuration is created and daemon is running. - Enabling and disabling public access works. Public access file is created/removed. App page shows current value. If exception is raised, error is shown properly. - Setting safe search to all three values works. Configuration file is updated properly. App page shows current value properly. If exception is raised, error is shown properly. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
8db063b59b
commit
52f42a4f74
@ -1,13 +1,10 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""FreedomBox app to configure Searx."""
|
||||||
FreedomBox app to configure Searx.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from plinth import actions
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||||
@ -16,7 +13,7 @@ from plinth.modules.firewall.components import Firewall
|
|||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.package import Packages
|
from plinth.package import Packages
|
||||||
|
|
||||||
from . import manifest
|
from . import manifest, privileged
|
||||||
|
|
||||||
_description = [
|
_description = [
|
||||||
_('Searx is a privacy-respecting Internet metasearch engine. '
|
_('Searx is a privacy-respecting Internet metasearch engine. '
|
||||||
@ -95,9 +92,9 @@ class SearxApp(app_module.App):
|
|||||||
def setup(self, old_version):
|
def setup(self, old_version):
|
||||||
"""Install and configure the app."""
|
"""Install and configure the app."""
|
||||||
super().setup(old_version)
|
super().setup(old_version)
|
||||||
actions.superuser_run('searx', ['setup'])
|
privileged.setup()
|
||||||
if not old_version or old_version < 3:
|
if not old_version or old_version < 3:
|
||||||
actions.superuser_run('searx', ['disable-public-access'])
|
privileged.disable_public_access()
|
||||||
self.enable()
|
self.enable()
|
||||||
self.set_shortcut_login_required(True)
|
self.set_shortcut_login_required(True)
|
||||||
|
|
||||||
@ -115,12 +112,6 @@ class SearxWebserverAuth(Webserver):
|
|||||||
super().enable()
|
super().enable()
|
||||||
|
|
||||||
|
|
||||||
def get_safe_search_setting():
|
|
||||||
"""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():
|
def is_public_access_enabled():
|
||||||
"""Check whether public access is enabled for Searx."""
|
"""Check whether public access is enabled for Searx."""
|
||||||
return os.path.exists(manifest.PUBLIC_ACCESS_SETTING_FILE)
|
return os.path.exists(manifest.PUBLIC_ACCESS_SETTING_FILE)
|
||||||
@ -128,7 +119,7 @@ def is_public_access_enabled():
|
|||||||
|
|
||||||
def enable_public_access():
|
def enable_public_access():
|
||||||
"""Allow Searx app to be accessed by anyone with access."""
|
"""Allow Searx app to be accessed by anyone with access."""
|
||||||
actions.superuser_run('searx', ['enable-public-access'])
|
privileged.enable_public_access()
|
||||||
app = app_module.App.get('searx')
|
app = app_module.App.get('searx')
|
||||||
app.get_component('webserver-searx-auth').disable()
|
app.get_component('webserver-searx-auth').disable()
|
||||||
app.set_shortcut_login_required(False)
|
app.set_shortcut_login_required(False)
|
||||||
@ -136,7 +127,7 @@ def enable_public_access():
|
|||||||
|
|
||||||
def disable_public_access():
|
def disable_public_access():
|
||||||
"""Allow Searx app to be accessed by logged-in users only."""
|
"""Allow Searx app to be accessed by logged-in users only."""
|
||||||
actions.superuser_run('searx', ['disable-public-access'])
|
privileged.disable_public_access()
|
||||||
app = app_module.App.get('searx')
|
app = app_module.App.get('searx')
|
||||||
app.get_component('webserver-searx-auth').enable()
|
app.get_component('webserver-searx-auth').enable()
|
||||||
app.set_shortcut_login_required(True)
|
app.set_shortcut_login_required(True)
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""Django form for configuring Searx."""
|
||||||
Django form for configuring Searx.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@ -9,6 +7,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
class SearxForm(forms.Form):
|
class SearxForm(forms.Form):
|
||||||
"""Searx configuration form."""
|
"""Searx configuration form."""
|
||||||
|
|
||||||
safe_search = forms.ChoiceField(
|
safe_search = forms.ChoiceField(
|
||||||
label=_('Safe Search'), help_text=_(
|
label=_('Safe Search'), help_text=_(
|
||||||
'Select the default family filter to apply to your search results.'
|
'Select the default family filter to apply to your search results.'
|
||||||
|
|||||||
76
actions/searx → plinth/modules/searx/privileged.py
Executable file → Normal file
76
actions/searx → plinth/modules/searx/privileged.py
Executable file → Normal file
@ -1,10 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""Configure searx."""
|
||||||
Configuration helper for searx.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import gzip
|
import gzip
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
@ -15,6 +11,7 @@ import augeas
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
|
from plinth.actions import privileged
|
||||||
from plinth.modules.searx.manifest import PUBLIC_ACCESS_SETTING_FILE
|
from plinth.modules.searx.manifest import PUBLIC_ACCESS_SETTING_FILE
|
||||||
from plinth.utils import gunzip
|
from plinth.utils import gunzip
|
||||||
|
|
||||||
@ -23,34 +20,6 @@ SETTINGS_FILE = '/etc/searx/settings.yml'
|
|||||||
UWSGI_FILE = '/etc/uwsgi/apps-available/searx.ini'
|
UWSGI_FILE = '/etc/uwsgi/apps-available/searx.ini'
|
||||||
|
|
||||||
|
|
||||||
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='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')
|
|
||||||
safe_search.add_argument(
|
|
||||||
'filter', type=int,
|
|
||||||
help='Filter results. 0: None, 1: Moderate, 2: Strict')
|
|
||||||
|
|
||||||
subparsers.add_parser('get-safe-search',
|
|
||||||
help='Print the value of the safe search setting.')
|
|
||||||
|
|
||||||
subparsers.required = True
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def _copy_uwsgi_configuration():
|
def _copy_uwsgi_configuration():
|
||||||
"""Copy example uwsgi configuration
|
"""Copy example uwsgi configuration
|
||||||
|
|
||||||
@ -100,21 +69,22 @@ def _set_safe_search(settings):
|
|||||||
settings['search']['safe_search'] = 1
|
settings['search']['safe_search'] = 1
|
||||||
|
|
||||||
|
|
||||||
def subcommand_set_safe_search(arguments):
|
@privileged
|
||||||
|
def set_safe_search(filter_: int):
|
||||||
"""Set safe search filter for search results."""
|
"""Set safe search filter for search results."""
|
||||||
value = arguments.filter
|
|
||||||
settings = read_settings()
|
settings = read_settings()
|
||||||
settings['search']['safe_search'] = value
|
settings['search']['safe_search'] = filter_
|
||||||
write_settings(settings)
|
write_settings(settings)
|
||||||
|
|
||||||
|
|
||||||
def subcommand_get_safe_search(_):
|
@privileged
|
||||||
"""Print the value of the safe search setting."""
|
def get_safe_search() -> int:
|
||||||
|
"""Return the value of the safe search setting."""
|
||||||
if os.path.exists(SETTINGS_FILE):
|
if os.path.exists(SETTINGS_FILE):
|
||||||
settings = read_settings()
|
settings = read_settings()
|
||||||
print(settings['search']['safe_search'])
|
return int(settings['search']['safe_search'])
|
||||||
else:
|
else:
|
||||||
print(0)
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def read_settings():
|
def read_settings():
|
||||||
@ -138,15 +108,16 @@ def _get_example_settings_file():
|
|||||||
|
|
||||||
|
|
||||||
def _update_search_engines(settings):
|
def _update_search_engines(settings):
|
||||||
"""Updates settings with the latest supported search engines."""
|
"""Update settings with the latest supported search engines."""
|
||||||
example_settings_file = _get_example_settings_file()
|
example_settings_file = _get_example_settings_file()
|
||||||
open_func = gzip.open if example_settings_file.suffix == '.gz' else open
|
open_func = gzip.open if example_settings_file.suffix == '.gz' else open
|
||||||
with open_func(example_settings_file, 'rb') as example_settings:
|
with open_func(example_settings_file, 'rb') as example_settings:
|
||||||
settings['engines'] = yaml.safe_load(example_settings)['engines']
|
settings['engines'] = yaml.safe_load(example_settings)['engines']
|
||||||
|
|
||||||
|
|
||||||
def subcommand_setup(_):
|
@privileged
|
||||||
"""Post installation actions for Searx"""
|
def setup():
|
||||||
|
"""Post installation actions for Searx."""
|
||||||
_copy_uwsgi_configuration()
|
_copy_uwsgi_configuration()
|
||||||
_update_uwsgi_configuration()
|
_update_uwsgi_configuration()
|
||||||
|
|
||||||
@ -169,25 +140,14 @@ def subcommand_setup(_):
|
|||||||
action_utils.service_restart('uwsgi')
|
action_utils.service_restart('uwsgi')
|
||||||
|
|
||||||
|
|
||||||
def subcommand_enable_public_access(_):
|
@privileged
|
||||||
|
def enable_public_access():
|
||||||
"""Enable public access to the SearX application."""
|
"""Enable public access to the SearX application."""
|
||||||
open(PUBLIC_ACCESS_SETTING_FILE, 'w', encoding='utf-8').close()
|
open(PUBLIC_ACCESS_SETTING_FILE, 'w', encoding='utf-8').close()
|
||||||
|
|
||||||
|
|
||||||
def subcommand_disable_public_access(_):
|
@privileged
|
||||||
|
def disable_public_access():
|
||||||
"""Disable public access to the SearX application."""
|
"""Disable public access to the SearX application."""
|
||||||
if os.path.exists(PUBLIC_ACCESS_SETTING_FILE):
|
if os.path.exists(PUBLIC_ACCESS_SETTING_FILE):
|
||||||
os.remove(PUBLIC_ACCESS_SETTING_FILE)
|
os.remove(PUBLIC_ACCESS_SETTING_FILE)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Parse arguments and perform all duties."""
|
|
||||||
arguments = parse_arguments()
|
|
||||||
|
|
||||||
subcommand = arguments.subcommand.replace('-', '_')
|
|
||||||
subcommand_method = globals()['subcommand_' + subcommand]
|
|
||||||
subcommand_method(arguments)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@ -1,29 +1,27 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""Django views for Searx."""
|
||||||
Django views for Searx.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from plinth import actions
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import views
|
from plinth import views
|
||||||
from plinth.errors import ActionError
|
|
||||||
from plinth.modules import searx
|
from plinth.modules import searx
|
||||||
|
|
||||||
|
from . import privileged
|
||||||
from .forms import SearxForm
|
from .forms import SearxForm
|
||||||
|
|
||||||
|
|
||||||
class SearxAppView(views.AppView):
|
class SearxAppView(views.AppView):
|
||||||
"""Serve configuration page."""
|
"""Serve configuration page."""
|
||||||
|
|
||||||
app_id = 'searx'
|
app_id = 'searx'
|
||||||
form_class = SearxForm
|
form_class = SearxForm
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
"""Return the status of the service to fill in the form."""
|
"""Return the status of the service to fill in the form."""
|
||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
initial['safe_search'] = searx.get_safe_search_setting()
|
initial['safe_search'] = privileged.get_safe_search()
|
||||||
initial['public_access'] = searx.is_public_access_enabled() and \
|
initial['public_access'] = searx.is_public_access_enabled() and \
|
||||||
app_module.App.get('searx').is_enabled()
|
app_module.App.get('searx').is_enabled()
|
||||||
return initial
|
return initial
|
||||||
@ -35,10 +33,9 @@ class SearxAppView(views.AppView):
|
|||||||
|
|
||||||
if str(old_data['safe_search']) != form_data['safe_search']:
|
if str(old_data['safe_search']) != form_data['safe_search']:
|
||||||
try:
|
try:
|
||||||
actions.superuser_run(
|
privileged.set_safe_search(int(form_data['safe_search']))
|
||||||
'searx', ['set-safe-search', form_data['safe_search']])
|
|
||||||
messages.success(self.request, _('Configuration updated.'))
|
messages.success(self.request, _('Configuration updated.'))
|
||||||
except ActionError:
|
except Exception:
|
||||||
messages.error(self.request,
|
messages.error(self.request,
|
||||||
_('An error occurred during configuration.'))
|
_('An error occurred during configuration.'))
|
||||||
|
|
||||||
@ -49,7 +46,7 @@ class SearxAppView(views.AppView):
|
|||||||
else:
|
else:
|
||||||
searx.disable_public_access()
|
searx.disable_public_access()
|
||||||
messages.success(self.request, _('Configuration updated.'))
|
messages.success(self.request, _('Configuration updated.'))
|
||||||
except ActionError:
|
except Exception:
|
||||||
messages.error(self.request,
|
messages.error(self.request,
|
||||||
_('An error occurred during configuration.'))
|
_('An error occurred during configuration.'))
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user