pgadmin4/web/pgadmin/preferences/__init__.py

323 lines
9.0 KiB
Python

##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2024, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Implements the routes for creating Preferences/Options Dialog on the client
side and for getting/setting preferences.
"""
import config
import json
from flask import render_template, url_for, Response, request, session
from flask_babel import gettext
from pgadmin.user_login_check import pga_login_required
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import success_return, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import make_json_response
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.constants import MIMETYPE_APP_JS
from pgadmin.browser.server_groups import ServerGroupModule as sgm
MODULE_NAME = 'preferences'
class PreferencesModule(PgAdminModule):
"""
PreferenceModule represets the preferences of different modules to the
user in UI.
And, allows the user to modify (not add/remove) as per their requirement.
"""
def get_own_menuitems(self):
return {}
def get_exposed_url_endpoints(self):
"""
Returns:
list: a list of url endpoints exposed to the client.
"""
return [
'preferences.index',
'preferences.get_by_name',
'preferences.get_all',
'preferences.get_all_cli',
'preferences.update_pref'
]
blueprint = PreferencesModule(MODULE_NAME, __name__)
@blueprint.route("/preferences.js")
@pga_login_required
def script():
"""render the required javascript"""
return Response(
response=render_template("preferences/preferences.js", _=gettext),
status=200,
mimetype=MIMETYPE_APP_JS
)
@blueprint.route("/", methods=["GET"], endpoint='index')
@blueprint.route("/<module>/<preference>", endpoint='get_by_name')
@pga_login_required
def preferences(module=None, preference=None):
"""Fetch all/or requested preferences of pgAdmin IV."""
if module is not None and preference is not None:
try:
m = Preferences.module(module, create=False)
if m is None:
return Response(status=404)
p = m.preference(preference)
if p is None:
return Response(status=404)
return ajax_response(
response=p.to_json(),
status=200
)
except Exception as e:
return internal_server_error(errormsg=str(e))
# Load Preferences
pref = Preferences.preferences()
res = []
def label(p):
return gettext(p['label'])
_group_pref_by_categories(pref, res, label)
return ajax_response(
response=sorted(res, key=label),
status=200
)
def _group_pref_by_categories(pref, res, label):
"""
Group preference by categories type.
:param pref: preference data.
:param res: response for request.
:param label: get label.
:return:
"""
for pref_d in pref:
if len(pref_d['categories']):
_iterate_categories(pref_d, label, res)
def _iterate_categories(pref_d, label, res):
"""
Iterate preference categories.
:param pref_d: preference data
:param label: get label.
:param res: response.
:return:
"""
om = {
"id": pref_d['id'],
"label": gettext(pref_d['label']),
"inode": True,
"open": True,
"children": [],
"value": gettext(pref_d['label']),
"name": pref_d['name']
}
for c in pref_d['categories']:
for p in c['preferences']:
if 'label' in p and p['label'] is not None:
p['label'] = gettext(p['label'])
if 'help_str' in p and p['help_str'] is not None:
p['help_str'] = gettext(p['help_str'])
oc = {
"id": c['id'],
"mid": pref_d['id'],
"name": c['name'],
"label": gettext(c['label']),
"value": '{0}{1}'.format(c['id'], gettext(c['label'])),
"inode": False,
"open": False,
"preferences": sorted(c['preferences'], key=label),
"showCheckbox": False
}
(om['children']).append(oc)
om['children'] = sorted(om['children'], key=label)
res.append(om)
@blueprint.route("/get_all", methods=["GET"], endpoint='get_all')
@pga_login_required
def preferences_s():
"""Fetch all preferences for caching."""
# Load Preferences
pref = Preferences.preferences()
res = []
for m in pref:
if len(m['categories']):
for c in m['categories']:
for p in c['preferences']:
p['module'] = m['name']
res.append(p)
return ajax_response(
response=res,
status=200
)
@blueprint.route("/get_all_cli", methods=["GET"], endpoint='get_all_cli')
def get_all_cli():
"""Fetch all preferences for caching."""
# Load Preferences
pref = Preferences.preferences()
res = {}
for m in pref:
if len(m['categories']):
for c in m['categories']:
for p in c['preferences']:
p['module'] = m['name']
res["{0}:{1}:{2}".format(m['label'], p['label'], c['label']
)] = "{0}:{1}:{2}".format(
p['module'],c['name'],p['name'])
return ajax_response(
response=res,
status=200
)
def get_data():
"""
Get preferences data.
:return: Preferences list
:rtype: list
"""
pref_data = request.form if request.form else json.loads(
request.data.decode())
if not pref_data:
raise ValueError("Please provide the valid preferences data to save.")
return pref_data
@blueprint.route("/", methods=["PUT"], endpoint="update")
@pga_login_required
def save():
"""
Save a specific preference.
"""
pref_data = get_data()
for data in pref_data:
if data['name'] in ['vw_edt_tab_title_placeholder',
'qt_tab_title_placeholder',
'debugger_tab_title_placeholder'] \
and data['value'].isspace():
data['value'] = ''
res, msg = Preferences.save(
data['mid'], data['category_id'], data['id'], data['value'])
sgm.get_nodes(sgm)
if not res:
return internal_server_error(errormsg=msg)
response = success_return()
# Set cookie & session for language settings.
# This will execute every time as could not find the better way to know
# that which preference is getting updated.
misc_preference = Preferences.module('misc')
user_languages = misc_preference.preference(
'user_language'
)
language = 'en'
if user_languages:
language = user_languages.get() or language
domain = dict()
if config.COOKIE_DEFAULT_DOMAIN and \
config.COOKIE_DEFAULT_DOMAIN != 'localhost':
domain['domain'] = config.COOKIE_DEFAULT_DOMAIN
setattr(session, 'PGADMIN_LANGUAGE', language)
response.set_cookie("PGADMIN_LANGUAGE", value=language,
path=config.SESSION_COOKIE_PATH,
secure=config.SESSION_COOKIE_SECURE,
httponly=config.SESSION_COOKIE_HTTPONLY,
samesite=config.SESSION_COOKIE_SAMESITE,
**domain)
return response
def save_pref(data):
"""
Save a specific preference.
"""
if data['name'] in ['vw_edt_tab_title_placeholder',
'qt_tab_title_placeholder',
'debugger_tab_title_placeholder'] \
and data['value'].isspace():
data['value'] = ''
if data['value'] in ['true','false']:
data['value'] = True if data['value'] == 'true' else False
res, _ = Preferences.save_cli(
data['mid'], data['category_id'], data['id'], data['user_id'],
data['value'])
if not res:
return False
return True
@blueprint.route("/update", methods=["PUT"], endpoint="update_pref")
@pga_login_required
def update():
"""
Update a specific preference.
"""
pref_data = get_data()
pref_data = json.loads(pref_data['pref_data'])
for data in pref_data:
if data['name'] in ['vw_edt_tab_title_placeholder',
'qt_tab_title_placeholder',
'debugger_tab_title_placeholder'] \
and data['value'].isspace():
data['value'] = ''
pref_module = Preferences.module(data['module'])
pref = pref_module.preference(data['name'])
# set user preferences
pref.set(data['value'])
return make_json_response(
data={'data': 'Success'},
status=200
)