Changement du refresh handler, soft reset d'ajouter sur beaucoup de formulaire de modification
CI - Security, Lint & Tests / validate (push) Failing after 1m3s
CI - Security, Lint & Tests / validate (push) Failing after 1m3s
This commit is contained in:
+52
-2
@@ -26,8 +26,10 @@ from sqlalchemy import text
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from app import i18n
|
||||
from app.api import json_endpoint
|
||||
from app.extensions import babel, csrf, db, limiter, login_manager
|
||||
from app.pagination import page_url
|
||||
from app.responders import current_revision, is_ajax_submit
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -347,6 +349,42 @@ def create_app(config=None):
|
||||
response.headers['X-Request-Id'] = g.get('request_id', '-')
|
||||
return response
|
||||
|
||||
@app.before_request
|
||||
def reject_stale_ajax_write():
|
||||
"""Reject an AJAX edit whose view is stale, instead of overwriting.
|
||||
|
||||
The AJAX form handler in main.js sends the revision it last saw in the
|
||||
X-Revision header. If another client has committed since then the
|
||||
server's revision has moved on, and clobbering their change would be
|
||||
silent last-write-wins. Answer 409 so the client asks the user to
|
||||
reload the page first.
|
||||
"""
|
||||
if request.method != 'POST':
|
||||
return None
|
||||
if not is_ajax_submit():
|
||||
return None
|
||||
sent = request.headers.get('X-Revision')
|
||||
if sent is None:
|
||||
return None
|
||||
try:
|
||||
sent = int(sent)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
if sent != current_revision():
|
||||
return (
|
||||
jsonify(
|
||||
{
|
||||
'error': 'conflict',
|
||||
'message': _(
|
||||
'This page was changed by someone else. Reload to '
|
||||
'see the latest changes before saving.'
|
||||
),
|
||||
}
|
||||
),
|
||||
409,
|
||||
)
|
||||
return None
|
||||
|
||||
@app.url_defaults
|
||||
def version_static_urls(endpoint, values):
|
||||
"""Stamp every static URL with the file's modification time.
|
||||
@@ -403,6 +441,7 @@ def create_app(config=None):
|
||||
|
||||
configure_logging(app)
|
||||
|
||||
from app.routes.admin import admin_bp
|
||||
from app.routes.auth import auth_bp
|
||||
from app.routes.evaluations import evaluations_bp
|
||||
from app.routes.main import main_bp
|
||||
@@ -411,7 +450,6 @@ def create_app(config=None):
|
||||
from app.routes.teams import teams_bp
|
||||
from app.routes.tryouts import tryouts_bp
|
||||
from app.routes.users import users_bp
|
||||
from app.routes.admin import admin_bp
|
||||
|
||||
app.register_blueprint(auth_bp)
|
||||
app.register_blueprint(tryouts_bp)
|
||||
@@ -531,6 +569,18 @@ def create_app(config=None):
|
||||
|
||||
return jsonify(health_data), 200
|
||||
|
||||
@app.route('/api/revision')
|
||||
@json_endpoint
|
||||
def data_revision():
|
||||
"""The current dataset revision, for the AJAX form handler in main.js.
|
||||
|
||||
One primary-key lookup in app_settings. The client compares this with
|
||||
the revision it last saw to decide whether a focus refresh is needed,
|
||||
and sends it back with every AJAX mutation so a stale edit is rejected
|
||||
with a 409 instead of overwriting someone else's change.
|
||||
"""
|
||||
return jsonify({'revision': current_revision()})
|
||||
|
||||
# =========================================================================
|
||||
# Custom Error Handlers
|
||||
# =========================================================================
|
||||
@@ -725,4 +775,4 @@ def create_app(config=None):
|
||||
# own host, port and debug default — `python app/app.py` bound 0.0.0.0:10000
|
||||
# while `python run.py` bound 127.0.0.2:5000 with the debugger on. This
|
||||
# module defines the factory; run.py starts it for development, wsgi.py for
|
||||
# production (ARCH-007).
|
||||
# production (ARCH-007).
|
||||
|
||||
Reference in New Issue
Block a user