Implementing Flask-Login with multiple User Classes Implementing Flask-Login with multiple User Classes flask flask

Implementing Flask-Login with multiple User Classes


You can define each User with a specific role. For example, user 'x' can be SCHOOL while user 'y' can be 'STAFF'.

class User(db.Model):    __tablename__ = 'User'    id = db.Column(db.Integer,primary_key=True)    username = db.Column(db.String(80),unique=True)    pwd_hash = db.Column(db.String(200))    email = db.Column(db.String(256),unique=True)    is_active = db.Column(db.Boolean,default=False)    urole = db.Column(db.String(80))    def __init__(self,username,pwd_hash,email,is_active,urole):            self.username = username            self.pwd_hash = pwd_hash            self.email = email            self.is_active = is_active            self.urole = urole    def get_id(self):            return self.id    def is_active(self):            return self.is_active    def activate_user(self):            self.is_active = True             def get_username(self):            return self.username    def get_urole(self):            return self.urole

Flask-login however does not have the concept of user roles yet and I wrote my own version of login_required decorator to override that. So you might want to use something like:

def login_required(role="ANY"):    def wrapper(fn):        @wraps(fn)        def decorated_view(*args, **kwargs):            if not current_user.is_authenticated():               return current_app.login_manager.unauthorized()            urole = current_app.login_manager.reload_user().get_urole()            if ( (urole != role) and (role != "ANY")):                return current_app.login_manager.unauthorized()                  return fn(*args, **kwargs)        return decorated_view    return wrapper

Then, you can use this decorator on a view function like:

@app.route('/school/')@login_required(role="SCHOOL")def restricted_view_for_school():    pass


@codegeek i found this very useful, thanks. I had to modify the code a bit to get it working for me, so i figured i'd drop it here in case it can help anyone else:

from functools import wrapslogin_manager = LoginManager()...def login_required(role="ANY"):    def wrapper(fn):        @wraps(fn)        def decorated_view(*args, **kwargs):            if not current_user.is_authenticated():              return login_manager.unauthorized()            if ((current_user.role != role) and (role != "ANY")):                return login_manager.unauthorized()            return fn(*args, **kwargs)        return decorated_view    return wrapper


This is an example of what you could do. I don't have experience using Flask-SQLAlchemy, but the how shouldn't be much more different. The example below uses SQLAlchemy directly.

First you define a user class that inherits from Base so that it can be mapped by ORM (Declarative)

class User(Base):    __tablename__ = 'user_table'    id = Column(Integer, primary_key=True)    email = Column(String(45), unique=True)    name = Column(String(45))    pwd = Column(String(8))    user_role = Column(String(15))    __mapper_args__ = {        'polymorphic_identity': 'user_table',        'polymorphic_on': user_role    }

Once your parent class class is ready, set a different class for each of the roles that you want to have.

class SchoolAccount(User):    __tablename__ = 'school_account'    id = Column(Integer, ForeignKey('user_table.id'), primary_key=True)    representative_name = Column(String(45))    __mapper_args__ = {        'polymorphic_identity': 'school_account'    } 

Using Flask-Login you login the user and limit access based on roles.

Here is an example of a login system with two different roles. This is a nice tutorial for flask, flask-sqlalchemy, flask-login: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins