Commit 96f46153 authored by Serge S. Koval's avatar Serge S. Koval

Merge pull request #766 from pawl/fix_delete_csrf

fix index_view csrf value rendering
parents 10b2f19a c01277a3
...@@ -58,13 +58,36 @@ Form Rendering Rule Description ...@@ -58,13 +58,36 @@ Form Rendering Rule Description
Enabling CSRF Validation Enabling CSRF Validation
--------------- ---------------
Adding CSRF validation will require overriding the :class:`flask.ext.admin.form.BaseForm` by using :attr:`flask.ext.admin.model.BaseModelView.form_base_class`.
Flask-Admin does not use Flask-WTF Form class - it uses the wtforms Form class, which does not have CSRF validation. WTForms >=2::
Adding CSRF validation will require importing flask_wtf and overriding the :class:`flask.ext.admin.form.BaseForm` by using :attr:`flask.ext.admin.model.BaseModelView.form_base_class`::
from wtforms.csrf.session import SessionCSRF
from wtforms.meta import DefaultMeta
from flask import session
from datetime import timedelta
from flask.ext.admin import form
from flask.ext.admin.contrib import sqla
class SecureForm(form.BaseForm):
class Meta(DefaultMeta):
csrf = True
csrf_class = SessionCSRF
csrf_secret = b'EPj00jpfj8Gx1SjnyLxwBBSQfnQ9DJYe0Ym'
csrf_time_limit = timedelta(minutes=20)
@property
def csrf_context(self):
return session
class ModelAdmin(sqla.ModelView):
form_base_class = SecureForm
For WTForms 1, you can use use Flask-WTF's Form class::
import os import os
import flask import flask
**import flask_wtf** import flask_wtf
import flask_admin import flask_admin
import flask_sqlalchemy import flask_sqlalchemy
from flask_admin.contrib.sqla import ModelView from flask_admin.contrib.sqla import ModelView
...@@ -74,15 +97,15 @@ Adding CSRF validation will require importing flask_wtf and overriding the :clas ...@@ -74,15 +97,15 @@ Adding CSRF validation will require importing flask_wtf and overriding the :clas
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['SECRET_KEY'] = 'Dnit7qz7mfcP0YuelDrF8vLFvk0snhwP' app.config['SECRET_KEY'] = 'Dnit7qz7mfcP0YuelDrF8vLFvk0snhwP'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + DBFILE app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + DBFILE
**app.config['CSRF_ENABLED'] = True** app.config['CSRF_ENABLED'] = True
**flask_wtf.CsrfProtect(app)** flask_wtf.CsrfProtect(app)
db = flask_sqlalchemy.SQLAlchemy(app) db = flask_sqlalchemy.SQLAlchemy(app)
admin = flask_admin.Admin(app, name='Admin') admin = flask_admin.Admin(app, name='Admin')
## Here is the fix:
class MyModelView(ModelView): class MyModelView(ModelView):
**form_base_class = flask_wtf.Form** # Here is the fix:
form_base_class = flask_wtf.Form
class User(db.Model): class User(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
...@@ -92,7 +115,6 @@ Adding CSRF validation will require importing flask_wtf and overriding the :clas ...@@ -92,7 +115,6 @@ Adding CSRF validation will require importing flask_wtf and overriding the :clas
if not os.path.exists(DBFILE): if not os.path.exists(DBFILE):
db.create_all() db.create_all()
## The subclass is used here:
admin.add_view( MyModelView(User, db.session, name='User') ) admin.add_view( MyModelView(User, db.session, name='User') )
app.run(debug=True) app.run(debug=True)
......
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
<input type="hidden" name="id" value="{{ get_pk_value(row) }}"/> <input type="hidden" name="id" value="{{ get_pk_value(row) }}"/>
<input type="hidden" name="url" value="{{ return_url }}"/> <input type="hidden" name="url" value="{{ return_url }}"/>
{% if delete_form.csrf_token %} {% if delete_form.csrf_token %}
<input type="hidden" name="csrf_token" value="{{ delete_form.csrf_token() }}"/> <input name="csrf_token" type="hidden" value="{{ delete_form.csrf_token._value() }}"/>
{% endif %} {% endif %}
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete this record?') }}');" title="{{ _gettext('Delete record') }}"> <button onclick="return confirm('{{ _gettext('Are you sure you want to delete this record?') }}');" title="{{ _gettext('Delete record') }}">
<i class="icon-trash"></i> <i class="icon-trash"></i>
......
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
<input type="hidden" name="id" value="{{ get_pk_value(row) }}"/> <input type="hidden" name="id" value="{{ get_pk_value(row) }}"/>
<input type="hidden" name="url" value="{{ return_url }}"/> <input type="hidden" name="url" value="{{ return_url }}"/>
{% if delete_form.csrf_token %} {% if delete_form.csrf_token %}
<input type="hidden" name="csrf_token" value="{{ delete_form.csrf_token() }}"/> <input name="csrf_token" type="hidden" value="{{ delete_form.csrf_token() }}"/>
{% endif %} {% endif %}
<button onclick="return confirm('{{ _gettext('Are you sure you want to delete this record?') }}');" title="Delete record"> <button onclick="return confirm('{{ _gettext('Are you sure you want to delete this record?') }}');" title="Delete record">
<span class="glyphicon glyphicon-trash"></span> <span class="glyphicon glyphicon-trash"></span>
......
...@@ -366,7 +366,7 @@ def test_csrf(): ...@@ -366,7 +366,7 @@ def test_csrf():
def get_csrf_token(data): def get_csrf_token(data):
data = data.split('name="csrf_token" type="hidden" value="')[1] data = data.split('name="csrf_token" type="hidden" value="')[1]
token = data.split('">')[0] token = data.split('"')[0]
return token return token
app, admin = setup() app, admin = setup()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment