Skip to main content

Flask Extension for User Authorizations, Users can have Groups, and Each Group can have Roles, more control and easy to use.

Project description

This Software is in Beta Version, Please place an issue or contact me if you found a Bug !

Flask-Roleman

flask-roleman is a flask extension for User Authorizations, Users can have Groups, and Each Group can have Roles, you can define your Groups Model and Roles Model, as well as Users Model.

About

  • Dependencies: flask flask-login, flask-sqlalchemy
  • License: Open Source Under GNU GPL v2
  • Author: Mohamed El-Hasnaouy codeberg.org/elhasnaouymed

Live Example

Jump to live example

Install

Using PIP

You can install flask-roleman using pip:

pip install flask-roleman

From source

Or you can download & compile & install it from source:

  1. git clone https://codeberg.org/Elhasnaouymed/flask-roleman.git
  2. cd flask-roleman
  3. python setup.py sdist
  4. pip install dist/flask-roleman-*.tar.gz

Note: on most GNU/Linux distributions, You can install only inside a Virtual Environment (see PEP 0668)

Initialization

As most Extensions of Flask, you first import and create the Main Instance, then you can Initialize it in place or after:

...

db = SQLAlchemy()
roleman = RoleMan()

...

roleman.init_db(db, create_secondaries=True)

...

But before initialization, you must define the three models to inherit from their mixing, as shown in the next section.

also you should initialize before db.init_app() to allow secondary tables to be created.

Mixing

To use RoleMan in your project, you need to have:

  • User Model that inherits from flask_roleman.UserModelMixing.
  • Group Model that inherits from flask_roleman.GroupModelMixing.
  • Role Model that inherits from flask_roleman.RoleModelMixing.

Group Model must have:

  • A String column name.
  • users: many-to-many relationship to the Users model, with secondary=RoleMan.SECONDARY_USER_GROUP_TABLE_NAME and backref="groups".
  • roles: many-to-many relationship to the Roles model, with secondary=RoleMan.SECONDARY_GROUP_ROLE_TABLE_NAME and backref="groups".

Role Model must have:

  • A String column name.

Minimal Example

Minimal Example of defining the three necessary Models with their Inheritance:

from flask_roleman import RoleMan, UserModelMixing, GroupModelMixing, RoleModelMixing

class User(db.Model, UserModelMixing):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String, nullable=False, unique=True)
    password = db.Column(db.String, nullable=False)
    ...

class Group(db.Model, GroupModelMixing):
    __tablename__ = 'group'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False, unique=True)
    users = db.relationship('User', secondary=RoleMan.SECONDARY_USER_GROUP_TABLE_NAME, backref="groups")
    roles = db.relationship('Role', secondary=RoleMan.SECONDARY_GROUP_ROLE_TABLE_NAME, backref="groups")
    ...
    
class Role(db.Model, RoleModelMixing):
    __tablename__ = 'role'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False, unique=True)
    ...

Usage

There are two ways to use this tool, One by decorating the route you want to protect, Two is by using .has_roles() method over a User or a Group

Both methods take variable length argument *roles=Tuple[Union[List[str], str]], you can pass a list of roles like ['admin', 'manager', 'chief'] or just a role name as string like 'admin'

  • by passing a list, the User must have at least one of the Roles
  • by passing a string, the User must have that Role

In other words: the program performs AND operator over the method arguments, and OR over the list values.

Notes

You should assign Roles to Groups, and Groups to the Users.

The user get Authorized only if he has at least one of the Requested roles bound to one of his Groups.

Static Authorizing

Whenever you want to Require a role from User, use this Decorator:

from flask_roleman import roles_required

@app.route('/admin')
@roles_required('admin')
def admin_page():
    ...
    return render_template('admin.html')

Dynamic Authorizing

Or you can check dynamically using current_user.has_roles:

from flask_login import current_user
from flask import abort

@app.route('/admin')
def admin_page():
    if not current_user.has_roles('admin'):
        return abort(401)
    return render_template('admin.html')

The Live Example

In This example, the user will always get 401 error when accessing /admin, until he logs in with a user that has the 'admin' role in one of his groups

from flask import Flask
from flask_login import LoginManager
from flask_roleman import RoleMan, UserModelMixing, GroupModelMixing, RoleModelMixing, roles_required
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SECRET_KEY'] = '5d19362626f3290221a2b37f0a5038d07e5aa0e18a9967ffcbedc69eaee4cce9'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.db'
db = SQLAlchemy()
login_manager = LoginManager(app)


@login_manager.user_loader
def user_loader(id: int):
    return User.query.get(id)


class User(db.Model, UserModelMixing):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String, nullable=False, unique=True)
    password = db.Column(db.String, nullable=False)


class Group(db.Model, GroupModelMixing):
    __tablename__ = 'group'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False, unique=True)
    users = db.relationship('User', secondary=RoleMan.SECONDARY_USER_GROUP_TABLE_NAME, backref="groups")
    roles = db.relationship('Role', secondary=RoleMan.SECONDARY_GROUP_ROLE_TABLE_NAME, backref="groups")


class Role(db.Model, RoleModelMixing):
    __tablename__ = 'role'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False, unique=True)


@app.route('/')
def home():
    return 'Hello World! from Home'

@app.route('/admin')
@roles_required('admin')
def admin():
    return 'Admin Page !!!'


if __name__ == '__main__':
    app.run(debug=True)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flask_roleman-1.0.3.tar.gz (5.7 kB view details)

Uploaded Source

Built Distribution

flask_roleman-1.0.3-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file flask_roleman-1.0.3.tar.gz.

File metadata

  • Download URL: flask_roleman-1.0.3.tar.gz
  • Upload date:
  • Size: 5.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.12.5

File hashes

Hashes for flask_roleman-1.0.3.tar.gz
Algorithm Hash digest
SHA256 1f9b84d8e2919aa2161d7d1b88f4339eb2c813125374b1ed856e6c8e9bb8e77b
MD5 bd774126b998b03d2e5b1bbf47130265
BLAKE2b-256 0957a27ce246bf5a99eff187c72745d3455c6bd6139d5424668d343082d297a3

See more details on using hashes here.

File details

Details for the file flask_roleman-1.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for flask_roleman-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 0078fa2619533fc94addde3b2452fcf358228d0c7d8bd33309231da76ed5c176
MD5 954c16e286615e64e11fa92b2f4b8a78
BLAKE2b-256 0fbc5ab14931786b964ce3e9b5cd2c358d2fe19881d5f48b47936aa43e6319cc

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page