enable ACLs - users and roles
This commit is contained in:
parent
93cee58cfb
commit
61743a5050
1
bootstrap/data_static/Role.csv
Normal file
1
bootstrap/data_static/Role.csv
Normal file
@ -0,0 +1 @@
|
|||||||
|
name
|
|
1
bootstrap/data_static/User.csv
Normal file
1
bootstrap/data_static/User.csv
Normal file
@ -0,0 +1 @@
|
|||||||
|
email,password,role_names
|
|
@ -0,0 +1,2 @@
|
|||||||
|
Role
|
||||||
|
User
|
@ -13,6 +13,7 @@ from flask_migrate import upgrade as migrate_upgrade
|
|||||||
from flask_migrate import init as migrate_init
|
from flask_migrate import init as migrate_init
|
||||||
from flask_security import RoleMixin, UserMixin
|
from flask_security import RoleMixin, UserMixin
|
||||||
from flask_security import Security, SQLAlchemyUserDatastore
|
from flask_security import Security, SQLAlchemyUserDatastore
|
||||||
|
from flask_security.utils import encrypt_password, hash_password
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from markupsafe import escape, Markup
|
from markupsafe import escape, Markup
|
||||||
from sqlalchemy import Boolean
|
from sqlalchemy import Boolean
|
||||||
@ -266,15 +267,38 @@ def init_db(app):
|
|||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
SENSITIVE_PREFIX = "__SENSITIVE__."
|
||||||
|
|
||||||
|
|
||||||
def populate_static(app):
|
def populate_static(app):
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
models = import_module("webapp.models")
|
models = import_module("webapp.models")
|
||||||
|
sensitive = import_module("sensitive")
|
||||||
ordered_model_names = order_from_process_order('csv', STATIC_DATA_DIR)
|
ordered_model_names = order_from_process_order('csv', STATIC_DATA_DIR)
|
||||||
for model_name in ordered_model_names:
|
for model_name in ordered_model_names:
|
||||||
|
if model_name in ['User', 'Role']:
|
||||||
|
model = eval(model_name)
|
||||||
|
else:
|
||||||
model = getattr(models, model_name)
|
model = getattr(models, model_name)
|
||||||
with open(os.path.join(STATIC_DATA_DIR, "{}.csv".format(model_name))) as f:
|
with open(os.path.join(STATIC_DATA_DIR, "{}.csv".format(model_name))) as f:
|
||||||
reader = csv.DictReader(f)
|
reader = csv.DictReader(f)
|
||||||
for row in reader:
|
for row in reader:
|
||||||
|
row_updates = dict()
|
||||||
|
for key, value in row.items():
|
||||||
|
if value.startswith(SENSITIVE_PREFIX):
|
||||||
|
sensitive_key = SENSITIVE_PREFIX.join(value.split(SENSITIVE_PREFIX)[1:])
|
||||||
|
sensitive_value = getattr(sensitive, sensitive_key)
|
||||||
|
row_updates[key] = sensitive_value
|
||||||
|
if row_updates:
|
||||||
|
row.update(row_updates)
|
||||||
|
if model_name == "User":
|
||||||
|
role_names = row.pop('role_names')
|
||||||
|
row['password'] = hash_password(row['password'])
|
||||||
|
user = user_datastore.create_user(**row)
|
||||||
|
for role_name in role_names.split(';'):
|
||||||
|
role = Role.query.filter_by(name=role_name).first()
|
||||||
|
user_datastore.add_role_to_user(user, role)
|
||||||
|
else:
|
||||||
instance = model(**row)
|
instance = model(**row)
|
||||||
db.session.add(instance)
|
db.session.add(instance)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import importlib
|
import importlib
|
||||||
from copy import deepcopy, copy
|
from copy import copy
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
import inflect
|
import inflect
|
||||||
from flask import flash, render_template, redirect, request, url_for, jsonify
|
from flask import flash, render_template, redirect, request, url_for, jsonify
|
||||||
|
from flask_security import login_required, roles_required
|
||||||
|
|
||||||
from oshipka.persistance import db
|
from oshipka.persistance import db
|
||||||
from oshipka.util.strings import camel_case_to_snake_case
|
from oshipka.util.strings import camel_case_to_snake_case
|
||||||
@ -172,8 +173,9 @@ class ViewContext(object):
|
|||||||
self.redirect_next = None
|
self.redirect_next = None
|
||||||
|
|
||||||
|
|
||||||
def create_view(model_view, view_context, **kwargs):
|
def create_view(model_view, view_context, is_login_required=False, the_roles_required=None, **kwargs):
|
||||||
view_context.model_view = model_view
|
view_context.model_view = model_view
|
||||||
|
the_roles_required = [] if not the_roles_required else the_roles_required
|
||||||
|
|
||||||
def return_json_or_template():
|
def return_json_or_template():
|
||||||
if view_context.is_json:
|
if view_context.is_json:
|
||||||
@ -212,6 +214,10 @@ def create_view(model_view, view_context, **kwargs):
|
|||||||
return view_context.redirect_func(view_context)
|
return view_context.redirect_func(view_context)
|
||||||
|
|
||||||
return return_json_or_template()
|
return return_json_or_template()
|
||||||
|
if is_login_required:
|
||||||
|
if the_roles_required:
|
||||||
|
inner = roles_required(*the_roles_required)(inner)
|
||||||
|
return login_required(inner)
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
@ -269,7 +275,7 @@ def catch_flash(f):
|
|||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
flash(str(e), "error")
|
flash(str(e), "error")
|
||||||
serialized_form = serialize_form()
|
serialized_form = {k: v for k, v in request.form.items()}
|
||||||
if '_next' in serialized_form:
|
if '_next' in serialized_form:
|
||||||
_next = serialized_form.pop('_next')
|
_next = serialized_form.pop('_next')
|
||||||
elif request.referrer and request.referrer != request.path:
|
elif request.referrer and request.referrer != request.path:
|
||||||
|
@ -10,10 +10,12 @@ from webapp.models import [[ name ]]
|
|||||||
from webapp.routes.[[ name|camel_to_snake ]]_hooks import *
|
from webapp.routes.[[ name|camel_to_snake ]]_hooks import *
|
||||||
|
|
||||||
[[ name|camel_to_snake ]] = ModelView(app, [[name]])
|
[[ name|camel_to_snake ]] = ModelView(app, [[name]])
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=get_view_context, verb="get", per_item=True)
|
[% for verb, verb_values in _verbs.items() %]
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=list_view_context, verb="list")
|
[[ name|camel_to_snake ]].register_verb(view_context=[[ verb ]]_view_context,
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=table_view_context, verb="table")
|
verb="[[ verb ]]",
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=search_view_context, verb="search")
|
methods=[[ verb_values.methods ]],
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=create_view_context, verb="create", methods=["GET", "POST"])
|
per_item=[[ verb_values.per_item ]],
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=update_view_context, verb="update", methods=["GET", "POST"], per_item=True)
|
is_login_required=[[ verb_values.is_login_required if verb_values.is_login_required else 'False' ]],
|
||||||
[[ name|camel_to_snake ]].register_verb(view_context=delete_view_context, verb="delete", methods=["GET", "POST"] , per_item=True)
|
the_roles_required=[[ verb_values.the_roles_required if verb_values.the_roles_required else '[]' ]],
|
||||||
|
)
|
||||||
|
[% endfor %]
|
||||||
|
@ -37,6 +37,38 @@ def process_secondary(view_model, column_name):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERBS = {
|
||||||
|
'get': {
|
||||||
|
'per_item': 'True',
|
||||||
|
'methods': ['GET'],
|
||||||
|
},
|
||||||
|
'list': {
|
||||||
|
'per_item': 'False',
|
||||||
|
'methods': ['GET'],
|
||||||
|
},
|
||||||
|
'table': {
|
||||||
|
'per_item': 'False',
|
||||||
|
'methods': ['GET'],
|
||||||
|
},
|
||||||
|
'search': {
|
||||||
|
'per_item': 'False',
|
||||||
|
'methods': ['GET'],
|
||||||
|
},
|
||||||
|
'create': {
|
||||||
|
'per_item': 'False',
|
||||||
|
'methods': ['GET', 'POST'],
|
||||||
|
},
|
||||||
|
'update': {
|
||||||
|
'per_item': 'True',
|
||||||
|
'methods': ['GET', 'POST'],
|
||||||
|
},
|
||||||
|
'delete': {
|
||||||
|
'per_item': 'True',
|
||||||
|
'methods': ['GET', 'POST'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def enrich_view_model(view_model):
|
def enrich_view_model(view_model):
|
||||||
columns = []
|
columns = []
|
||||||
for column in view_model.get('columns', {}):
|
for column in view_model.get('columns', {}):
|
||||||
@ -48,6 +80,8 @@ def enrich_view_model(view_model):
|
|||||||
_column_type = 'db.Integer'
|
_column_type = 'db.Integer'
|
||||||
elif column_type in ['bool', ] or column_name.startswith('is_'):
|
elif column_type in ['bool', ] or column_name.startswith('is_'):
|
||||||
_column_type = 'LiberalBoolean'
|
_column_type = 'LiberalBoolean'
|
||||||
|
elif column_type in ['datetime', ] or column_name.endswith('_dt'):
|
||||||
|
_column_type = 'db.UnicodeText'
|
||||||
elif column_type in ['relationship', ]:
|
elif column_type in ['relationship', ]:
|
||||||
_column_type = 'relationship'
|
_column_type = 'relationship'
|
||||||
multiple = column.get('multiple')
|
multiple = column.get('multiple')
|
||||||
@ -68,6 +102,25 @@ def enrich_view_model(view_model):
|
|||||||
column.update({'_type': _column_type})
|
column.update({'_type': _column_type})
|
||||||
columns.append(column)
|
columns.append(column)
|
||||||
view_model['columns'] = columns
|
view_model['columns'] = columns
|
||||||
|
|
||||||
|
view_model['_verbs'] = {}
|
||||||
|
for verb, verb_default in VERBS.items():
|
||||||
|
view_model['_verbs'][verb] = verb_default
|
||||||
|
|
||||||
|
access = view_model.get('access')
|
||||||
|
if access:
|
||||||
|
for acl in access:
|
||||||
|
verb = acl.get('verb')
|
||||||
|
if verb == 'all':
|
||||||
|
for verb in VERBS:
|
||||||
|
view_model['_verbs'][verb]['is_login_required'] = acl.get('login_required')
|
||||||
|
view_model['_verbs'][verb]['the_roles_required'] = acl.get('roles_required')
|
||||||
|
else:
|
||||||
|
is_login_required = acl.get('login_required')
|
||||||
|
if is_login_required is False: # overrides all
|
||||||
|
view_model['_verbs'][verb]['the_roles_required'] = acl.get('login_required')
|
||||||
|
view_model['_verbs'][verb]['is_login_required'] = is_login_required
|
||||||
|
view_model['_verbs'][verb]['the_roles_required'] = acl.get('roles_required')
|
||||||
return view_model
|
return view_model
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user