sandman2
sandman2 copied to clipboard
Add role based security or any kind of access control
Interesting project, but I can not find any hint about how to control access to data, also the documentation does not provide any concept regarding data security.
Some kind of access control system seems like a very basic requirement for any data access software - is this something that is planned for the future?
This would be a killer feature. Currently using nginx as a proxy.
If one cracks open the code one finds the following for the create application method
def get_app(
database_uri,
exclude_tables=None,
user_models=None,
reflect_all=True,
read_only=False,
schema=None):
"""..."""
app = Flask('sandman2')
app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
app.config['SANDMAN2_READ_ONLY'] = read_only
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.classes = []
db.init_app(app)
admin = Admin(app, base_template='layout.html', template_mode='bootstrap3')
_register_error_handlers(app)
if user_models:
with app.app_context():
_register_user_models(user_models, admin, schema=schema)
elif reflect_all:
with app.app_context():
_reflect_all(exclude_tables, admin, read_only, schema=schema)
@app.route('/')
def index():
"""Return a list of routes to the registered classes."""
routes = {}
for cls in app.classes:
routes[cls.__model__.__name__] = '{}{{/{}}}'.format(
cls.__model__.__url__,
cls.__model__.primary_key())
return jsonify(routes)
return app
Which one can restructure as follows
def create_app(
database_uri,
exclude_tables=None,
user_models=None,
reflect_all=True,
read_only=False,
schema=None):
app = Flask('sandman2')
app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
app.config['SANDMAN2_READ_ONLY'] = read_only
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.classes = []
sandman(
application,
database_uri,
exclude_tables=None,
user_models=None,
reflect_all=True,
read_only=False,
schema=None)
def sandman(
application,
database_uri,
exclude_tables=None,
user_models=None,
reflect_all=True,
read_only=False,
schema=None):
"""..."""
db.init_app(application)
admin = Admin(application, base_template='layout.html', template_mode='bootstrap3')
_register_error_handlers(application)
if user_models:
with application.app_context():
_register_user_models(user_models, admin, schema=schema)
elif reflect_all:
with application.app_context():
_reflect_all(exclude_tables, admin, read_only, schema=schema)
@application.route('/')
def index():
"""Return a list of routes to the registered classes."""
routes = {}
for cls in application.classes:
routes[cls.__model__.__name__] = '{}{{/{}}}'.format(
cls.__model__.__url__,
cls.__model__.primary_key())
return jsonify(routes)
Once this is done it becomes rather trivial to add security to the application.
from flask_jwt_extended import JWTManager
def create_app(
database_uri,
exclude_tables=None,
user_models=None,
reflect_all=True,
read_only=False,
schema=None):
app = Flask('sandman2')
app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
app.config['SANDMAN2_READ_ONLY'] = read_only
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.classes = []
jwt = JWTManager(app)
sandman(
application,
database_uri,
exclude_tables=None,
user_models=None,
reflect_all=True,
read_only=False,
schema=None)
Then add the endpoints one wants as necessary. Similarly it is possible to secure ones administration interface by adding say Flask-Login
but one must also then subclass the AdminView
and AdminIndexView
and pass these through the the Admin
invocation in the "new" sandman
method.
I have submitted a PR that already does this refactoring and am awaiting its acceptance.
Yes, authentication is a must. I believe sandman1
had it. Was expecting sandman2
to do it better... not less... But I as a beggar cannot be a boss. But we can choose another approach, such as dreamfactory. Will start playing with that now... hopefully it's not crazy hard to setup.
@zeluspudding My example above was meant to illustrate that forcing a security solution upon the user is unnecessary and that, with minor refactoring of the code, it becomes trivial for persons using the library to set this up.
To setup security layer for the interim one need only copy the create_app
/get_app
code and extend it yourself, as I have above. There are multiple libraries that deal with this e.g. flask_jwt, flask_jwt_extended, flask-login and the like.
@jeffknupp When my PR is accepted/rejected I will push up my documentation for the changes and I can happily document the methods by which security can be added.