on master help sign in
Let admins lock user preferences
33e139cNoémi Ványi
searx/preferences.py+42−3
@@ -35,9 +35,10 @@ class ValidationException(Exception):
35class Setting:
35class Setting:
36 """Base class of user settings"""
36 """Base class of user settings"""
37
37
38− def __init__(self, default_value, **kwargs):
38+ def __init__(self, default_value, locked=False, **kwargs):
39 super().__init__()
39 super().__init__()
40 self.value = default_value
40 self.value = default_value
41+ self.locked = locked
41 for key, value in kwargs.items():
42 for key, value in kwargs.items():
42 setattr(self, key, value)
43 setattr(self, key, value)
43
44
@@ -115,6 +116,9 @@ class MultipleChoiceSetting(EnumStringSetting):
115 self.value = elements
116 self.value = elements
116
117
117 def parse_form(self, data): # pylint: disable=missing-function-docstring
118 def parse_form(self, data): # pylint: disable=missing-function-docstring
119+ if self.locked:
120+ return
121+
118 self.value = []
122 self.value = []
119 for choice in data:
123 for choice in data:
120 if choice in self.choices and choice not in self.value: # pylint: disable=no-member
124 if choice in self.choices and choice not in self.value: # pylint: disable=no-member
@@ -149,6 +153,9 @@ class SetSetting(Setting):
149 self.values.add(element)
153 self.values.add(element)
150
154
151 def parse_form(self, data): # pylint: disable=missing-function-docstring
155 def parse_form(self, data): # pylint: disable=missing-function-docstring
156+ if self.locked:
157+ return
158+
152 elements = data.split(',')
159 elements = data.split(',')
153 self.values = set(elements) # pylint: disable=attribute-defined-outside-init
160 self.values = set(elements) # pylint: disable=attribute-defined-outside-init
154
161
@@ -233,6 +240,9 @@ class SwitchableSetting(Setting):
233 self.enabled = set(data[ENABLED].split(','))
240 self.enabled = set(data[ENABLED].split(','))
234
241
235 def parse_form(self, items): # pylint: disable=missing-function-docstring
242 def parse_form(self, items): # pylint: disable=missing-function-docstring
243+ if self.locked:
244+ return
245+
236 items = self.transform_form_items(items)
246 items = self.transform_form_items(items)
237 self.disabled = set() # pylint: disable=attribute-defined-outside-init
247 self.disabled = set() # pylint: disable=attribute-defined-outside-init
238 self.enabled = set() # pylint: disable=attribute-defined-outside-init
248 self.enabled = set() # pylint: disable=attribute-defined-outside-init
@@ -317,22 +327,28 @@ class Preferences:
317
327
318 self.key_value_settings = {
328 self.key_value_settings = {
319 'categories': MultipleChoiceSetting(
329 'categories': MultipleChoiceSetting(
330+ ['general'],
331+ is_locked('categories'),
320− ['general'], choices=categories + ['none']
332+ choices=categories + ['none']
321 ),
333 ),
322 'language': SearchLanguageSetting(
334 'language': SearchLanguageSetting(
323 settings['search'].get('default_lang', ''),
335 settings['search'].get('default_lang', ''),
336+ is_locked('language'),
324 choices=list(LANGUAGE_CODES) + ['']
337 choices=list(LANGUAGE_CODES) + ['']
325 ),
338 ),
326 'locale': EnumStringSetting(
339 'locale': EnumStringSetting(
327 settings['ui'].get('default_locale', ''),
340 settings['ui'].get('default_locale', ''),
341+ is_locked('locale'),
328 choices=list(settings['locales'].keys()) + ['']
342 choices=list(settings['locales'].keys()) + ['']
329 ),
343 ),
330 'autocomplete': EnumStringSetting(
344 'autocomplete': EnumStringSetting(
331 settings['search'].get('autocomplete', ''),
345 settings['search'].get('autocomplete', ''),
346+ is_locked('autocomplete'),
332 choices=list(autocomplete.backends.keys()) + ['']
347 choices=list(autocomplete.backends.keys()) + ['']
333 ),
348 ),
334 'image_proxy': MapSetting(
349 'image_proxy': MapSetting(
335 settings['server'].get('image_proxy', False),
350 settings['server'].get('image_proxy', False),
351+ is_locked('image_proxy'),
336 map={
352 map={
337 '': settings['server'].get('image_proxy', 0),
353 '': settings['server'].get('image_proxy', 0),
338 '0': False,
354 '0': False,
@@ -343,10 +359,12 @@ class Preferences:
343 ),
359 ),
344 'method': EnumStringSetting(
360 'method': EnumStringSetting(
345 settings['server'].get('method', 'POST'),
361 settings['server'].get('method', 'POST'),
362+ is_locked('method'),
346 choices=('GET', 'POST')
363 choices=('GET', 'POST')
347 ),
364 ),
348 'safesearch': MapSetting(
365 'safesearch': MapSetting(
349 settings['search'].get('safe_search', 0),
366 settings['search'].get('safe_search', 0),
367+ is_locked('safesearch'),
350 map={
368 map={
351 '0': 0,
369 '0': 0,
352 '1': 1,
370 '1': 1,
@@ -355,10 +373,12 @@ class Preferences:
355 ),
373 ),
356 'theme': EnumStringSetting(
374 'theme': EnumStringSetting(
357 settings['ui'].get('default_theme', 'oscar'),
375 settings['ui'].get('default_theme', 'oscar'),
376+ is_locked('theme'),
358 choices=themes
377 choices=themes
359 ),
378 ),
360 'results_on_new_tab': MapSetting(
379 'results_on_new_tab': MapSetting(
361 settings['ui'].get('results_on_new_tab', False),
380 settings['ui'].get('results_on_new_tab', False),
381+ is_locked('results_on_new_tab'),
362 map={
382 map={
363 '0': False,
383 '0': False,
364 '1': True,
384 '1': True,
@@ -367,10 +387,13 @@ class Preferences:
367 }
387 }
368 ),
388 ),
369 'doi_resolver': MultipleChoiceSetting(
389 'doi_resolver': MultipleChoiceSetting(
390+ ['oadoi.org'],
391+ is_locked('doi_resolver'),
370− ['oadoi.org'], choices=DOI_RESOLVERS
392+ choices=DOI_RESOLVERS
371 ),
393 ),
372 'oscar-style': EnumStringSetting(
394 'oscar-style': EnumStringSetting(
373 settings['ui'].get('theme_args', {}).get('oscar_style', 'logicodev'),
395 settings['ui'].get('theme_args', {}).get('oscar_style', 'logicodev'),
396+ is_locked('oscar-style'),
374 choices=['', 'logicodev', 'logicodev-dark', 'pointhi']),
397 choices=['', 'logicodev', 'logicodev-dark', 'pointhi']),
375 }
398 }
376
399
@@ -383,6 +406,8 @@ class Preferences:
383 """Return preferences as URL parameters"""
406 """Return preferences as URL parameters"""
384 settings_kv = {}
407 settings_kv = {}
385 for k, v in self.key_value_settings.items():
408 for k, v in self.key_value_settings.items():
409+ if v.locked:
410+ continue
386 if isinstance(v, MultipleChoiceSetting):
411 if isinstance(v, MultipleChoiceSetting):
387 settings_kv[k] = ','.join(v.get_value())
412 settings_kv[k] = ','.join(v.get_value())
388 else:
413 else:
@@ -410,6 +435,8 @@ class Preferences:
410 """parse preferences from request (``flask.request.form``)"""
435 """parse preferences from request (``flask.request.form``)"""
411 for user_setting_name, user_setting in input_data.items():
436 for user_setting_name, user_setting in input_data.items():
412 if user_setting_name in self.key_value_settings:
437 if user_setting_name in self.key_value_settings:
438+ if self.key_value_settings[user_setting_name].locked:
439+ continue
413 self.key_value_settings[user_setting_name].parse(user_setting)
440 self.key_value_settings[user_setting_name].parse(user_setting)
414 elif user_setting_name == 'disabled_engines':
441 elif user_setting_name == 'disabled_engines':
415 self.engines.parse_cookie((input_data.get('disabled_engines', ''),
442 self.engines.parse_cookie((input_data.get('disabled_engines', ''),
@@ -464,6 +491,8 @@ class Preferences:
464 """Save cookie in the HTTP reponse obect
491 """Save cookie in the HTTP reponse obect
465 """
492 """
466 for user_setting_name, user_setting in self.key_value_settings.items():
493 for user_setting_name, user_setting in self.key_value_settings.items():
494+ if self.key_value_settings[user_setting_name].locked:
495+ continue
467 user_setting.save(user_setting_name, resp)
496 user_setting.save(user_setting_name, resp)
468 self.engines.save(resp)
497 self.engines.save(resp)
469 self.plugins.save(resp)
498 self.plugins.save(resp)
@@ -482,3 +511,13 @@ class Preferences:
482 break
511 break
483
512
484 return valid
513 return valid
514+
515+
516+def is_locked(setting_name):
517+ """Checks if a given setting name is locked by settings.yml
518+ """
519+ if 'preferences' not in settings:
520+ return False
521+ if 'lock' not in settings['preferences']:
522+ return False
523+ return setting_name in settings['preferences']['lock']
searx/settings.yml+9
@@ -33,6 +33,15 @@ ui:
33# - it
33# - it
34# - science
34# - science
35
35
36+# Lock arbitrary settings on the preferences page.
37+# To find the ID of the user setting you want to lock, check
38+# the ID of the form on the page "preferences".
39+#preferences:
40+# lock:
41+# - language
42+# - autocomplete
43+# - method
44+
36# searx supports result proxification using an external service: https://github.com/asciimoo/morty
45# searx supports result proxification using an external service: https://github.com/asciimoo/morty
37# uncomment below section if you have running morty proxy
46# uncomment below section if you have running morty proxy
38# the key is base64 encoded (keep the !!binary notation)
47# the key is base64 encoded (keep the !!binary notation)
searx/settings_robot.yml+3
@@ -17,6 +17,9 @@ ui:
17 templates_path : ""
17 templates_path : ""
18 default_theme : oscar
18 default_theme : oscar
19
19
20+preferences:
21+ lock: []
22+
20outgoing:
23outgoing:
21 request_timeout : 1.0 # seconds
24 request_timeout : 1.0 # seconds
22 useragent_suffix : ""
25 useragent_suffix : ""
searx/templates/courgette/preferences.html+16
@@ -5,10 +5,13 @@
5 <h2>{{ _('Preferences') }}</h2>
5 <h2>{{ _('Preferences') }}</h2>
6
6
7 <form method="post" action="{{ url_for('preferences') }}" id="search_form">
7 <form method="post" action="{{ url_for('preferences') }}" id="search_form">
8+ {% if 'categories' not in locked_preferences %}
8 <fieldset>
9 <fieldset>
9 <legend>{{ _('Default categories') }}</legend>
10 <legend>{{ _('Default categories') }}</legend>
10 {% include 'courgette/categories.html' %}
11 {% include 'courgette/categories.html' %}
11 </fieldset>
12 </fieldset>
13+ {% endif %}
14+ {% if 'language' not in locked_preferences %}
12 <fieldset>
15 <fieldset>
13 <legend>{{ _('Search language') }}</legend>
16 <legend>{{ _('Search language') }}</legend>
14 <p>
17 <p>
@@ -20,6 +23,8 @@
20 </select>
23 </select>
21 </p>
24 </p>
22 </fieldset>
25 </fieldset>
26+ {% endif %}
27+ {% if 'locale' not in locked_preferences %}
23 <fieldset>
28 <fieldset>
24 <legend>{{ _('Interface language') }}</legend>
29 <legend>{{ _('Interface language') }}</legend>
25 <p>
30 <p>
@@ -30,6 +35,8 @@
30 </select>
35 </select>
31 </p>
36 </p>
32 </fieldset>
37 </fieldset>
38+ {% endif %}
39+ {% if 'autocomplete' not in locked_preferences %}
33 <fieldset>
40 <fieldset>
34 <legend>{{ _('Autocomplete') }}</legend>
41 <legend>{{ _('Autocomplete') }}</legend>
35 <p>
42 <p>
@@ -41,6 +48,8 @@
41 </select>
48 </select>
42 </p>
49 </p>
43 </fieldset>
50 </fieldset>
51+ {% endif %}
52+ {% if 'image_proxy' not in locked_preferences %}
44 <fieldset>
53 <fieldset>
45 <legend>{{ _('Image proxy') }}</legend>
54 <legend>{{ _('Image proxy') }}</legend>
46 <p>
55 <p>
@@ -50,6 +59,8 @@
50 </select>
59 </select>
51 </p>
60 </p>
52 </fieldset>
61 </fieldset>
62+ {% endif %}
63+ {% if 'method' not in locked_preferences %}
53 <fieldset>
64 <fieldset>
54 <legend>{{ _('Method') }}</legend>
65 <legend>{{ _('Method') }}</legend>
55 <p>
66 <p>
@@ -59,6 +70,8 @@
59 </select>
70 </select>
60 </p>
71 </p>
61 </fieldset>
72 </fieldset>
73+ {% endif %}
74+ {% if 'safesearch' not in locked_preferences %}
62 <fieldset>
75 <fieldset>
63 <legend>{{ _('SafeSearch') }}</legend>
76 <legend>{{ _('SafeSearch') }}</legend>
64 <p>
77 <p>
@@ -69,6 +82,8 @@
69 </select>
82 </select>
70 </p>
83 </p>
71 </fieldset>
84 </fieldset>
85+ {% endif %}
86+ {% if 'theme' not in locked_preferences %}
72 <fieldset>
87 <fieldset>
73 <legend>{{ _('Themes') }}</legend>
88 <legend>{{ _('Themes') }}</legend>
74 <p>
89 <p>
@@ -92,6 +107,7 @@
92 </select>
107 </select>
93 </p>
108 </p>
94 </fieldset>
109 </fieldset>
110+ {% endif %}
95 <fieldset>
111 <fieldset>
96 <legend>{{ _('Currently used search engines') }}</legend>
112 <legend>{{ _('Currently used search engines') }}</legend>
97
113
searx/templates/legacy/preferences.html+16
@@ -10,6 +10,7 @@
10 {% set display_tooltip = false %}
10 {% set display_tooltip = false %}
11 {% include 'legacy/categories.html' %}
11 {% include 'legacy/categories.html' %}
12 </fieldset>
12 </fieldset>
13+ {% if 'language' not in locked_preferences %}
13 <fieldset>
14 <fieldset>
14 <legend>{{ _('Search language') }}</legend>
15 <legend>{{ _('Search language') }}</legend>
15 <p>
16 <p>
@@ -21,6 +22,8 @@
21 </select>
22 </select>
22 </p>
23 </p>
23 </fieldset>
24 </fieldset>
25+ {% endif %}
26+ {% if 'locale' not in locked_preferences %}
24 <fieldset>
27 <fieldset>
25 <legend>{{ _('Interface language') }}</legend>
28 <legend>{{ _('Interface language') }}</legend>
26 <p>
29 <p>
@@ -31,6 +34,8 @@
31 </select>
34 </select>
32 </p>
35 </p>
33 </fieldset>
36 </fieldset>
37+ {% endif %}
38+ {% if 'autocomplete' not in locked_preferences %}
34 <fieldset>
39 <fieldset>
35 <legend>{{ _('Autocomplete') }}</legend>
40 <legend>{{ _('Autocomplete') }}</legend>
36 <p>
41 <p>
@@ -42,6 +47,8 @@
42 </select>
47 </select>
43 </p>
48 </p>
44 </fieldset>
49 </fieldset>
50+ {% endif %}
51+ {% if 'image_proxy' not in locked_preferences %}
45 <fieldset>
52 <fieldset>
46 <legend>{{ _('Image proxy') }}</legend>
53 <legend>{{ _('Image proxy') }}</legend>
47 <p>
54 <p>
@@ -51,6 +58,8 @@
51 </select>
58 </select>
52 </p>
59 </p>
53 </fieldset>
60 </fieldset>
61+ {% endif %}
62+ {% if 'method' not in locked_preferences %}
54 <fieldset>
63 <fieldset>
55 <legend>{{ _('Method') }}</legend>
64 <legend>{{ _('Method') }}</legend>
56 <p>
65 <p>
@@ -60,6 +69,8 @@
60 </select>
69 </select>
61 </p>
70 </p>
62 </fieldset>
71 </fieldset>
72+ {% endif %}
73+ {% if 'safesearch' not in locked_preferences %}
63 <fieldset>
74 <fieldset>
64 <legend>{{ _('SafeSearch') }}</legend>
75 <legend>{{ _('SafeSearch') }}</legend>
65 <p>
76 <p>
@@ -70,6 +81,8 @@
70 </select>
81 </select>
71 </p>
82 </p>
72 </fieldset>
83 </fieldset>
84+ {% endif %}
85+ {% if 'theme' not in locked_preferences %}
73 <fieldset>
86 <fieldset>
74 <legend>{{ _('Themes') }}</legend>
87 <legend>{{ _('Themes') }}</legend>
75 <p>
88 <p>
@@ -80,6 +93,8 @@
80 </select>
93 </select>
81 </p>
94 </p>
82 </fieldset>
95 </fieldset>
96+ {% endif %}
97+ {% if 'results_on_new_tab' not in locked_preferences %}
83 <fieldset>
98 <fieldset>
84 <legend>{{ _('Results on new tabs') }}</legend>
99 <legend>{{ _('Results on new tabs') }}</legend>
85 <p>
100 <p>
@@ -89,6 +104,7 @@
89 </select>
104 </select>
90 </p>
105 </p>
91 </fieldset>
106 </fieldset>
107+ {% endif %}
92 <fieldset>
108 <fieldset>
93 <legend>{{ _('Currently used search engines') }}</legend>
109 <legend>{{ _('Currently used search engines') }}</legend>
94
110
searx/templates/oscar/preferences.html+22
@@ -25,6 +25,7 @@
25 <div class="tab-pane active" id="tab_general">
25 <div class="tab-pane active" id="tab_general">
26 <fieldset>
26 <fieldset>
27 <div class="container-fluid">
27 <div class="container-fluid">
28+ {% if 'categories' not in locked_preferences %}
28 <div class="row form-group">
29 <div class="row form-group">
29 {% if rtl %}
30 {% if rtl %}
30 <div class="col-sm-11 col-md-10">
31 <div class="col-sm-11 col-md-10">
@@ -38,12 +39,16 @@
38 </div>
39 </div>
39 {% endif %}
40 {% endif %}
40 </div>
41 </div>
42+ {% endif %}
43+ {% if 'language' not in locked_preferences %}
41 {% set language_label = _('Search language') %}
44 {% set language_label = _('Search language') %}
42 {% set language_info = _('What language do you prefer for search?') %}
45 {% set language_info = _('What language do you prefer for search?') %}
43 {{ preferences_item_header(language_info, language_label, rtl, 'language') }}
46 {{ preferences_item_header(language_info, language_label, rtl, 'language') }}
44 {% include 'oscar/languages.html' %}
47 {% include 'oscar/languages.html' %}
45 {{ preferences_item_footer(language_info, language_label, rtl) }}
48 {{ preferences_item_footer(language_info, language_label, rtl) }}
49+ {% endif %}
46
50
51+ {% if 'locale' not in locked_preferences %}
47 {% set locale_label = _('Interface language') %}
52 {% set locale_label = _('Interface language') %}
48 {% set locale_info = _('Change the language of the layout') %}
53 {% set locale_info = _('Change the language of the layout') %}
49 {{ preferences_item_header(locale_info, locale_label, rtl, 'locale') }}
54 {{ preferences_item_header(locale_info, locale_label, rtl, 'locale') }}
@@ -53,7 +58,9 @@
53 {% endfor %}
58 {% endfor %}
54 </select>
59 </select>
55 {{ preferences_item_footer(locale_info, locale_label, rtl) }}
60 {{ preferences_item_footer(locale_info, locale_label, rtl) }}
61+ {% endif %}
56
62
63+ {% if 'autocomplete' not in locked_preferences %}
57 {% set autocomplete_label = _('Autocomplete') %}
64 {% set autocomplete_label = _('Autocomplete') %}
58 {% set autocomplete_info = _('Find stuff as you type') %}
65 {% set autocomplete_info = _('Find stuff as you type') %}
59 {{ preferences_item_header(autocomplete_info, autocomplete_label, rtl, 'autocomplete') }}
66 {{ preferences_item_header(autocomplete_info, autocomplete_label, rtl, 'autocomplete') }}
@@ -64,7 +71,9 @@
64 {% endfor %}
71 {% endfor %}
65 </select>
72 </select>
66 {{ preferences_item_footer(autocomplete_info, autocomplete_label, rtl) }}
73 {{ preferences_item_footer(autocomplete_info, autocomplete_label, rtl) }}
74+ {% endif %}
67
75
76+ {% if 'image_proxy' not in locked_preferences %}
68 {% set image_proxy_label = _('Image proxy') %}
77 {% set image_proxy_label = _('Image proxy') %}
69 {% set image_proxy_info = _('Proxying image results through searx') %}
78 {% set image_proxy_info = _('Proxying image results through searx') %}
70 {{ preferences_item_header(image_proxy_info, image_proxy_label, rtl, 'image_proxy') }}
79 {{ preferences_item_header(image_proxy_info, image_proxy_label, rtl, 'image_proxy') }}
@@ -73,7 +82,9 @@
73 <option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled')}}</option>
82 <option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled')}}</option>
74 </select>
83 </select>
75 {{ preferences_item_footer(image_proxy_info, image_proxy_label, rtl) }}
84 {{ preferences_item_footer(image_proxy_info, image_proxy_label, rtl) }}
85+ {% endif %}
76
86
87+ {% if 'method' not in locked_preferences %}
77 {% set method_label = _('Method') %}
88 {% set method_label = _('Method') %}
78 {% 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>') %}
89 {% 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>') %}
79 {{ preferences_item_header(method_info, method_label, rtl, 'method') }}
90 {{ preferences_item_header(method_info, method_label, rtl, 'method') }}
@@ -82,7 +93,9 @@
82 <option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option>
93 <option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option>
83 </select>
94 </select>
84 {{ preferences_item_footer(method_info, method_label, rtl) }}
95 {{ preferences_item_footer(method_info, method_label, rtl) }}
96+ {% endif %}
85
97
98+ {% if 'safesearch' not in locked_preferences %}
86 {% set safesearch_label = _('SafeSearch') %}
99 {% set safesearch_label = _('SafeSearch') %}
87 {% set safesearch_info = _('Filter content') %}
100 {% set safesearch_info = _('Filter content') %}
88 {{ preferences_item_header(safesearch_info, safesearch_label, rtl, 'safesearch') }}
101 {{ preferences_item_header(safesearch_info, safesearch_label, rtl, 'safesearch') }}
@@ -92,7 +105,9 @@
92 <option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option>
105 <option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option>
93 </select>
106 </select>
94 {{ preferences_item_footer(safesearch_info, safesearch_label, rtl) }}
107 {{ preferences_item_footer(safesearch_info, safesearch_label, rtl) }}
108+ {% endif %}
95
109
110+ {% if 'theme' not in locked_preferences %}
96 {% set theme_label = _('Themes') %}
111 {% set theme_label = _('Themes') %}
97 {% set theme_info = _('Change searx layout') %}
112 {% set theme_info = _('Change searx layout') %}
98 {{ preferences_item_header(theme_info, theme_label, rtl, 'theme') }}
113 {{ preferences_item_header(theme_info, theme_label, rtl, 'theme') }}
@@ -102,7 +117,9 @@
102 {% endfor %}
117 {% endfor %}
103 </select>
118 </select>
104 {{ preferences_item_footer(theme_info, theme_label, rtl) }}
119 {{ preferences_item_footer(theme_info, theme_label, rtl) }}
120+ {% endif %}
105
121
122+ {% if 'oscar-style' not in locked_preferences %}
106 {{ preferences_item_header(_('Choose style for this theme'), _('Style'), rtl, 'oscar_style') }}
123 {{ preferences_item_header(_('Choose style for this theme'), _('Style'), rtl, 'oscar_style') }}
107 <select class="form-control {{ custom_select_class(rtl) }}" name="oscar-style" id="oscar_style">
124 <select class="form-control {{ custom_select_class(rtl) }}" name="oscar-style" id="oscar_style">
108 <option value="logicodev" >Logicodev</option>
125 <option value="logicodev" >Logicodev</option>
@@ -110,7 +127,9 @@
110 <option value="logicodev-dark" {% if preferences.get_value('oscar-style') == 'logicodev-dark' %}selected="selected"{% endif %}>Logicodev dark</option>
127 <option value="logicodev-dark" {% if preferences.get_value('oscar-style') == 'logicodev-dark' %}selected="selected"{% endif %}>Logicodev dark</option>
111 </select>
128 </select>
112 {{ preferences_item_footer(_('Choose style for this theme'), _('Style'), rtl) }}
129 {{ preferences_item_footer(_('Choose style for this theme'), _('Style'), rtl) }}
130+ {% endif %}
113
131
132+ {% if 'results_on_new_tab' not in locked_preferences %}
114 {% set label = _('Results on new tabs') %}
133 {% set label = _('Results on new tabs') %}
115 {% set info = _('Open result links on new browser tabs') %}
134 {% set info = _('Open result links on new browser tabs') %}
116 {{ preferences_item_header(info, label, rtl, 'results_on_new_tab') }}
135 {{ preferences_item_header(info, label, rtl, 'results_on_new_tab') }}
@@ -119,7 +138,9 @@
119 <option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option>
138 <option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option>
120 </select>
139 </select>
121 {{ preferences_item_footer(info, label, rtl) }}
140 {{ preferences_item_footer(info, label, rtl) }}
141+ {% endif %}
122
142
143+ {% if 'doi_resolver' not in locked_preferences %}
123 {% set label = _('Open Access DOI resolver') %}
144 {% set label = _('Open Access DOI resolver') %}
124 {% set info = _('Redirect to open-access versions of publications when available (plugin required)') %}
145 {% set info = _('Redirect to open-access versions of publications when available (plugin required)') %}
125 {{ preferences_item_header(info, label, rtl, 'doi_resolver') }}
146 {{ preferences_item_header(info, label, rtl, 'doi_resolver') }}
@@ -131,6 +152,7 @@
131 {% endfor %}
152 {% endfor %}
132 </select>
153 </select>
133 {{ preferences_item_footer(info, label, rtl) }}
154 {{ preferences_item_footer(info, label, rtl) }}
155+ {% endif %}
134
156
135 {% set label = _('Engine tokens') %}
157 {% set label = _('Engine tokens') %}
136 {% set info = _('Access tokens for private engines') %}
158 {% set info = _('Access tokens for private engines') %}
searx/templates/pix-art/preferences.html+8
@@ -5,6 +5,7 @@
5 <h2>{{ _('Preferences') }}</h2>
5 <h2>{{ _('Preferences') }}</h2>
6
6
7 <form method="post" action="{{ url_for('preferences') }}" id="search_form">
7 <form method="post" action="{{ url_for('preferences') }}" id="search_form">
8+ {% if 'language' not in locked_preferences %}
8 <fieldset>
9 <fieldset>
9 <legend>{{ _('Search language') }}</legend>
10 <legend>{{ _('Search language') }}</legend>
10 <p>
11 <p>
@@ -16,6 +17,8 @@
16 </select>
17 </select>
17 </p>
18 </p>
18 </fieldset>
19 </fieldset>
20+ {% endif %}
21+ {% if 'locale' not in locked_preferences %}
19 <fieldset>
22 <fieldset>
20 <legend>{{ _('Interface language') }}</legend>
23 <legend>{{ _('Interface language') }}</legend>
21 <p>
24 <p>
@@ -26,6 +29,8 @@
26 </select>
29 </select>
27 </p>
30 </p>
28 </fieldset>
31 </fieldset>
32+ {% endif %}
33+ {% if 'method' not in locked_preferences %}
29 <fieldset>
34 <fieldset>
30 <legend>{{ _('Method') }}</legend>
35 <legend>{{ _('Method') }}</legend>
31 <p>
36 <p>
@@ -35,6 +40,8 @@
35 </select>
40 </select>
36 </p>
41 </p>
37 </fieldset>
42 </fieldset>
43+ {% endif %}
44+ {% if 'theme' not in locked_preferences %}
38 <fieldset>
45 <fieldset>
39 <legend>{{ _('Themes') }}</legend>
46 <legend>{{ _('Themes') }}</legend>
40 <p>
47 <p>
@@ -45,6 +52,7 @@
45 </select>
52 </select>
46 </p>
53 </p>
47 </fieldset>
54 </fieldset>
55+ {% endif %}
48 <fieldset>
56 <fieldset>
49 <legend>{{ _('Currently used search engines') }}</legend>
57 <legend>{{ _('Currently used search engines') }}</legend>
50
58
searx/templates/simple/preferences.html+20
@@ -30,11 +30,14 @@
30{{ tabs_open() }}
30{{ tabs_open() }}
31
31
32{{ tab_header('maintab', 'general', _('General')) }}
32{{ tab_header('maintab', 'general', _('General')) }}
33+ {% if 'categories' not in locked_preferences %}
33 <fieldset>
34 <fieldset>
34 <legend>{{ _('Default categories') }}</legend>
35 <legend>{{ _('Default categories') }}</legend>
35 {% set display_tooltip = false %}
36 {% set display_tooltip = false %}
36 {% include 'simple/categories.html' %}
37 {% include 'simple/categories.html' %}
37 </fieldset>
38 </fieldset>
39+ {% endif %}
40+ {% if 'language' not in locked_preferences %}
38 <fieldset>
41 <fieldset>
39 <legend>{{ _('Search language') }}</legend>
42 <legend>{{ _('Search language') }}</legend>
40 <p class="value">{{- '' -}}
43 <p class="value">{{- '' -}}
@@ -47,6 +50,8 @@
47 </p>
50 </p>
48 <div class="description">{{ _('What language do you prefer for search?') }}</div>
51 <div class="description">{{ _('What language do you prefer for search?') }}</div>
49 </fieldset>
52 </fieldset>
53+ {% endif %}
54+ {% if 'autocomplete' not in locked_preferences %}
50 <fieldset>
55 <fieldset>
51 <legend>{{ _('Autocomplete') }}</legend>
56 <legend>{{ _('Autocomplete') }}</legend>
52 <p class="value">
57 <p class="value">
@@ -59,6 +64,8 @@
59 </p>
64 </p>
60 <div class="description">{{ _('Find stuff as you type') }}</div>
65 <div class="description">{{ _('Find stuff as you type') }}</div>
61 </fieldset>
66 </fieldset>
67+ {% endif %}
68+ {% if 'safesearch' not in locked_preferences %}
62 <fieldset>
69 <fieldset>
63 <legend>{{ _('SafeSearch') }}</legend>
70 <legend>{{ _('SafeSearch') }}</legend>
64 <p class="value">
71 <p class="value">
@@ -70,7 +77,9 @@
70 </p>
77 </p>
71 <p class="description">{{ _('Filter content') }}</p>
78 <p class="description">{{ _('Filter content') }}</p>
72 </fieldset>
79 </fieldset>
80+ {% endif %}
73 {{ plugin_preferences('general') }}
81 {{ plugin_preferences('general') }}
82+ {% if 'doi_resolver' not in locked_preferences %}
74 <fieldset>
83 <fieldset>
75 <legend>{{ _('Open Access DOI resolver') }}</legend>
84 <legend>{{ _('Open Access DOI resolver') }}</legend>
76 <p class="value">
85 <p class="value">
@@ -84,6 +93,7 @@
84 </p>
93 </p>
85 <div class="description"><!-- {{ _('Redirect to open-access versions of publications when available (plugin required)') }} --></div>
94 <div class="description"><!-- {{ _('Redirect to open-access versions of publications when available (plugin required)') }} --></div>
86 </fieldset>
95 </fieldset>
96+ {% endif %}
87 {{ tab_footer() }}
97 {{ tab_footer() }}
88
98
89 {{ tab_header('maintab', 'engines', _('Engines')) }}
99 {{ tab_header('maintab', 'engines', _('Engines')) }}
@@ -129,6 +139,7 @@
129 {{ tab_footer() }}
139 {{ tab_footer() }}
130
140
131 {{ tab_header('maintab', 'ui', _('User interface')) }}
141 {{ tab_header('maintab', 'ui', _('User interface')) }}
142+ {% if 'locale' not in locked_preferences %}
132 <fieldset>
143 <fieldset>
133 <legend>{{ _('Interface language') }}</legend>
144 <legend>{{ _('Interface language') }}</legend>
134 <p class="value">
145 <p class="value">
@@ -140,6 +151,8 @@
140 </p>
151 </p>
141 <div class="description">{{ _('Change the language of the layout') }}</div>
152 <div class="description">{{ _('Change the language of the layout') }}</div>
142 </fieldset>
153 </fieldset>
154+ {% endif %}
155+ {% if 'theme' not in locked_preferences %}
143 <fieldset>
156 <fieldset>
144 <legend>{{ _('Themes') }}</legend>
157 <legend>{{ _('Themes') }}</legend>
145 <p class="value">
158 <p class="value">
@@ -151,6 +164,8 @@
151 </p>
164 </p>
152 <div class="description">{{ _('Change searx layout') }}</div>
165 <div class="description">{{ _('Change searx layout') }}</div>
153 </fieldset>
166 </fieldset>
167+ {% endif %}
168+ {% if 'results_on_new_tab' not in locked_preferences %}
154 <fieldset>
169 <fieldset>
155 <legend>{{ _('Results on new tabs') }}</legend>
170 <legend>{{ _('Results on new tabs') }}</legend>
156 <p class="value">
171 <p class="value">
@@ -161,6 +176,7 @@
161 </p>
176 </p>
162 <div class="description">{{_('Open result links on new browser tabs') }}</div>
177 <div class="description">{{_('Open result links on new browser tabs') }}</div>
163 </fieldset>
178 </fieldset>
179+ {% endif %}
164 {{ plugin_preferences('ui') }}
180 {{ plugin_preferences('ui') }}
165 {{ tab_footer() }}
181 {{ tab_footer() }}
166
182
@@ -197,6 +213,7 @@
197 {{ tab_footer() }}
213 {{ tab_footer() }}
198
214
199 {{ tab_header('maintab', 'privacy', _('Privacy')) }}
215 {{ tab_header('maintab', 'privacy', _('Privacy')) }}
216+ {% if 'method' not in locked_preferences %}
200 <fieldset>
217 <fieldset>
201 <legend>{{ _('Method') }}</legend>
218 <legend>{{ _('Method') }}</legend>
202 <p class="value">
219 <p class="value">
@@ -207,6 +224,8 @@
207 </p>
224 </p>
208 <div class="description">{{ _('Search language') }}</div>
225 <div class="description">{{ _('Search language') }}</div>
209 </fieldset>
226 </fieldset>
227+ {% endif %}
228+ {% if 'image_proxy' not in locked_preferences %}
210 <fieldset>
229 <fieldset>
211 <legend>{{ _('Image proxy') }}</legend>
230 <legend>{{ _('Image proxy') }}</legend>
212 <p class="value">
231 <p class="value">
@@ -217,6 +236,7 @@
217 </p>
236 </p>
218 <div class="description">{{ _('Proxying image results through searx') }}</div>
237 <div class="description">{{ _('Proxying image results through searx') }}</div>
219 </fieldset>
238 </fieldset>
239+ {% endif %}
220 {{ plugin_preferences('privacy') }}
240 {{ plugin_preferences('privacy') }}
221
241
222 {{ tab_footer() }}
242 {{ tab_footer() }}
searx/webadapter.py+9−1
@@ -4,7 +4,7 @@ from searx.webutils import VALID_LANGUAGE_CODE
4from searx.query import RawTextQuery
4from searx.query import RawTextQuery
5from searx.engines import categories, engines
5from searx.engines import categories, engines
6from searx.search import SearchQuery, EngineRef
6from searx.search import SearchQuery, EngineRef
7−from searx.preferences import Preferences
7+from searx.preferences import Preferences, is_locked
8
8
9
9
10# remove duplicate queries.
10# remove duplicate queries.
@@ -48,6 +48,8 @@ def parse_pageno(form: Dict[str, str]) -> int:
48
48
49
49
50def parse_lang(preferences: Preferences, form: Dict[str, str], raw_text_query: RawTextQuery) -> str:
50def parse_lang(preferences: Preferences, form: Dict[str, str], raw_text_query: RawTextQuery) -> str:
51+ if is_locked('language'):
52+ return preferences.get_value('langueage')
51 # get language
53 # get language
52 # set specific language if set on request, query or preferences
54 # set specific language if set on request, query or preferences
53 # TODO support search with multible languages
55 # TODO support search with multible languages
@@ -66,6 +68,9 @@ def parse_lang(preferences: Preferences, form: Dict[str, str], raw_text_query: R
66
68
67
69
68def parse_safesearch(preferences: Preferences, form: Dict[str, str]) -> int:
70def parse_safesearch(preferences: Preferences, form: Dict[str, str]) -> int:
71+ if is_locked('safesearch'):
72+ return preferences.get_value('safesearch')
73+
69 if 'safesearch' in form:
74 if 'safesearch' in form:
70 query_safesearch = form.get('safesearch')
75 query_safesearch = form.get('safesearch')
71 # first check safesearch
76 # first check safesearch
@@ -117,6 +122,9 @@ def parse_specific(raw_text_query: RawTextQuery) -> Tuple[List[EngineRef], List[
117
122
118
123
119def parse_category_form(query_categories: List[str], name: str, value: str) -> None:
124def parse_category_form(query_categories: List[str], name: str, value: str) -> None:
125+ if is_locked('categories'):
126+ return preferences.get_value('categories')
127+
120 if name == 'categories':
128 if name == 'categories':
121 query_categories.extend(categ for categ in map(str.strip, value.split(',')) if categ in categories)
129 query_categories.extend(categ for categ in map(str.strip, value.split(',')) if categ in categories)
122 elif name.startswith('category_'):
130 elif name.startswith('category_'):
searx/webapp.py+5
@@ -828,6 +828,10 @@ def preferences():
828 stats[engine_stat.get('name')]['warn_time'] = True
828 stats[engine_stat.get('name')]['warn_time'] = True
829 # end of stats
829 # end of stats
830
830
831+ locked_preferences = list()
832+ if 'preferences' in settings and 'lock' in settings['preferences']:
833+ locked_preferences = settings['preferences']['lock']
834+
831 return render('preferences.html',
835 return render('preferences.html',
832 selected_categories=get_selected_categories(request.preferences, request.form),
836 selected_categories=get_selected_categories(request.preferences, request.form),
833 all_categories=_get_ordered_categories(),
837 all_categories=_get_ordered_categories(),
@@ -848,6 +852,7 @@ def preferences():
848 theme=get_current_theme_name(),
852 theme=get_current_theme_name(),
849 preferences_url_params=request.preferences.get_as_url_params(),
853 preferences_url_params=request.preferences.get_as_url_params(),
850 base_url=get_base_url(),
854 base_url=get_base_url(),
855+ locked_preferences=locked_preferences,
851 preferences=True)
856 preferences=True)
852
857
853
858
tests/unit/test_preferences.py+1−1
@@ -141,4 +141,4 @@ class TestPreferences(SearxTestCase):
141 pref.parse_encoded_data(url_params)
141 pref.parse_encoded_data(url_params)
142 self.assertEqual(
142 self.assertEqual(
143 vars(pref.key_value_settings['categories']),
143 vars(pref.key_value_settings['categories']),
144− {'value': ['general'], 'choices': ['general', 'none']})
144+ {'value': ['general'], 'locked': False, 'choices': ['general', 'none']})