diff --git a/cps/admin.py b/cps/admin.py index 1c228e49..29f5fb20 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -129,11 +129,11 @@ def admin_forbidden(): abort(403) -@admi.route("/shutdown") +@admi.route("/shutdown", methods=["POST"]) @login_required @admin_required def shutdown(): - task = int(request.args.get("parameter").strip()) + task = request.get_json().get('parameter', -1) showtext = {} if task in (0, 1): # valid commandos received # close all database connections @@ -906,7 +906,7 @@ def list_restriction(res_type, user_id): response.headers["Content-Type"] = "application/json; charset=utf-8" return response -@admi.route("/ajax/fullsync") +@admi.route("/ajax/fullsync", methods=["POST"]) @login_required def ajax_fullsync(): count = ub.session.query(ub.KoboSyncedBooks).filter(current_user.id == ub.KoboSyncedBooks.user_id).delete() @@ -1626,7 +1626,7 @@ def edit_user(user_id): page="edituser") -@admi.route("/admin/resetpassword/") +@admi.route("/admin/resetpassword/", methods=["POST"]) @login_required @admin_required def reset_user_password(user_id): @@ -1802,7 +1802,7 @@ def ldap_import_create_user(user, user_data): return 0, message -@admi.route('/import_ldap_users') +@admi.route('/import_ldap_users', methods=["POST"]) @login_required @admin_required def import_ldap_users(): diff --git a/cps/editbooks.py b/cps/editbooks.py index 21dc3ba0..b6fdc164 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -26,6 +26,8 @@ import json from shutil import copyfile from uuid import uuid4 from markupsafe import escape +from functools import wraps + try: from lxml.html.clean import clean_html except ImportError: @@ -51,13 +53,6 @@ from .tasks.upload import TaskUpload from .render_template import render_title_template from .usermanagement import login_required_if_no_ano -try: - from functools import wraps -except ImportError: - pass # We're not using Python 3 - - - editbook = Blueprint('editbook', __name__) log = logger.create() @@ -237,14 +232,14 @@ def modify_identifiers(input_identifiers, db_identifiers, db_session): changed = True return changed, error -@editbook.route("/ajax/delete/") +@editbook.route("/ajax/delete/", methods=["POST"]) @login_required def delete_book_from_details(book_id): return Response(delete_book_from_table(book_id, "", True), mimetype='application/json') -@editbook.route("/delete/", defaults={'book_format': ""}) -@editbook.route("/delete//") +@editbook.route("/delete/", defaults={'book_format': ""}, methods=["POST"]) +@editbook.route("/delete//", methods=["POST"]) @login_required def delete_book_ajax(book_id, book_format): return delete_book_from_table(book_id, book_format, False) @@ -1014,7 +1009,7 @@ def move_coverfile(meta, db_book): category="error") -@editbook.route("/upload", methods=["GET", "POST"]) +@editbook.route("/upload", methods=["POST"]) @login_required_if_no_ano @upload_required def upload(): diff --git a/cps/kobo_auth.py b/cps/kobo_auth.py index a51095c8..8d46b26a 100644 --- a/cps/kobo_auth.py +++ b/cps/kobo_auth.py @@ -62,6 +62,7 @@ particular calls to non-Kobo specific endpoints such as the CalibreWeb book down from binascii import hexlify from datetime import datetime from os import urandom +from functools import wraps from flask import g, Blueprint, url_for, abort, request from flask_login import login_user, current_user, login_required @@ -70,11 +71,6 @@ from flask_babel import gettext as _ from . import logger, config, calibre_db, db, helper, ub, lm from .render_template import render_title_template -try: - from functools import wraps -except ImportError: - pass # We're not using Python 3 - log = logger.create() @@ -167,7 +163,7 @@ def generate_auth_token(user_id): ) -@kobo_auth.route("/deleteauthtoken/") +@kobo_auth.route("/deleteauthtoken/", methods=["POST"]) @login_required def delete_auth_token(user_id): # Invalidate any prevously generated Kobo Auth token for this user. diff --git a/cps/shelf.py b/cps/shelf.py index 5f6a66bf..19c2d68e 100644 --- a/cps/shelf.py +++ b/cps/shelf.py @@ -56,7 +56,7 @@ def check_shelf_view_permissions(cur_shelf): return True -@shelf.route("/shelf/add//") +@shelf.route("/shelf/add//", methods=["POST"]) @login_required def add_to_shelf(shelf_id, book_id): xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest' @@ -112,7 +112,7 @@ def add_to_shelf(shelf_id, book_id): return "", 204 -@shelf.route("/shelf/massadd/") +@shelf.route("/shelf/massadd/", methods=["POST"]) @login_required def search_to_shelf(shelf_id): shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first() @@ -164,7 +164,7 @@ def search_to_shelf(shelf_id): return redirect(url_for('web.index')) -@shelf.route("/shelf/remove//") +@shelf.route("/shelf/remove//", methods=["POST"]) @login_required def remove_from_shelf(shelf_id, book_id): xhr = request.headers.get('X-Requested-With') == 'XMLHttpRequest' @@ -323,12 +323,13 @@ def delete_shelf_helper(cur_shelf): ub.session_commit("successfully deleted Shelf {}".format(cur_shelf.name)) -@shelf.route("/shelf/delete/") +@shelf.route("/shelf/delete/", methods=["POST"]) @login_required def delete_shelf(shelf_id): cur_shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first() try: delete_shelf_helper(cur_shelf) + flash(_("Shelf successfully deleted"), category="success") except InvalidRequestError: ub.session.rollback() log.error("Settings DB is not Writeable") diff --git a/cps/static/js/main.js b/cps/static/js/main.js index 585d2296..6cef22f8 100644 --- a/cps/static/js/main.js +++ b/cps/static/js/main.js @@ -179,7 +179,7 @@ $("#delete_confirm").click(function() { if (ajaxResponse) { path = getPath() + "/ajax/delete/" + deleteId; $.ajax({ - method:"get", + method:"post", url: path, timeout: 900, success:function(data) { @@ -376,9 +376,11 @@ $(function() { $("#restart").click(function() { $.ajax({ + method:"post", + contentType: "application/json; charset=utf-8", dataType: "json", - url: window.location.pathname + "/../../shutdown", - data: {"parameter":0}, + url: getPath() + "/shutdown", + data: JSON.stringify({"parameter":0}), success: function success() { $("#spinner").show(); setTimeout(restartTimer, 3000); @@ -387,9 +389,11 @@ $(function() { }); $("#shutdown").click(function() { $.ajax({ + method:"post", + contentType: "application/json; charset=utf-8", dataType: "json", - url: window.location.pathname + "/../../shutdown", - data: {"parameter":1}, + url: getPath() + "/shutdown", + data: JSON.stringify({"parameter":1}), success: function success(data) { return alert(data.text); } @@ -447,9 +451,11 @@ $(function() { $("#DialogContent").html(""); $("#spinner2").show(); $.ajax({ + method:"post", + contentType: "application/json; charset=utf-8", dataType: "json", url: getPath() + "/shutdown", - data: {"parameter":2}, + data: JSON.stringify({"parameter":2}), success: function success(data) { $("#spinner2").hide(); $("#DialogContent").html(data.text); @@ -527,7 +533,7 @@ $(function() { $(this).data('value'), function (value) { $.ajax({ - method: "get", + method: "post", url: getPath() + "/kobo_auth/deleteauthtoken/" + value, }); $("#config_delete_kobo_token").hide(); @@ -574,7 +580,7 @@ $(function() { function(value){ path = getPath() + "/ajax/fullsync" $.ajax({ - method:"get", + method:"post", url: path, timeout: 900, success:function(data) { @@ -638,7 +644,7 @@ $(function() { else { $("#InvalidDialog").modal('show'); } - } else { + } else { changeDbSettings(); } } @@ -685,7 +691,7 @@ $(function() { "GeneralDeleteModal", $(this).data('value'), function(value){ - window.location.href = window.location.pathname + "/../../shelf/delete/" + value + $("#delete_shelf").closest("form").submit() } ); @@ -734,7 +740,8 @@ $(function() { $("#DialogContent").html(""); $("#spinner2").show(); $.ajax({ - method:"get", + method:"post", + contentType: "application/json; charset=utf-8", dataType: "json", url: getPath() + "/import_ldap_users", success: function success(data) { diff --git a/cps/templates/shelf.html b/cps/templates/shelf.html index 4f74a4da..5bb9317e 100644 --- a/cps/templates/shelf.html +++ b/cps/templates/shelf.html @@ -2,14 +2,16 @@ {% block body %}

{{title}}

+
{% if g.user.role_download() %} {{ _('Download') }} {% endif %} {% if g.user.is_authenticated %} {% if (g.user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %} - -
{{ _('Delete this Shelf') }}
+ +
{{ _('Delete this Shelf') }}
{{ _('Edit Shelf Properties') }} +
{% if entries.__len__() %} {{ _('Arrange books manually') }} @@ -84,22 +86,6 @@ {% endfor %}
- - {% endblock %} {% block modal %} {{ delete_confirm_modal() }} diff --git a/cps/web.py b/cps/web.py index f203783b..81c37711 100644 --- a/cps/web.py +++ b/cps/web.py @@ -1055,7 +1055,8 @@ def get_tasks_status(): return render_title_template('tasks.html', entries=answer, title=_(u"Tasks"), page="tasks") -@app.route("/reconnect") +# method is available without login and not protected by CSRF to make it easy reachable +@app.route("/reconnect", methods=['GET']) def reconnect(): calibre_db.reconnect_db(config, ub.app_DB_path) return json.dumps({}) @@ -1435,7 +1436,7 @@ def download_link(book_id, book_format, anyname): return get_download_link(book_id, book_format, client) -@web.route('/send///') +@web.route('/send///', methods=["POST"]) @login_required @download_required def send_to_kindle(book_id, book_format, convert):