From 0f95800dde1ed015e878ce1b5c2afe153e7f04e5 Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Mon, 12 Apr 2021 18:23:25 +0200 Subject: [PATCH 1/4] Update sqlalchemy-utils dependency for oauth Sort for state checkbox in user list and books list working --- cps/static/js/table.js | 3 +-- optional-requirements.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cps/static/js/table.js b/cps/static/js/table.js index 59b70626..68f00aee 100644 --- a/cps/static/js/table.js +++ b/cps/static/js/table.js @@ -117,6 +117,7 @@ $(function() { $("#books-table").bootstrapTable({ sidePagination: "server", + queryParams: queryParams, pagination: true, paginationLoop: false, paginationDetailHAlign: " hidden", @@ -734,8 +735,6 @@ function queryParams(params) params.state = JSON.stringify(selections); return params; } -function user_handle (userId) { -} function test(){ console.log("hello"); diff --git a/optional-requirements.txt b/optional-requirements.txt index b6fee806..ca54fe4d 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -27,7 +27,7 @@ Flask-SimpleLDAP>=1.4.0,<1.5.0 #oauth Flask-Dance>=1.4.0,<3.1.0 -SQLAlchemy-Utils>=0.33.5,<0.37.0 +SQLAlchemy-Utils>=0.33.5,<0.38.0 # extracting metadata lxml>=3.8.0,<4.7.0 From 90f2b3fb212352a3aa9e6e47060bf5e01f7cb8af Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Mon, 12 Apr 2021 18:39:09 +0200 Subject: [PATCH 2/4] Refactored list checkbox sort --- cps/admin.py | 22 +++++++--------------- cps/db.py | 13 +++++++++++++ cps/web.py | 23 ++++++++--------------- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index 935aee45..10f9a5b4 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -246,15 +246,16 @@ def list_users(): limit = int(request.args.get("limit") or 10) search = request.args.get("search") sort = request.args.get("sort", "state") - order = request.args.get("order") + order = request.args.get("order", "").lower() state = None - if sort != "state" and order: - order = text(sort + " " + order) - else: - order = ub.User.name.desc() if sort == "state": state = json.loads(request.args.get("state")) + if sort != "state" and order: + order = text(sort + " " + order) + elif not state: + 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) @@ -266,16 +267,7 @@ def list_users(): func.lower(ub.User.kindle_mail).ilike("%" + search + "%"), func.lower(ub.User.email).ilike("%" + search + "%"))) if state: - outcome = list() - userlist = {user.id:user for user in all_user.all()} - for entry in state: - outcome.append(userlist[entry]) - del userlist[entry] - for entry in userlist: - outcome.append(userlist[entry]) - if request.args.get("order", "").lower() == "asc": - outcome.reverse() - users = outcome[off:off + limit] + users = calibre_db.get_checkbox_sorted(all_user.all(), state, off, limit, request.args.get("order", "").lower()) else: users = all_user.order_by(order).offset(off).limit(limit).all() if search: diff --git a/cps/db.py b/cps/db.py index 51aeeca1..0d7055a4 100644 --- a/cps/db.py +++ b/cps/db.py @@ -616,6 +616,19 @@ class CalibreDB(): return and_(lang_filter, pos_content_tags_filter, ~neg_content_tags_filter, pos_content_cc_filter, ~neg_content_cc_filter, archived_filter) + @staticmethod + def get_checkbox_sorted(inputlist, state, offset, limit, order): + outcome = list() + elementlist = {ele.id: ele for ele in inputlist} + for entry in state: + outcome.append(elementlist[entry]) + del elementlist[entry] + for entry in elementlist: + outcome.append(elementlist[entry]) + if order == "asc": + outcome.reverse() + return outcome[offset:offset + limit] + # Fill indexpage with all requested data from database def fill_indexpage(self, page, pagesize, database, db_filter, order, *join): return self.fill_indexpage_with_archived_books(page, pagesize, database, db_filter, order, False, *join) diff --git a/cps/web.py b/cps/web.py index a8c7b71a..528e285a 100644 --- a/cps/web.py +++ b/cps/web.py @@ -757,33 +757,26 @@ def list_books(): limit = int(request.args.get("limit") or config.config_books_per_page) search = request.args.get("search") sort = request.args.get("sort", "state") - order = request.args.get("order") + order = request.args.get("order", "").lower() state = None - if sort != "state" and order: - order = [text(sort + " " + order)] - else: - order = [db.Books.timestamp.desc()] + if sort == "state": state = json.loads(request.args.get("state")) + if sort != "state" and order: + order = [text(sort + " " + order)] + elif not state: + order = [db.Books.timestamp.desc()] + total_count = filtered_count = calibre_db.session.query(db.Books).count() if state: - outcome = list() if search: books = calibre_db.search_query(search) filtered_count = len(books) else: books = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).all() - booklist = {book.id: book for book in books} - for entry in state: - outcome.append(booklist[entry]) - del booklist[entry] - for entry in booklist: - outcome.append(booklist[entry]) - if request.args.get("order", "").lower() == "asc": - outcome.reverse() - entries = outcome[off:off + limit] + entries = calibre_db.get_checkbox_sorted(books, state, off, limit,order) elif search: entries, filtered_count, __ = calibre_db.get_search_results(search, off, order, limit) else: From d0a895628ea1137a7bede955d84f42eda849617d Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Mon, 12 Apr 2021 18:45:44 +0200 Subject: [PATCH 3/4] Prevent delete of Guest user #1938 --- cps/static/js/table.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cps/static/js/table.js b/cps/static/js/table.js index 68f00aee..7a07d82d 100644 --- a/cps/static/js/table.js +++ b/cps/static/js/table.js @@ -462,7 +462,7 @@ $(function() { $("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); $("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); + $(".user-remove[data-pk='"+guest.data("pk")+"']").hide(); }, onSort: function(a, b) { console.log("huh"); From d32b2ca524371e377ca19deabbab6f3553ddc8b6 Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Mon, 12 Apr 2021 19:04:27 +0200 Subject: [PATCH 4/4] Prevent traceback after delete user flash message in case last admin role is removed #1938 --- cps/admin.py | 8 +++++--- cps/static/js/table.js | 35 ++++++++++++++++++++--------------- cps/web.py | 2 +- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index 10f9a5b4..5cd31f18 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -249,7 +249,7 @@ def list_users(): order = request.args.get("order", "").lower() state = None if sort == "state": - state = json.loads(request.args.get("state")) + state = json.loads(request.args.get("state", "[]")) if sort != "state" and order: order = text(sort + " " + order) @@ -356,7 +356,7 @@ def edit_list_user(param): user.email = check_email(vals['value']) elif param == 'kindle_mail': user.kindle_mail = valid_email(vals['value']) if vals['value'] else "" - elif param == 'role': + elif param.endswith('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")) @@ -367,7 +367,9 @@ def edit_list_user(param): if not ub.session.query(ub.User).\ filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN, ub.User.id != user.id).count(): - return _(u"No admin user remaining, can't remove admin role", nick=user.name), 400 + return Response(json.dumps({'type': "danger", + 'message':_(u"No admin user remaining, can't remove admin role", + nick=user.name)}), mimetype='application/json') user.role &= ~int(vals['field_index']) elif param == 'sidebar_view': if user.name == "Guest" and int(vals['field_index']) == constants.SIDEBAR_READ_AND_UNREAD: diff --git a/cps/static/js/table.js b/cps/static/js/table.js index 7a07d82d..7c4b04a7 100644 --- a/cps/static/js/table.js +++ b/cps/static/js/table.js @@ -612,25 +612,30 @@ function checkboxFormatter(value, row, index){ function checkboxChange(checkbox, userId, field, field_index) { $.ajax({ - method:"post", + method: "post", url: window.location.pathname + "/../../ajax/editlistusers/" + field, - data: {"pk":userId, "field_index":field_index, "value": checkbox.checked} - /*
- -
*/ - /*
Text to show
*/ - }); - $.ajax({ - method:"get", - url: window.location.pathname + "/../../ajax/listusers", - async: true, - timeout: 900, - success:function(data) { - $("#user-table").bootstrapTable("load", data); + data: {"pk": userId, "field_index": field_index, "value": checkbox.checked}, + success: function (data) { + if (!jQuery.isEmptyObject(data)) { + $("#flash_success").remove(); + $("#flash_danger").remove(); + $( ".navbar" ).after( '
' + + '
'+data.message+'
' + + '
'); + } + $.ajax({ + method: "get", + url: window.location.pathname + "/../../ajax/listusers", + async: true, + timeout: 900, + success: function (data) { + $("#user-table").bootstrapTable("load", data); + } + }); } }); } + function deactivateHeaderButtons(e) { $("#user_delete_selection").addClass("disabled"); $("#user_delete_selection").attr("aria-disabled", true); diff --git a/cps/web.py b/cps/web.py index 528e285a..cf488986 100644 --- a/cps/web.py +++ b/cps/web.py @@ -761,7 +761,7 @@ def list_books(): state = None if sort == "state": - state = json.loads(request.args.get("state")) + state = json.loads(request.args.get("state", "[]")) if sort != "state" and order: order = [text(sort + " " + order)]