|
|
|
@ -47,10 +47,7 @@ from .gdriveutils import is_gdrive_ready, gdrive_support
|
|
|
|
|
from .render_template import render_title_template, get_sidebar_config
|
|
|
|
|
from . import debug_info, _BABEL_TRANSLATIONS
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from functools import wraps
|
|
|
|
|
except ImportError:
|
|
|
|
|
pass # We're not using Python 3
|
|
|
|
|
from functools import wraps
|
|
|
|
|
|
|
|
|
|
log = logger.create()
|
|
|
|
|
|
|
|
|
@ -199,6 +196,7 @@ def admin():
|
|
|
|
|
feature_support=feature_support, kobo_support=kobo_support,
|
|
|
|
|
title=_(u"Admin page"), page="admin")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/admin/dbconfig", methods=["GET", "POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
@admin_required
|
|
|
|
@ -239,6 +237,7 @@ def ajax_db_config():
|
|
|
|
|
def calibreweb_alive():
|
|
|
|
|
return "", 200
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/admin/viewconfig")
|
|
|
|
|
@login_required
|
|
|
|
|
@admin_required
|
|
|
|
@ -255,6 +254,7 @@ def view_configuration():
|
|
|
|
|
translations=translations,
|
|
|
|
|
title=_(u"UI Configuration"), page="uiconfig")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/admin/usertable")
|
|
|
|
|
@login_required
|
|
|
|
|
@admin_required
|
|
|
|
@ -316,8 +316,8 @@ def list_users():
|
|
|
|
|
|
|
|
|
|
if search:
|
|
|
|
|
all_user = all_user.filter(or_(func.lower(ub.User.name).ilike("%" + search + "%"),
|
|
|
|
|
func.lower(ub.User.kindle_mail).ilike("%" + search + "%"),
|
|
|
|
|
func.lower(ub.User.email).ilike("%" + search + "%")))
|
|
|
|
|
func.lower(ub.User.kindle_mail).ilike("%" + search + "%"),
|
|
|
|
|
func.lower(ub.User.email).ilike("%" + search + "%")))
|
|
|
|
|
if state:
|
|
|
|
|
users = calibre_db.get_checkbox_sorted(all_user.all(), state, off, limit, request.args.get("order", "").lower())
|
|
|
|
|
else:
|
|
|
|
@ -337,12 +337,14 @@ def list_users():
|
|
|
|
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/ajax/deleteuser", methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
@admin_required
|
|
|
|
|
def delete_user():
|
|
|
|
|
user_ids = request.form.to_dict(flat=False)
|
|
|
|
|
users = None
|
|
|
|
|
message = ""
|
|
|
|
|
if "userid[]" in user_ids:
|
|
|
|
|
users = ub.session.query(ub.User).filter(ub.User.id.in_(user_ids['userid[]'])).all()
|
|
|
|
|
elif "userid" in user_ids:
|
|
|
|
@ -370,6 +372,7 @@ def delete_user():
|
|
|
|
|
success.extend(errors)
|
|
|
|
|
return Response(json.dumps(success), mimetype='application/json')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/ajax/getlocale")
|
|
|
|
|
@login_required
|
|
|
|
|
@admin_required
|
|
|
|
@ -429,9 +432,9 @@ def edit_list_user(param):
|
|
|
|
|
if user.name == "Guest":
|
|
|
|
|
raise Exception(_("Guest Name can't be changed"))
|
|
|
|
|
user.name = check_username(vals['value'])
|
|
|
|
|
elif param =='email':
|
|
|
|
|
elif param == 'email':
|
|
|
|
|
user.email = check_email(vals['value'])
|
|
|
|
|
elif param =='kobo_only_shelves_sync':
|
|
|
|
|
elif param == 'kobo_only_shelves_sync':
|
|
|
|
|
user.kobo_only_shelves_sync = int(vals['value'] == 'true')
|
|
|
|
|
elif param == 'kindle_mail':
|
|
|
|
|
user.kindle_mail = valid_email(vals['value']) if vals['value'] else ""
|
|
|
|
@ -451,8 +454,8 @@ def edit_list_user(param):
|
|
|
|
|
ub.User.id != user.id).count():
|
|
|
|
|
return Response(
|
|
|
|
|
json.dumps([{'type': "danger",
|
|
|
|
|
'message':_(u"No admin user remaining, can't remove admin role",
|
|
|
|
|
nick=user.name)}]), mimetype='application/json')
|
|
|
|
|
'message': _(u"No admin user remaining, can't remove admin role",
|
|
|
|
|
nick=user.name)}]), mimetype='application/json')
|
|
|
|
|
user.role &= ~value
|
|
|
|
|
else:
|
|
|
|
|
raise Exception(_("Value has to be true or false"))
|
|
|
|
@ -515,6 +518,7 @@ def update_table_settings():
|
|
|
|
|
return "Invalid request", 400
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_valid_read_column(column):
|
|
|
|
|
if column != "0":
|
|
|
|
|
if not calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.id == column) \
|
|
|
|
@ -522,6 +526,7 @@ def check_valid_read_column(column):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_valid_restricted_column(column):
|
|
|
|
|
if column != "0":
|
|
|
|
|
if not calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.id == column) \
|
|
|
|
@ -560,7 +565,6 @@ def update_view_configuration():
|
|
|
|
|
_config_string(to_save, "config_default_language")
|
|
|
|
|
_config_string(to_save, "config_default_locale")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
config.config_default_role = constants.selected_roles(to_save)
|
|
|
|
|
config.config_default_role &= ~constants.ROLE_ANONYMOUS
|
|
|
|
|
|
|
|
|
@ -597,13 +601,15 @@ def load_dialogtexts(element_id):
|
|
|
|
|
elif element_id == "restrictions":
|
|
|
|
|
texts["main"] = _('Are you sure you want to change the selected restrictions for the selected user(s)?')
|
|
|
|
|
elif element_id == "sidebar_view":
|
|
|
|
|
texts["main"] = _('Are you sure you want to change the selected visibility restrictions for the selected user(s)?')
|
|
|
|
|
texts["main"] = _('Are you sure you want to change the selected visibility restrictions '
|
|
|
|
|
'for the selected user(s)?')
|
|
|
|
|
elif element_id == "kobo_only_shelves_sync":
|
|
|
|
|
texts["main"] = _('Are you sure you want to change shelf sync behavior for the selected user(s)?')
|
|
|
|
|
elif element_id == "db_submit":
|
|
|
|
|
texts["main"] = _('Are you sure you want to change Calibre library location?')
|
|
|
|
|
elif element_id == "btnfullsync":
|
|
|
|
|
texts["main"] = _("Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?")
|
|
|
|
|
texts["main"] = _("Are you sure you want delete Calibre-Web's sync database "
|
|
|
|
|
"to force a full sync with your Kobo Reader?")
|
|
|
|
|
return json.dumps(texts)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -774,6 +780,7 @@ def prepare_tags(user, action, tags_name, id_list):
|
|
|
|
|
def add_user_0_restriction(res_type):
|
|
|
|
|
return add_restriction(res_type, 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/ajax/addrestriction/<int:res_type>/<int:user_id>", methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
@admin_required
|
|
|
|
@ -880,8 +887,8 @@ def delete_restriction(res_type, user_id):
|
|
|
|
|
@admin_required
|
|
|
|
|
def list_restriction(res_type, user_id):
|
|
|
|
|
if res_type == 0: # Tags as template
|
|
|
|
|
restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) }
|
|
|
|
|
for i,x in enumerate(config.list_denied_tags()) if x != '']
|
|
|
|
|
restrict = [{'Element': x, 'type': _('Deny'), 'id': 'd'+str(i)}
|
|
|
|
|
for i, x in enumerate(config.list_denied_tags()) if x != '']
|
|
|
|
|
allow = [{'Element': x, 'type': _('Allow'), 'id': 'a'+str(i)}
|
|
|
|
|
for i, x in enumerate(config.list_allowed_tags()) if x != '']
|
|
|
|
|
json_dumps = restrict + allow
|
|
|
|
@ -918,6 +925,7 @@ def list_restriction(res_type, user_id):
|
|
|
|
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admi.route("/ajax/fullsync", methods=["POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
def ajax_fullsync():
|
|
|
|
@ -1179,7 +1187,7 @@ def simulatedbchange():
|
|
|
|
|
|
|
|
|
|
def _db_simulate_change():
|
|
|
|
|
param = request.form.to_dict()
|
|
|
|
|
to_save = {}
|
|
|
|
|
to_save = dict()
|
|
|
|
|
to_save['config_calibre_dir'] = re.sub(r'[\\/]metadata\.db$',
|
|
|
|
|
'',
|
|
|
|
|
param['config_calibre_dir'],
|
|
|
|
@ -1236,6 +1244,7 @@ def _db_configuration_update_helper():
|
|
|
|
|
config.save()
|
|
|
|
|
return _db_configuration_result(None, gdrive_error)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _configuration_update_helper():
|
|
|
|
|
reboot_required = False
|
|
|
|
|
to_save = request.form.to_dict()
|
|
|
|
@ -1325,6 +1334,7 @@ def _configuration_update_helper():
|
|
|
|
|
|
|
|
|
|
return _configuration_result(None, reboot_required)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _configuration_result(error_flash=None, reboot=False):
|
|
|
|
|
resp = {}
|
|
|
|
|
if error_flash:
|
|
|
|
@ -1332,9 +1342,9 @@ def _configuration_result(error_flash=None, reboot=False):
|
|
|
|
|
config.load()
|
|
|
|
|
resp['result'] = [{'type': "danger", 'message': error_flash}]
|
|
|
|
|
else:
|
|
|
|
|
resp['result'] = [{'type': "success", 'message':_(u"Calibre-Web configuration updated")}]
|
|
|
|
|
resp['result'] = [{'type': "success", 'message': _(u"Calibre-Web configuration updated")}]
|
|
|
|
|
resp['reboot'] = reboot
|
|
|
|
|
resp['config_upload']= config.config_upload_formats
|
|
|
|
|
resp['config_upload'] = config.config_upload_formats
|
|
|
|
|
return Response(json.dumps(resp), mimetype='application/json')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1416,6 +1426,7 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support):
|
|
|
|
|
log.error("Settings DB is not Writeable")
|
|
|
|
|
flash(_("Settings DB is not Writeable"), category="error")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _delete_user(content):
|
|
|
|
|
if ub.session.query(ub.User).filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN,
|
|
|
|
|
ub.User.id != content.id).count():
|
|
|
|
@ -1439,7 +1450,7 @@ def _delete_user(content):
|
|
|
|
|
ub.session.delete(kobo_entry)
|
|
|
|
|
ub.session_commit()
|
|
|
|
|
log.info("User {} deleted".format(content.name))
|
|
|
|
|
return(_("User '%(nick)s' deleted", nick=content.name))
|
|
|
|
|
return _("User '%(nick)s' deleted", nick=content.name)
|
|
|
|
|
else:
|
|
|
|
|
log.warning(_("Can't delete Guest User"))
|
|
|
|
|
raise Exception(_("Can't delete Guest User"))
|
|
|
|
@ -1737,7 +1748,7 @@ def get_updater_status():
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
commit = request.form.to_dict()
|
|
|
|
|
if "start" in commit and commit['start'] == 'True':
|
|
|
|
|
text = {
|
|
|
|
|
txt = {
|
|
|
|
|
"1": _(u'Requesting update package'),
|
|
|
|
|
"2": _(u'Downloading update package'),
|
|
|
|
|
"3": _(u'Unzipping update package'),
|
|
|
|
@ -1752,7 +1763,7 @@ def get_updater_status():
|
|
|
|
|
"12": _(u'Update failed:') + u' ' + _(u'Update file could not be saved in temp dir'),
|
|
|
|
|
"13": _(u'Update failed:') + u' ' + _(u'Files could not be replaced during update')
|
|
|
|
|
}
|
|
|
|
|
status['text'] = text
|
|
|
|
|
status['text'] = txt
|
|
|
|
|
updater_thread.status = 0
|
|
|
|
|
updater_thread.resume()
|
|
|
|
|
status['status'] = updater_thread.get_update_status()
|
|
|
|
|