Merge branch 'master' of https://github.com/janeczku/calibre-web
This commit is contained in:
commit
df91ca500f
37
cps/admin.py
37
cps/admin.py
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"));
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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)}}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue
Block a user