Admin-based Access Role - Change Role-Based Access

I gave an auth-flask-Admin example from here and modified it a bit.

I added the following block to the view below, but it does not show the export button. I expected it to add an export option to admin views. It prints ---superuser on the console.

  if current_user.has_role('superuser'): can_export = True print ' ---- superuser ' 

I used the export function many times before. It will work if I put the can_export = True statement just below the class MyModelView(sqla.ModelView): I use this as an example of access control for creating / editing / etc based on a user role. For example, I want to have the readonly role, where can_create = False, can_edit = False, etc.

Can anyone help? Can someone tell me what I am doing wrong?

==

This is the whole view.

 # Create customized model view class class MyModelView(sqla.ModelView): def is_accessible(self): if not current_user.is_active or not current_user.is_authenticated: return False if current_user.has_role('superuser'): return True return False def _handle_view(self, name, **kwargs): """ Override builtin _handle_view in order to redirect users when a view is not accessible. """ if current_user.has_role('superuser'): can_export = True print ' ---- superuser ' if not self.is_accessible(): if current_user.is_authenticated: # permission denied abort(403) else: # login return redirect(url_for('security.login', next=request.url)) 

==

For reference: I put all the code here .

+6
source share
2 answers

In the @dirn comment above, adding self. fixed it.

 self.can_export = True 

Thanks @dirn

0
source

To continue further, I continued to use the auth example as the base at the top and added some simple role-based access control functions. Hope this can help someone.

Full code here . If you see something here that is not good RBAC practice, I would like to hear about it.

Main app.py file:

 import os from flask import Flask, url_for, redirect, render_template, request, abort from flask_sqlalchemy import SQLAlchemy from flask_security import Security, SQLAlchemyUserDatastore, \ UserMixin, RoleMixin, login_required, current_user from flask_security.utils import encrypt_password import flask_admin from flask_admin.contrib import sqla from flask_admin import helpers as admin_helpers # Create Flask application app = Flask(__name__) app.config.from_pyfile('config.py') db = SQLAlchemy(app) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Define models directly without reflection... class Customer(db.Model): CustomerId = db.Column(db.Integer(), primary_key=True) FirstName = db.Column(db.Unicode(40), nullable=False) LastName = db.Column(db.String(20), nullable=False) City = db.Column(db.Unicode(40)) Email = db.Column(db.Unicode(60), unique = True) def __str__(self): return self.CustomerID class City(db.Model): Id = db.Column(db.Integer(), primary_key=True) City = db.Column(db.Unicode(40), unique = True) def __str__(self): return self.ID #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Define models roles_users = db.Table( 'roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), db.Column('role_id', db.Integer(), db.ForeignKey('role.id')) ) class Role(db.Model, RoleMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) def __str__(self): return self.name class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) first_name = db.Column(db.String(255)) last_name = db.Column(db.String(255)) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) confirmed_at = db.Column(db.DateTime()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) def __str__(self): return self.email # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(app, user_datastore) # Flask views @app.route('/') def index(): return render_template('index.html') # Create customized model view class class dgBaseView(sqla.ModelView): column_display_pk = True page_size = 20 can_view_details = True #can_export = False can_export = True def _handle_view(self, name, **kwargs): """ Override builtin _handle_view in order to redirect users when a view is not accessible. """ if not self.is_accessible(): if current_user.is_authenticated: # permission denied abort(403) else: # login return redirect(url_for('security.login', next=request.url)) class regularRbacView(dgBaseView): def is_accessible(self): # set accessibility... if not current_user.is_active or not current_user.is_authenticated: return False # roles not tied to ascending permissions... if not current_user.has_role('export'): self.can_export = False # roles with ascending permissions... if current_user.has_role('adminrole'): self.can_create = True self.can_edit = True self.can_delete = True self.can_export = True return True if current_user.has_role('supervisor'): self.can_create = True self.can_edit = True self.can_delete = False return True if current_user.has_role('user'): self.can_create = True self.can_edit = True self.can_delete = False return True if current_user.has_role('create'): self.can_create = True self.can_edit = False self.can_delete = False return True if current_user.has_role('read'): self.can_create = False self.can_edit = False self.can_delete = False return True return False class lookupRbacView(dgBaseView): def is_accessible(self): # set accessibility... if not current_user.is_active or not current_user.is_authenticated: return False # roles not tied to ascending permissions... if not current_user.has_role('export'): self.can_export = False # roles with ascending permissions... if current_user.has_role('adminrole'): self.can_create = True self.can_edit = True self.can_delete = True self.can_export = True return True if current_user.has_role('supervisor'): self.can_create = True self.can_edit = True self.can_delete = False return True if current_user.has_role('user'): self.can_create = False self.can_edit = False self.can_delete = False return True if current_user.has_role('create'): self.can_create = False self.can_edit = False self.can_delete = False return True if current_user.has_role('read'): self.can_create = False self.can_edit = False self.can_delete = False return True return False class SuperView(dgBaseView): can_export = True def is_accessible(self): if not current_user.is_active or not current_user.is_authenticated: return False if current_user.has_role('adminrole'): self.can_create = True self.can_edit = True self.can_delete = True #self.can_export = True return True return False # define a context processor for merging flask-admin template context into the # flask-security views. @security.context_processor def security_context_processor(): return dict( admin_base_template=admin.base_template, admin_view=admin.index_view, h=admin_helpers, ) # Create admin admin = flask_admin.Admin( app, 'Rbac RoleBasedAccess', base_template='my_master.html', template_mode='bootstrap3', ) class customer_view(regularRbacView): column_searchable_list = ['CustomerId', 'City', 'Email', 'FirstName', 'LastName',] # make sure the type of your filter matches your hybrid_property column_filters = ['FirstName', 'LastName', 'City', 'Email' ] # column_default_sort = ('part_timestamp', True) #column_export_list = ['CustomerId', 'City', 'Email', 'FirstName', 'LastName',] # Add model views admin.add_view(SuperView(Role, db.session)) admin.add_view(SuperView(User, db.session)) admin.add_view(customer_view(Customer, db.session)) admin.add_view(lookupRbacView(City, db.session)) def build_sample_db(): """ Populate a small db with some example entries. """ import string #db.drop_all() db.create_all() with app.app_context(): read_role = Role(name='read') user_role = Role(name='user') super_user_role = Role(name='adminrole') db.session.add(user_role) db.session.add(super_user_role) db.session.add(Role(name='read')) db.session.add(Role(name='create')) db.session.add(Role(name='supervisor')) db.session.add(Role(name='delete')) db.session.add(Role(name='export')) db.session.commit() test_user = user_datastore.create_user( first_name='Admin', email='admin', password=encrypt_password('admin'), roles=[user_role, super_user_role] ) first_names = [ 'read', 'create', 'user', 'suser', 'delete', 'Charlie', 'Sophie', 'Mia', ] last_names = [ 'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas', ] roles1 = [ 'read', 'create', 'user', 'supervisor', 'delete', 'read', 'read', 'read', ] for i in range(len(first_names)): tmp_email = first_names[i].lower() # initialize the users with simple password... 'a' tmp_pass = 'a' user_datastore.create_user( first_name=first_names[i], last_name=last_names[i], email=tmp_email, password=encrypt_password(tmp_pass), roles=[read_role, ] ) db.session.commit() return if __name__ == '__main__': # Build a sample db on the fly, if one does not exist yet. app_dir = os.path.realpath(os.path.dirname(__file__)) database_path = os.path.join(app_dir, app.config['DATABASE_FILE']) if not os.path.exists(database_path): build_sample_db() app.run(host='0.0.0.0', port=5000, debug=True) 

Configuration:

 # http://stackoverflow.com/questions/5055042/whats-the-best-practice-using-a-settings-file-in-python import creds # Create dummy secret key so we can use sessions SECRET_KEY = creds.cred['secretkey'] # Create in-memory database DATABASE_FILE = 'fground.sqlite' SQLALCHEMY_DATABASE_URI = creds.cred['dbspec'] + DATABASE_FILE SQLALCHEMY_ECHO = True # Flask-Security config SECURITY_URL_PREFIX = "/admin" SECURITY_PASSWORD_HASH = "pbkdf2_sha512" SECURITY_PASSWORD_SALT = creds.cred['csalt'] # Flask-Security URLs, overridden because they don't put a / at the end SECURITY_LOGIN_URL = "/login/" SECURITY_LOGOUT_URL = "/logout/" SECURITY_REGISTER_URL = "/register/" SECURITY_POST_LOGIN_VIEW = "/admin/" SECURITY_POST_LOGOUT_VIEW = "/admin/" SECURITY_POST_REGISTER_VIEW = "/admin/" # Flask-Security features SECURITY_REGISTERABLE = True SECURITY_SEND_REGISTER_EMAIL = False 

The creds.py file says:

 cred = dict( secretkey = '123232323238', dbspec = 'sqlite:///', csalt = "ATGUOHAELKiubaq3fgo8hiughaerGOJAEGj", dbu = 'user', dbp = 'pass', ) 

To run this, I recommend that you start with the auth-admin auth example above, and then copy these files to this example. The launch should create a database with users and roles. Alternatively, you can get all the code ready to go to the github link.

+8
source

Source: https://habr.com/ru/post/1245745/


All Articles