add support for config through url
This commit is contained in:
parent
32ad39d0e1
commit
27e16e5e2c
|
@ -1,7 +1,12 @@
|
|||
from inspect import Attribute
|
||||
from app.utils.misc import read_config_bool
|
||||
from flask import current_app
|
||||
import os
|
||||
import re
|
||||
from base64 import urlsafe_b64encode
|
||||
import pickle
|
||||
from cryptography.fernet import Fernet
|
||||
import hashlib
|
||||
|
||||
|
||||
class Config:
|
||||
|
@ -29,6 +34,7 @@ class Config:
|
|||
self.view_image = read_config_bool('WHOOGLE_CONFIG_VIEW_IMAGE')
|
||||
self.get_only = read_config_bool('WHOOGLE_CONFIG_GET_ONLY')
|
||||
self.anon_view = read_config_bool('WHOOGLE_CONFIG_ANON_VIEW')
|
||||
self.preferences_key = os.getenv('WHOOGLE_CONFIG_PREFERENCES_KEY', '')
|
||||
self.accept_language = False
|
||||
|
||||
self.safe_keys = [
|
||||
|
@ -71,6 +77,15 @@ class Config:
|
|||
if not name.startswith("__")
|
||||
and (type(attr) is bool or type(attr) is str)}
|
||||
|
||||
def get_attrs(self):
|
||||
return {name: attr for name, attr in self.__dict__.items()
|
||||
if not name.startswith("__")
|
||||
and (type(attr) is bool or type(attr) is str)}
|
||||
|
||||
@property
|
||||
def preferences(self) -> str:
|
||||
return self._encode_preferences()
|
||||
|
||||
def is_safe_key(self, key) -> bool:
|
||||
"""Establishes a group of config options that are safe to set
|
||||
in the url.
|
||||
|
@ -109,6 +124,13 @@ class Config:
|
|||
Returns:
|
||||
Config -- a modified config object
|
||||
"""
|
||||
if 'preferences' in params:
|
||||
params_new = self._decode_preferences(params['preferences'])
|
||||
# if preferences leads to an empty dictionary it means preferences
|
||||
# parameter was not decrypted successfully
|
||||
if len(params_new):
|
||||
params = params_new
|
||||
|
||||
for param_key in params.keys():
|
||||
if not self.is_safe_key(param_key):
|
||||
continue
|
||||
|
@ -116,6 +138,8 @@ class Config:
|
|||
|
||||
if param_val == 'off':
|
||||
param_val = False
|
||||
elif isinstance(param_val, bool):
|
||||
pass
|
||||
elif param_val.isdigit():
|
||||
param_val = int(param_val)
|
||||
|
||||
|
@ -135,3 +159,25 @@ class Config:
|
|||
param_str = param_str + f'&{safe_key}={self[safe_key]}'
|
||||
|
||||
return param_str
|
||||
|
||||
def _get_fernet_key(self, password: str) -> bytes:
|
||||
hash_object = hashlib.md5(password.encode())
|
||||
key = urlsafe_b64encode(hash_object.hexdigest().encode())
|
||||
return key
|
||||
|
||||
def _encode_preferences(self) -> str:
|
||||
if self.preferences_key == '':
|
||||
return ''
|
||||
encoded_preferences = pickle.dumps(self.get_attrs())
|
||||
key = self._get_fernet_key(self.preferences_key)
|
||||
return Fernet(key).encrypt(encoded_preferences).decode()
|
||||
|
||||
def _decode_preferences(self, preferences: str) -> dict:
|
||||
try:
|
||||
key = self._get_fernet_key(self.preferences_key)
|
||||
config = Fernet(key).decrypt(preferences.encode())
|
||||
config = pickle.loads(config)
|
||||
except Exception:
|
||||
config = {}
|
||||
|
||||
return config
|
|
@ -193,6 +193,9 @@ def index():
|
|||
session['error_message'] = ''
|
||||
return render_template('error.html', error_message=error_message)
|
||||
|
||||
# Update user config if specified in search args
|
||||
g.user_config = g.user_config.from_params(g.request_params)
|
||||
|
||||
return render_template('index.html',
|
||||
has_update=app.config['HAS_UPDATE'],
|
||||
languages=app.config['LANGUAGES'],
|
||||
|
@ -231,7 +234,8 @@ def opensearch():
|
|||
main_url=opensearch_url,
|
||||
request_type='' if get_only else 'method="post"',
|
||||
search_type=request.args.get('tbm'),
|
||||
search_name=get_search_name(request.args.get('tbm'))
|
||||
search_name=get_search_name(request.args.get('tbm')),
|
||||
preferences=g.user_config.preferences
|
||||
), 200, {'Content-Type': 'application/xml'}
|
||||
|
||||
|
||||
|
@ -334,6 +338,7 @@ def search():
|
|||
tabs = get_tabs_content(app.config['HEADER_TABS'],
|
||||
search_util.full_query,
|
||||
search_util.search_type,
|
||||
g.user_config.preferences,
|
||||
translation)
|
||||
|
||||
# Feature to display currency_card
|
||||
|
@ -342,6 +347,9 @@ def search():
|
|||
html_soup = bsoup(str(response), 'html.parser')
|
||||
response = add_currency_card(html_soup, conversion)
|
||||
|
||||
preferences = g.user_config.preferences
|
||||
home_url = f"home?preferences={preferences}" if preferences else "home"
|
||||
|
||||
return render_template(
|
||||
'display.html',
|
||||
has_update=app.config['HAS_UPDATE'],
|
||||
|
@ -365,6 +373,7 @@ def search():
|
|||
version_number=app.config['VERSION_NUMBER'],
|
||||
search_header=render_template(
|
||||
'header.html',
|
||||
home_url=home_url,
|
||||
config=g.user_config,
|
||||
translation=translation,
|
||||
languages=app.config['LANGUAGES'],
|
||||
|
|
|
@ -4,13 +4,16 @@
|
|||
<form class="search-form header"
|
||||
id="search-form"
|
||||
method="{{ 'GET' if config.get_only else 'POST' }}">
|
||||
<a class="logo-link mobile-logo" href="home">
|
||||
<a class="logo-link mobile-logo" href="{{ home_url }}">
|
||||
<div id="mobile-header-logo">
|
||||
{{ logo|safe }}
|
||||
</div>
|
||||
</a>
|
||||
<div class="H0PQec mobile-input-div">
|
||||
<div class="autocomplete-mobile esbc autocomplete">
|
||||
{% if config.preferences %}
|
||||
<input type="hidden" name="preferences" value="{{ config.preferences }}" />
|
||||
{% endif %}
|
||||
<input
|
||||
id="search-bar"
|
||||
class="mobile-search-bar"
|
||||
|
@ -57,7 +60,7 @@
|
|||
{% else %}
|
||||
<header>
|
||||
<div class="logo-div">
|
||||
<a class="logo-link" href="home">
|
||||
<a class="logo-link" href="{{ home_url }}">
|
||||
<div class="desktop-header-logo">
|
||||
{{ logo|safe }}
|
||||
</div>
|
||||
|
@ -70,6 +73,9 @@
|
|||
method="{{ 'GET' if config.get_only else 'POST' }}">
|
||||
<div class="autocomplete header-autocomplete">
|
||||
<div style="width: 100%; display: flex">
|
||||
{% if config.preferences %}
|
||||
<input type="hidden" name="preferences" value="{{ config.preferences }}" />
|
||||
{% endif %}
|
||||
<input
|
||||
id="search-bar"
|
||||
autocapitalize="none"
|
||||
|
|
|
@ -66,6 +66,9 @@
|
|||
<form id="search-form" action="search" method="{{ 'get' if config.get_only else 'post' }}">
|
||||
<div class="search-fields">
|
||||
<div class="autocomplete">
|
||||
{% if config.preferences %}
|
||||
<input type="hidden" name="preferences" value="{{ config.preferences }}" />
|
||||
{% endif %}
|
||||
<input
|
||||
type="text"
|
||||
name="q"
|
||||
|
@ -233,6 +236,10 @@
|
|||
{{ config.style.replace('\t', '') }}
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="config-div config-div-pref-url">
|
||||
<label for="config-pref-url">{{ translation['config-url'] }}: </label>
|
||||
<input type="text" name="pref-url" id="config-pref-url" value="{{ config.url }}?preferences={{ config.preferences }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-div config-buttons">
|
||||
<input type="submit" id="config-load" value="{{ translation['load'] }}">
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
{% if search_type %}
|
||||
<Param name="tbm" value="{{ search_type }}"/>
|
||||
{% endif %}
|
||||
{% if preferences %}
|
||||
<Param name="preferences" value="{{ preferences }}"/>
|
||||
{% endif %}
|
||||
</Url>
|
||||
<Url type="application/x-suggestions+json" {{ request_type|safe }} template="{{ main_url }}/autocomplete">
|
||||
<Param name="q" value="{searchTerms}"/>
|
||||
|
|
|
@ -393,6 +393,7 @@ def add_currency_card(soup: BeautifulSoup,
|
|||
def get_tabs_content(tabs: dict,
|
||||
full_query: str,
|
||||
search_type: str,
|
||||
preferences: str,
|
||||
translation: dict) -> dict:
|
||||
"""Takes the default tabs content and updates it according to the query.
|
||||
|
||||
|
@ -416,6 +417,9 @@ def get_tabs_content(tabs: dict,
|
|||
|
||||
if tab_content['tbm'] is not None:
|
||||
query = f"{query}&tbm={tab_content['tbm']}"
|
||||
|
||||
if preferences:
|
||||
query = f"{query}&preferences={preferences}"
|
||||
|
||||
tab_content['href'] = tab_content['href'].format(query=query)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user