Merge pull request #2270 from kvch/disable-preference-settings

Let admins lock user preferences
This commit is contained in:
Adam Tauber 2020-10-25 18:24:54 +01:00 committed by GitHub
commit 0a44fa8bb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 151 additions and 5 deletions

View file

@ -35,9 +35,10 @@ class ValidationException(Exception):
class Setting: class Setting:
"""Base class of user settings""" """Base class of user settings"""
def __init__(self, default_value, **kwargs): def __init__(self, default_value, locked=False, **kwargs):
super().__init__() super().__init__()
self.value = default_value self.value = default_value
self.locked = locked
for key, value in kwargs.items(): for key, value in kwargs.items():
setattr(self, key, value) setattr(self, key, value)
@ -115,6 +116,9 @@ class MultipleChoiceSetting(EnumStringSetting):
self.value = elements self.value = elements
def parse_form(self, data): # pylint: disable=missing-function-docstring def parse_form(self, data): # pylint: disable=missing-function-docstring
if self.locked:
return
self.value = [] self.value = []
for choice in data: for choice in data:
if choice in self.choices and choice not in self.value: # pylint: disable=no-member if choice in self.choices and choice not in self.value: # pylint: disable=no-member
@ -149,6 +153,9 @@ class SetSetting(Setting):
self.values.add(element) self.values.add(element)
def parse_form(self, data): # pylint: disable=missing-function-docstring def parse_form(self, data): # pylint: disable=missing-function-docstring
if self.locked:
return
elements = data.split(',') elements = data.split(',')
self.values = set(elements) # pylint: disable=attribute-defined-outside-init self.values = set(elements) # pylint: disable=attribute-defined-outside-init
@ -233,6 +240,9 @@ class SwitchableSetting(Setting):
self.enabled = set(data[ENABLED].split(',')) self.enabled = set(data[ENABLED].split(','))
def parse_form(self, items): # pylint: disable=missing-function-docstring def parse_form(self, items): # pylint: disable=missing-function-docstring
if self.locked:
return
items = self.transform_form_items(items) items = self.transform_form_items(items)
self.disabled = set() # pylint: disable=attribute-defined-outside-init self.disabled = set() # pylint: disable=attribute-defined-outside-init
self.enabled = set() # pylint: disable=attribute-defined-outside-init self.enabled = set() # pylint: disable=attribute-defined-outside-init
@ -317,22 +327,28 @@ class Preferences:
self.key_value_settings = { self.key_value_settings = {
'categories': MultipleChoiceSetting( 'categories': MultipleChoiceSetting(
['general'], choices=categories + ['none'] ['general'],
is_locked('categories'),
choices=categories + ['none']
), ),
'language': SearchLanguageSetting( 'language': SearchLanguageSetting(
settings['search'].get('default_lang', ''), settings['search'].get('default_lang', ''),
is_locked('language'),
choices=list(LANGUAGE_CODES) + [''] choices=list(LANGUAGE_CODES) + ['']
), ),
'locale': EnumStringSetting( 'locale': EnumStringSetting(
settings['ui'].get('default_locale', ''), settings['ui'].get('default_locale', ''),
is_locked('locale'),
choices=list(settings['locales'].keys()) + [''] choices=list(settings['locales'].keys()) + ['']
), ),
'autocomplete': EnumStringSetting( 'autocomplete': EnumStringSetting(
settings['search'].get('autocomplete', ''), settings['search'].get('autocomplete', ''),
is_locked('autocomplete'),
choices=list(autocomplete.backends.keys()) + [''] choices=list(autocomplete.backends.keys()) + ['']
), ),
'image_proxy': MapSetting( 'image_proxy': MapSetting(
settings['server'].get('image_proxy', False), settings['server'].get('image_proxy', False),
is_locked('image_proxy'),
map={ map={
'': settings['server'].get('image_proxy', 0), '': settings['server'].get('image_proxy', 0),
'0': False, '0': False,
@ -343,10 +359,12 @@ class Preferences:
), ),
'method': EnumStringSetting( 'method': EnumStringSetting(
settings['server'].get('method', 'POST'), settings['server'].get('method', 'POST'),
is_locked('method'),
choices=('GET', 'POST') choices=('GET', 'POST')
), ),
'safesearch': MapSetting( 'safesearch': MapSetting(
settings['search'].get('safe_search', 0), settings['search'].get('safe_search', 0),
is_locked('safesearch'),
map={ map={
'0': 0, '0': 0,
'1': 1, '1': 1,
@ -355,10 +373,12 @@ class Preferences:
), ),
'theme': EnumStringSetting( 'theme': EnumStringSetting(
settings['ui'].get('default_theme', 'oscar'), settings['ui'].get('default_theme', 'oscar'),
is_locked('theme'),
choices=themes choices=themes
), ),
'results_on_new_tab': MapSetting( 'results_on_new_tab': MapSetting(
settings['ui'].get('results_on_new_tab', False), settings['ui'].get('results_on_new_tab', False),
is_locked('results_on_new_tab'),
map={ map={
'0': False, '0': False,
'1': True, '1': True,
@ -367,10 +387,13 @@ class Preferences:
} }
), ),
'doi_resolver': MultipleChoiceSetting( 'doi_resolver': MultipleChoiceSetting(
['oadoi.org'], choices=DOI_RESOLVERS ['oadoi.org'],
is_locked('doi_resolver'),
choices=DOI_RESOLVERS
), ),
'oscar-style': EnumStringSetting( 'oscar-style': EnumStringSetting(
settings['ui'].get('theme_args', {}).get('oscar_style', 'logicodev'), settings['ui'].get('theme_args', {}).get('oscar_style', 'logicodev'),
is_locked('oscar-style'),
choices=['', 'logicodev', 'logicodev-dark', 'pointhi']), choices=['', 'logicodev', 'logicodev-dark', 'pointhi']),
} }
@ -383,6 +406,8 @@ class Preferences:
"""Return preferences as URL parameters""" """Return preferences as URL parameters"""
settings_kv = {} settings_kv = {}
for k, v in self.key_value_settings.items(): for k, v in self.key_value_settings.items():
if v.locked:
continue
if isinstance(v, MultipleChoiceSetting): if isinstance(v, MultipleChoiceSetting):
settings_kv[k] = ','.join(v.get_value()) settings_kv[k] = ','.join(v.get_value())
else: else:
@ -410,6 +435,8 @@ class Preferences:
"""parse preferences from request (``flask.request.form``)""" """parse preferences from request (``flask.request.form``)"""
for user_setting_name, user_setting in input_data.items(): for user_setting_name, user_setting in input_data.items():
if user_setting_name in self.key_value_settings: if user_setting_name in self.key_value_settings:
if self.key_value_settings[user_setting_name].locked:
continue
self.key_value_settings[user_setting_name].parse(user_setting) self.key_value_settings[user_setting_name].parse(user_setting)
elif user_setting_name == 'disabled_engines': elif user_setting_name == 'disabled_engines':
self.engines.parse_cookie((input_data.get('disabled_engines', ''), self.engines.parse_cookie((input_data.get('disabled_engines', ''),
@ -464,6 +491,8 @@ class Preferences:
"""Save cookie in the HTTP reponse obect """Save cookie in the HTTP reponse obect
""" """
for user_setting_name, user_setting in self.key_value_settings.items(): for user_setting_name, user_setting in self.key_value_settings.items():
if self.key_value_settings[user_setting_name].locked:
continue
user_setting.save(user_setting_name, resp) user_setting.save(user_setting_name, resp)
self.engines.save(resp) self.engines.save(resp)
self.plugins.save(resp) self.plugins.save(resp)
@ -482,3 +511,13 @@ class Preferences:
break break
return valid return valid
def is_locked(setting_name):
"""Checks if a given setting name is locked by settings.yml
"""
if 'preferences' not in settings:
return False
if 'lock' not in settings['preferences']:
return False
return setting_name in settings['preferences']['lock']

View file

@ -33,6 +33,15 @@ ui:
# - it # - it
# - science # - science
# Lock arbitrary settings on the preferences page.
# To find the ID of the user setting you want to lock, check
# the ID of the form on the page "preferences".
#preferences:
# lock:
# - language
# - autocomplete
# - method
# searx supports result proxification using an external service: https://github.com/asciimoo/morty # searx supports result proxification using an external service: https://github.com/asciimoo/morty
# uncomment below section if you have running morty proxy # uncomment below section if you have running morty proxy
# the key is base64 encoded (keep the !!binary notation) # the key is base64 encoded (keep the !!binary notation)

View file

@ -17,6 +17,9 @@ ui:
templates_path : "" templates_path : ""
default_theme : oscar default_theme : oscar
preferences:
lock: []
outgoing: outgoing:
request_timeout : 1.0 # seconds request_timeout : 1.0 # seconds
useragent_suffix : "" useragent_suffix : ""

View file

@ -5,10 +5,13 @@
<h2>{{ _('Preferences') }}</h2> <h2>{{ _('Preferences') }}</h2>
<form method="post" action="{{ url_for('preferences') }}" id="search_form"> <form method="post" action="{{ url_for('preferences') }}" id="search_form">
{% if 'categories' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Default categories') }}</legend> <legend>{{ _('Default categories') }}</legend>
{% include 'courgette/categories.html' %} {% include 'courgette/categories.html' %}
</fieldset> </fieldset>
{% endif %}
{% if 'language' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Search language') }}</legend> <legend>{{ _('Search language') }}</legend>
<p> <p>
@ -20,6 +23,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'locale' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Interface language') }}</legend> <legend>{{ _('Interface language') }}</legend>
<p> <p>
@ -30,6 +35,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'autocomplete' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Autocomplete') }}</legend> <legend>{{ _('Autocomplete') }}</legend>
<p> <p>
@ -41,6 +48,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'image_proxy' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Image proxy') }}</legend> <legend>{{ _('Image proxy') }}</legend>
<p> <p>
@ -50,6 +59,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'method' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Method') }}</legend> <legend>{{ _('Method') }}</legend>
<p> <p>
@ -59,6 +70,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'safesearch' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('SafeSearch') }}</legend> <legend>{{ _('SafeSearch') }}</legend>
<p> <p>
@ -69,6 +82,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'theme' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Themes') }}</legend> <legend>{{ _('Themes') }}</legend>
<p> <p>
@ -92,6 +107,7 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
<fieldset> <fieldset>
<legend>{{ _('Currently used search engines') }}</legend> <legend>{{ _('Currently used search engines') }}</legend>

View file

@ -10,6 +10,7 @@
{% set display_tooltip = false %} {% set display_tooltip = false %}
{% include 'legacy/categories.html' %} {% include 'legacy/categories.html' %}
</fieldset> </fieldset>
{% if 'language' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Search language') }}</legend> <legend>{{ _('Search language') }}</legend>
<p> <p>
@ -21,6 +22,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'locale' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Interface language') }}</legend> <legend>{{ _('Interface language') }}</legend>
<p> <p>
@ -31,6 +34,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'autocomplete' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Autocomplete') }}</legend> <legend>{{ _('Autocomplete') }}</legend>
<p> <p>
@ -42,6 +47,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'image_proxy' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Image proxy') }}</legend> <legend>{{ _('Image proxy') }}</legend>
<p> <p>
@ -51,6 +58,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'method' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Method') }}</legend> <legend>{{ _('Method') }}</legend>
<p> <p>
@ -60,6 +69,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'safesearch' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('SafeSearch') }}</legend> <legend>{{ _('SafeSearch') }}</legend>
<p> <p>
@ -70,6 +81,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'theme' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Themes') }}</legend> <legend>{{ _('Themes') }}</legend>
<p> <p>
@ -80,6 +93,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'results_on_new_tab' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Results on new tabs') }}</legend> <legend>{{ _('Results on new tabs') }}</legend>
<p> <p>
@ -89,6 +104,7 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
<fieldset> <fieldset>
<legend>{{ _('Currently used search engines') }}</legend> <legend>{{ _('Currently used search engines') }}</legend>

View file

@ -25,6 +25,7 @@
<div class="tab-pane active" id="tab_general"> <div class="tab-pane active" id="tab_general">
<fieldset> <fieldset>
<div class="container-fluid"> <div class="container-fluid">
{% if 'categories' not in locked_preferences %}
<div class="row form-group"> <div class="row form-group">
{% if rtl %} {% if rtl %}
<div class="col-sm-11 col-md-10"> <div class="col-sm-11 col-md-10">
@ -38,12 +39,16 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% endif %}
{% if 'language' not in locked_preferences %}
{% set language_label = _('Search language') %} {% set language_label = _('Search language') %}
{% set language_info = _('What language do you prefer for search?') %} {% set language_info = _('What language do you prefer for search?') %}
{{ preferences_item_header(language_info, language_label, rtl, 'language') }} {{ preferences_item_header(language_info, language_label, rtl, 'language') }}
{% include 'oscar/languages.html' %} {% include 'oscar/languages.html' %}
{{ preferences_item_footer(language_info, language_label, rtl) }} {{ preferences_item_footer(language_info, language_label, rtl) }}
{% endif %}
{% if 'locale' not in locked_preferences %}
{% set locale_label = _('Interface language') %} {% set locale_label = _('Interface language') %}
{% set locale_info = _('Change the language of the layout') %} {% set locale_info = _('Change the language of the layout') %}
{{ preferences_item_header(locale_info, locale_label, rtl, 'locale') }} {{ preferences_item_header(locale_info, locale_label, rtl, 'locale') }}
@ -53,7 +58,9 @@
{% endfor %} {% endfor %}
</select> </select>
{{ preferences_item_footer(locale_info, locale_label, rtl) }} {{ preferences_item_footer(locale_info, locale_label, rtl) }}
{% endif %}
{% if 'autocomplete' not in locked_preferences %}
{% set autocomplete_label = _('Autocomplete') %} {% set autocomplete_label = _('Autocomplete') %}
{% set autocomplete_info = _('Find stuff as you type') %} {% set autocomplete_info = _('Find stuff as you type') %}
{{ preferences_item_header(autocomplete_info, autocomplete_label, rtl, 'autocomplete') }} {{ preferences_item_header(autocomplete_info, autocomplete_label, rtl, 'autocomplete') }}
@ -64,7 +71,9 @@
{% endfor %} {% endfor %}
</select> </select>
{{ preferences_item_footer(autocomplete_info, autocomplete_label, rtl) }} {{ preferences_item_footer(autocomplete_info, autocomplete_label, rtl) }}
{% endif %}
{% if 'image_proxy' not in locked_preferences %}
{% set image_proxy_label = _('Image proxy') %} {% set image_proxy_label = _('Image proxy') %}
{% set image_proxy_info = _('Proxying image results through searx') %} {% set image_proxy_info = _('Proxying image results through searx') %}
{{ preferences_item_header(image_proxy_info, image_proxy_label, rtl, 'image_proxy') }} {{ preferences_item_header(image_proxy_info, image_proxy_label, rtl, 'image_proxy') }}
@ -73,7 +82,9 @@
<option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled')}}</option> <option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled')}}</option>
</select> </select>
{{ preferences_item_footer(image_proxy_info, image_proxy_label, rtl) }} {{ preferences_item_footer(image_proxy_info, image_proxy_label, rtl) }}
{% endif %}
{% if 'method' not in locked_preferences %}
{% set method_label = _('Method') %} {% set method_label = _('Method') %}
{% set method_info = _('Change how forms are submited, <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods" rel="external">learn more about request methods</a>') %} {% set method_info = _('Change how forms are submited, <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods" rel="external">learn more about request methods</a>') %}
{{ preferences_item_header(method_info, method_label, rtl, 'method') }} {{ preferences_item_header(method_info, method_label, rtl, 'method') }}
@ -82,7 +93,9 @@
<option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option> <option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option>
</select> </select>
{{ preferences_item_footer(method_info, method_label, rtl) }} {{ preferences_item_footer(method_info, method_label, rtl) }}
{% endif %}
{% if 'safesearch' not in locked_preferences %}
{% set safesearch_label = _('SafeSearch') %} {% set safesearch_label = _('SafeSearch') %}
{% set safesearch_info = _('Filter content') %} {% set safesearch_info = _('Filter content') %}
{{ preferences_item_header(safesearch_info, safesearch_label, rtl, 'safesearch') }} {{ preferences_item_header(safesearch_info, safesearch_label, rtl, 'safesearch') }}
@ -92,7 +105,9 @@
<option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option> <option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option>
</select> </select>
{{ preferences_item_footer(safesearch_info, safesearch_label, rtl) }} {{ preferences_item_footer(safesearch_info, safesearch_label, rtl) }}
{% endif %}
{% if 'theme' not in locked_preferences %}
{% set theme_label = _('Themes') %} {% set theme_label = _('Themes') %}
{% set theme_info = _('Change searx layout') %} {% set theme_info = _('Change searx layout') %}
{{ preferences_item_header(theme_info, theme_label, rtl, 'theme') }} {{ preferences_item_header(theme_info, theme_label, rtl, 'theme') }}
@ -102,7 +117,9 @@
{% endfor %} {% endfor %}
</select> </select>
{{ preferences_item_footer(theme_info, theme_label, rtl) }} {{ preferences_item_footer(theme_info, theme_label, rtl) }}
{% endif %}
{% if 'oscar-style' not in locked_preferences %}
{{ preferences_item_header(_('Choose style for this theme'), _('Style'), rtl, 'oscar_style') }} {{ preferences_item_header(_('Choose style for this theme'), _('Style'), rtl, 'oscar_style') }}
<select class="form-control {{ custom_select_class(rtl) }}" name="oscar-style" id="oscar_style"> <select class="form-control {{ custom_select_class(rtl) }}" name="oscar-style" id="oscar_style">
<option value="logicodev" >Logicodev</option> <option value="logicodev" >Logicodev</option>
@ -110,7 +127,9 @@
<option value="logicodev-dark" {% if preferences.get_value('oscar-style') == 'logicodev-dark' %}selected="selected"{% endif %}>Logicodev dark</option> <option value="logicodev-dark" {% if preferences.get_value('oscar-style') == 'logicodev-dark' %}selected="selected"{% endif %}>Logicodev dark</option>
</select> </select>
{{ preferences_item_footer(_('Choose style for this theme'), _('Style'), rtl) }} {{ preferences_item_footer(_('Choose style for this theme'), _('Style'), rtl) }}
{% endif %}
{% if 'results_on_new_tab' not in locked_preferences %}
{% set label = _('Results on new tabs') %} {% set label = _('Results on new tabs') %}
{% set info = _('Open result links on new browser tabs') %} {% set info = _('Open result links on new browser tabs') %}
{{ preferences_item_header(info, label, rtl, 'results_on_new_tab') }} {{ preferences_item_header(info, label, rtl, 'results_on_new_tab') }}
@ -119,7 +138,9 @@
<option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option> <option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option>
</select> </select>
{{ preferences_item_footer(info, label, rtl) }} {{ preferences_item_footer(info, label, rtl) }}
{% endif %}
{% if 'doi_resolver' not in locked_preferences %}
{% set label = _('Open Access DOI resolver') %} {% set label = _('Open Access DOI resolver') %}
{% set info = _('Redirect to open-access versions of publications when available (plugin required)') %} {% set info = _('Redirect to open-access versions of publications when available (plugin required)') %}
{{ preferences_item_header(info, label, rtl, 'doi_resolver') }} {{ preferences_item_header(info, label, rtl, 'doi_resolver') }}
@ -131,6 +152,7 @@
{% endfor %} {% endfor %}
</select> </select>
{{ preferences_item_footer(info, label, rtl) }} {{ preferences_item_footer(info, label, rtl) }}
{% endif %}
{% set label = _('Engine tokens') %} {% set label = _('Engine tokens') %}
{% set info = _('Access tokens for private engines') %} {% set info = _('Access tokens for private engines') %}

View file

@ -5,6 +5,7 @@
<h2>{{ _('Preferences') }}</h2> <h2>{{ _('Preferences') }}</h2>
<form method="post" action="{{ url_for('preferences') }}" id="search_form"> <form method="post" action="{{ url_for('preferences') }}" id="search_form">
{% if 'language' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Search language') }}</legend> <legend>{{ _('Search language') }}</legend>
<p> <p>
@ -16,6 +17,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'locale' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Interface language') }}</legend> <legend>{{ _('Interface language') }}</legend>
<p> <p>
@ -26,6 +29,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'method' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Method') }}</legend> <legend>{{ _('Method') }}</legend>
<p> <p>
@ -35,6 +40,8 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
{% if 'theme' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Themes') }}</legend> <legend>{{ _('Themes') }}</legend>
<p> <p>
@ -45,6 +52,7 @@
</select> </select>
</p> </p>
</fieldset> </fieldset>
{% endif %}
<fieldset> <fieldset>
<legend>{{ _('Currently used search engines') }}</legend> <legend>{{ _('Currently used search engines') }}</legend>

View file

@ -30,11 +30,14 @@
{{ tabs_open() }} {{ tabs_open() }}
{{ tab_header('maintab', 'general', _('General')) }} {{ tab_header('maintab', 'general', _('General')) }}
{% if 'categories' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Default categories') }}</legend> <legend>{{ _('Default categories') }}</legend>
{% set display_tooltip = false %} {% set display_tooltip = false %}
{% include 'simple/categories.html' %} {% include 'simple/categories.html' %}
</fieldset> </fieldset>
{% endif %}
{% if 'language' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Search language') }}</legend> <legend>{{ _('Search language') }}</legend>
<p class="value">{{- '' -}} <p class="value">{{- '' -}}
@ -47,6 +50,8 @@
</p> </p>
<div class="description">{{ _('What language do you prefer for search?') }}</div> <div class="description">{{ _('What language do you prefer for search?') }}</div>
</fieldset> </fieldset>
{% endif %}
{% if 'autocomplete' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Autocomplete') }}</legend> <legend>{{ _('Autocomplete') }}</legend>
<p class="value"> <p class="value">
@ -59,6 +64,8 @@
</p> </p>
<div class="description">{{ _('Find stuff as you type') }}</div> <div class="description">{{ _('Find stuff as you type') }}</div>
</fieldset> </fieldset>
{% endif %}
{% if 'safesearch' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('SafeSearch') }}</legend> <legend>{{ _('SafeSearch') }}</legend>
<p class="value"> <p class="value">
@ -70,7 +77,9 @@
</p> </p>
<p class="description">{{ _('Filter content') }}</p> <p class="description">{{ _('Filter content') }}</p>
</fieldset> </fieldset>
{% endif %}
{{ plugin_preferences('general') }} {{ plugin_preferences('general') }}
{% if 'doi_resolver' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Open Access DOI resolver') }}</legend> <legend>{{ _('Open Access DOI resolver') }}</legend>
<p class="value"> <p class="value">
@ -84,6 +93,7 @@
</p> </p>
<div class="description"><!-- {{ _('Redirect to open-access versions of publications when available (plugin required)') }} --></div> <div class="description"><!-- {{ _('Redirect to open-access versions of publications when available (plugin required)') }} --></div>
</fieldset> </fieldset>
{% endif %}
{{ tab_footer() }} {{ tab_footer() }}
{{ tab_header('maintab', 'engines', _('Engines')) }} {{ tab_header('maintab', 'engines', _('Engines')) }}
@ -129,6 +139,7 @@
{{ tab_footer() }} {{ tab_footer() }}
{{ tab_header('maintab', 'ui', _('User interface')) }} {{ tab_header('maintab', 'ui', _('User interface')) }}
{% if 'locale' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Interface language') }}</legend> <legend>{{ _('Interface language') }}</legend>
<p class="value"> <p class="value">
@ -140,6 +151,8 @@
</p> </p>
<div class="description">{{ _('Change the language of the layout') }}</div> <div class="description">{{ _('Change the language of the layout') }}</div>
</fieldset> </fieldset>
{% endif %}
{% if 'theme' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Themes') }}</legend> <legend>{{ _('Themes') }}</legend>
<p class="value"> <p class="value">
@ -151,6 +164,8 @@
</p> </p>
<div class="description">{{ _('Change searx layout') }}</div> <div class="description">{{ _('Change searx layout') }}</div>
</fieldset> </fieldset>
{% endif %}
{% if 'results_on_new_tab' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Results on new tabs') }}</legend> <legend>{{ _('Results on new tabs') }}</legend>
<p class="value"> <p class="value">
@ -161,6 +176,7 @@
</p> </p>
<div class="description">{{_('Open result links on new browser tabs') }}</div> <div class="description">{{_('Open result links on new browser tabs') }}</div>
</fieldset> </fieldset>
{% endif %}
{{ plugin_preferences('ui') }} {{ plugin_preferences('ui') }}
{{ tab_footer() }} {{ tab_footer() }}
@ -197,6 +213,7 @@
{{ tab_footer() }} {{ tab_footer() }}
{{ tab_header('maintab', 'privacy', _('Privacy')) }} {{ tab_header('maintab', 'privacy', _('Privacy')) }}
{% if 'method' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Method') }}</legend> <legend>{{ _('Method') }}</legend>
<p class="value"> <p class="value">
@ -207,6 +224,8 @@
</p> </p>
<div class="description">{{ _('Search language') }}</div> <div class="description">{{ _('Search language') }}</div>
</fieldset> </fieldset>
{% endif %}
{% if 'image_proxy' not in locked_preferences %}
<fieldset> <fieldset>
<legend>{{ _('Image proxy') }}</legend> <legend>{{ _('Image proxy') }}</legend>
<p class="value"> <p class="value">
@ -217,6 +236,7 @@
</p> </p>
<div class="description">{{ _('Proxying image results through searx') }}</div> <div class="description">{{ _('Proxying image results through searx') }}</div>
</fieldset> </fieldset>
{% endif %}
{{ plugin_preferences('privacy') }} {{ plugin_preferences('privacy') }}
{{ tab_footer() }} {{ tab_footer() }}

View file

@ -4,7 +4,7 @@ from searx.webutils import VALID_LANGUAGE_CODE
from searx.query import RawTextQuery from searx.query import RawTextQuery
from searx.engines import categories, engines from searx.engines import categories, engines
from searx.search import SearchQuery, EngineRef from searx.search import SearchQuery, EngineRef
from searx.preferences import Preferences from searx.preferences import Preferences, is_locked
# remove duplicate queries. # remove duplicate queries.
@ -48,6 +48,8 @@ def parse_pageno(form: Dict[str, str]) -> int:
def parse_lang(preferences: Preferences, form: Dict[str, str], raw_text_query: RawTextQuery) -> str: def parse_lang(preferences: Preferences, form: Dict[str, str], raw_text_query: RawTextQuery) -> str:
if is_locked('language'):
return preferences.get_value('langueage')
# get language # get language
# set specific language if set on request, query or preferences # set specific language if set on request, query or preferences
# TODO support search with multible languages # TODO support search with multible languages
@ -66,6 +68,9 @@ def parse_lang(preferences: Preferences, form: Dict[str, str], raw_text_query: R
def parse_safesearch(preferences: Preferences, form: Dict[str, str]) -> int: def parse_safesearch(preferences: Preferences, form: Dict[str, str]) -> int:
if is_locked('safesearch'):
return preferences.get_value('safesearch')
if 'safesearch' in form: if 'safesearch' in form:
query_safesearch = form.get('safesearch') query_safesearch = form.get('safesearch')
# first check safesearch # first check safesearch
@ -117,6 +122,9 @@ def parse_specific(raw_text_query: RawTextQuery) -> Tuple[List[EngineRef], List[
def parse_category_form(query_categories: List[str], name: str, value: str) -> None: def parse_category_form(query_categories: List[str], name: str, value: str) -> None:
if is_locked('categories'):
return preferences.get_value('categories')
if name == 'categories': if name == 'categories':
query_categories.extend(categ for categ in map(str.strip, value.split(',')) if categ in categories) query_categories.extend(categ for categ in map(str.strip, value.split(',')) if categ in categories)
elif name.startswith('category_'): elif name.startswith('category_'):

View file

@ -828,6 +828,10 @@ def preferences():
stats[engine_stat.get('name')]['warn_time'] = True stats[engine_stat.get('name')]['warn_time'] = True
# end of stats # end of stats
locked_preferences = list()
if 'preferences' in settings and 'lock' in settings['preferences']:
locked_preferences = settings['preferences']['lock']
return render('preferences.html', return render('preferences.html',
selected_categories=get_selected_categories(request.preferences, request.form), selected_categories=get_selected_categories(request.preferences, request.form),
all_categories=_get_ordered_categories(), all_categories=_get_ordered_categories(),
@ -848,6 +852,7 @@ def preferences():
theme=get_current_theme_name(), theme=get_current_theme_name(),
preferences_url_params=request.preferences.get_as_url_params(), preferences_url_params=request.preferences.get_as_url_params(),
base_url=get_base_url(), base_url=get_base_url(),
locked_preferences=locked_preferences,
preferences=True) preferences=True)

View file

@ -141,4 +141,4 @@ class TestPreferences(SearxTestCase):
pref.parse_encoded_data(url_params) pref.parse_encoded_data(url_params)
self.assertEqual( self.assertEqual(
vars(pref.key_value_settings['categories']), vars(pref.key_value_settings['categories']),
{'value': ['general'], 'choices': ['general', 'none']}) {'value': ['general'], 'locked': False, 'choices': ['general', 'none']})