This commit is contained in:
cbartondock 2021-04-08 20:25:02 -04:00
commit df91ca500f
10 changed files with 61 additions and 31 deletions

View File

@ -37,7 +37,7 @@ from flask_babel import gettext as _
from sqlalchemy import and_
from sqlalchemy.orm.attributes import flag_modified
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
from sqlalchemy.sql.expression import func, or_
from sqlalchemy.sql.expression import func, or_, text
from . import constants, logger, helper, services
from .cli import filepicker
@ -244,6 +244,13 @@ def list_users():
off = request.args.get("offset") or 0
limit = request.args.get("limit") or 10
search = request.args.get("search")
sort = request.args.get("sort")
order = request.args.get("order")
if sort and order:
order = text(sort + " " + order)
else:
order = ub.User.name.desc()
all_user = ub.session.query(ub.User)
if not config.config_anonbrowse:
all_user = all_user.filter(ub.User.role.op('&')(constants.ROLE_ANONYMOUS) != constants.ROLE_ANONYMOUS)
@ -252,10 +259,10 @@ def list_users():
users = 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 + "%")))\
.offset(off).limit(limit).all()
.order_by(order).offset(off).limit(limit).all()
filtered_count = len(users)
else:
users = all_user.offset(off).limit(limit).all()
users = all_user.order_by(order).offset(off).limit(limit).all()
filtered_count = total_count
for user in users:
@ -335,6 +342,9 @@ def edit_list_user(param):
elif param == 'kindle_mail':
user.kindle_mail = valid_email(vals['value']) if vals['value'] else ""
elif param == 'role':
if user.name == "Guest" and int(vals['field_index']) in \
[constants.ROLE_ADMIN, constants.ROLE_PASSWD, constants.ROLE_EDIT_SHELFS]:
raise Exception(_("Guest can't have this role"))
if vals['value'] == 'true':
user.role |= int(vals['field_index'])
else:
@ -345,6 +355,8 @@ def edit_list_user(param):
return _(u"No admin user remaining, can't remove admin role", nick=user.name), 400
user.role &= ~int(vals['field_index'])
elif param == 'sidebar_view':
if user.name == "Guest" and int(vals['field_index']) == constants.SIDEBAR_READ_AND_UNREAD:
raise Exception(_("Guest can't have this view"))
if vals['value'] == 'true':
user.sidebar_view |= int(vals['field_index'])
else:
@ -358,6 +370,8 @@ def edit_list_user(param):
elif param == 'denied_column_value':
user.denied_column_value = vals['value']
elif param == 'locale':
if user.name == "Guest":
raise Exception(_("Guest's Locale is determined automatically and can't be set"))
user.locale = vals['value']
elif param == 'default_language':
user.default_language = vals['value']
@ -1185,10 +1199,14 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
if to_save.get("delete"):
if ub.session.query(ub.User).filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN,
ub.User.id != content.id).count():
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
ub.session_commit()
flash(_(u"User '%(nick)s' deleted", nick=content.name), category="success")
return redirect(url_for('admin.admin'))
if content.name != "Guest":
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
ub.session_commit()
flash(_(u"User '%(nick)s' deleted", nick=content.name), category="success")
return redirect(url_for('admin.admin'))
else:
flash(_(u"Can't delete Guest User"), category="error")
return redirect(url_for('admin.admin'))
else:
flash(_(u"No admin user remaining, can't delete user", nick=content.name), category="error")
return redirect(url_for('admin.admin'))
@ -1255,6 +1273,7 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
except OperationalError:
ub.session.rollback()
flash(_(u"Settings DB is not Writeable"), category="error")
return ""
@admi.route("/admin/user/new", methods=["GET", "POST"])
@ -1350,7 +1369,9 @@ def edit_user(user_id):
kobo_support = feature_support['kobo'] and config.config_kobo_sync
if request.method == "POST":
to_save = request.form.to_dict()
_handle_edit_user(to_save, content, languages, translations, kobo_support)
resp = _handle_edit_user(to_save, content, languages, translations, kobo_support)
if resp:
return resp
return render_title_template("user_edit.html",
translations=translations,
languages=languages,

View File

@ -24,7 +24,7 @@ import sys
from sqlalchemy import exc, Column, String, Integer, SmallInteger, Boolean, BLOB, JSON
from sqlalchemy.exc import OperationalError
try:
# Compability with sqlalchemy 2.0
# Compatibility with sqlalchemy 2.0
from sqlalchemy.orm import declarative_base
except ImportError:
from sqlalchemy.ext.declarative import declarative_base

View File

@ -33,7 +33,7 @@ from sqlalchemy.orm.collections import InstrumentedList
from sqlalchemy.ext.declarative import DeclarativeMeta
from sqlalchemy.exc import OperationalError
try:
# Compability with sqlalchemy 2.0
# Compatibility with sqlalchemy 2.0
from sqlalchemy.orm import declarative_base
except ImportError:
from sqlalchemy.ext.declarative import declarative_base
@ -393,7 +393,7 @@ class AlchemyEncoder(json.JSONEncoder):
if isinstance(o.__class__, DeclarativeMeta):
# an SQLAlchemy class
fields = {}
for field in [x for x in dir(o) if not x.startswith('_') and x != 'metadata']:
for field in [x for x in dir(o) if not x.startswith('_') and x != 'metadata' and x!="password"]:
if field == 'books':
continue
data = o.__getattribute__(field)

View File

@ -238,14 +238,14 @@ def modify_identifiers(input_identifiers, db_identifiers, db_session):
@editbook.route("/ajax/delete/<int:book_id>")
@login_required
def delete_book_from_details(book_id):
return Response(delete_book(book_id,"", True), mimetype='application/json')
return Response(delete_book(book_id, "", True), mimetype='application/json')
@editbook.route("/delete/<int:book_id>", defaults={'book_format': ""})
@editbook.route("/delete/<int:book_id>/<string:book_format>")
@login_required
def delete_book_ajax(book_id, book_format):
return delete_book(book_id,book_format, False)
return delete_book(book_id, book_format, False)
def delete_whole_book(book_id, book):

View File

@ -29,7 +29,7 @@ from sqlalchemy import Column, UniqueConstraint
from sqlalchemy import String, Integer
from sqlalchemy.orm import sessionmaker, scoped_session
try:
# Compability with sqlalchemy 2.0
# Compatibility with sqlalchemy 2.0
from sqlalchemy.orm import declarative_base
except ImportError:
from sqlalchemy.ext.declarative import declarative_base

View File

@ -142,10 +142,11 @@ $("#delete_confirm").click(function() {
//get data-id attribute of the clicked element
var deleteId = $(this).data("delete-id");
var bookFormat = $(this).data("delete-format");
var ajaxResponse = $(this).data("ajax");
if (bookFormat) {
window.location.href = getPath() + "/delete/" + deleteId + "/" + bookFormat;
} else {
if ($(this).data("delete-format")) {
if (ajaxResponse) {
path = getPath() + "/ajax/delete/" + deleteId;
$.ajax({
method:"get",
@ -187,6 +188,7 @@ $("#deleteModal").on("show.bs.modal", function(e) {
}
$(e.currentTarget).find("#delete_confirm").data("delete-id", bookId);
$(e.currentTarget).find("#delete_confirm").data("delete-format", bookfomat);
$(e.currentTarget).find("#delete_confirm").data("ajax", $(e.relatedTarget).data("ajax"));
});

View File

@ -459,8 +459,8 @@ $(function() {
$("input[data-name='admin_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
$("input[data-name='passwd_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
$("input[data-name='edit_shelf_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
// ToDo: Disable delete
$("input[data-name='sidebar_read_and_unread'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
$(".user-remove[data-pk='"+guest.data("pk")+"']").prop("disabled", true);
},
// eslint-disable-next-line no-unused-vars
@ -603,7 +603,7 @@ function EbookActions (value, row) {
/* Function for deleting books */
function UserActions (value, row) {
return [
"<div class=\"user-remove\" data-target=\"#GeneralDeleteModal\" title=\"Remove\">",
"<div class=\"user-remove\" data-pk=\"" + row.id + "\" data-target=\"#GeneralDeleteModal\" title=\"Remove\">",
"<i class=\"glyphicon glyphicon-trash\"></i>",
"</div>"
].join("");
@ -618,14 +618,14 @@ function responseHandler(res) {
}
function singleUserFormatter(value, row) {
return '<a class="btn btn-default" href="/admin/user/' + row.id + '">' + this.buttontext + '</a>'
return '<a class="btn btn-default" href="' + window.location.pathname + '/../../admin/user/' + row.id + '">' + this.buttontext + '</a>'
}
function checkboxFormatter(value, row, index){
if(value & this.column)
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.name + '" checked onchange="checkboxChange(this, ' + row.id + ', \'' + this.field + '\', ' + this.column + ')">';
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" checked onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">';
else
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.name + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.field + '\', ' + this.column + ')">';
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">';
}
function checkboxChange(checkbox, userId, field, field_index) {
@ -732,6 +732,11 @@ function user_handle (userId) {
});
}
function checkboxSorter(a, b, c, d)
{
return a - b
}
function test(){
console.log("hello");
}

View File

@ -111,15 +111,16 @@
{{ user_table_row('allowed_column_value', _("Edit Allowed Column Values"), _("Allowed Column Values"), false, true, 2) }}
{{ user_table_row('denied_column_value', _("Edit Denied Column Values"), _("Denied Columns Values"), false, true, 3) }}
{{ user_checkbox_row("role", "admin_role", _('Admin'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "download_role",_('Upload'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "upload_role", _('Download'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "edit_role", _('Edit'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "passwd_role", _('Change Password'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "edit_shelf_role", _('Edit Public Shelfs'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "delete_role", _('Delete'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "upload_role",_('Upload'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "download_role", _('Download'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "viewer_role", _('View'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "edit_role", _('Edit'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "delete_role", _('Delete'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "edit_shelf_role", _('Edit Public Shelfs'), visiblility, all_roles)}}
{{ user_checkbox_row("sidebar_view", "detail_random", _('Show Random Books in Detail View'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_language", _('Show language selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show read/unread selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_series", _('Show series selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_category", _('Show category selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_random", _('Show random books'), visiblility, sidebar_settings)}}

View File

@ -44,7 +44,7 @@ from sqlalchemy import String, Integer, SmallInteger, Boolean, DateTime, Float,
from sqlalchemy.orm.attributes import flag_modified
from sqlalchemy.sql.expression import func
try:
# Compability with sqlalchemy 2.0
# Compatibility with sqlalchemy 2.0
from sqlalchemy.orm import declarative_base
except ImportError:
from sqlalchemy.ext.declarative import declarative_base

View File

@ -755,11 +755,12 @@ def books_table():
def list_books():
off = request.args.get("offset") or 0
limit = request.args.get("limit") or config.config_books_per_page
# sort = request.args.get("sort")
if request.args.get("order") == 'desc':
order = [db.Books.timestamp.desc()]
sort = request.args.get("sort")
order = request.args.get("order")
if sort and order:
order = [text(sort + " " + order)]
else:
order = [db.Books.timestamp.asc()]
order = [db.Books.timestamp.desc()]
search = request.args.get("search")
total_count = calibre_db.session.query(db.Books).count()
if search: