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
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:
git clone https://codeberg.org/Elhasnaouymed/flask-roleman.git
cd flask-roleman
python setup.py sdist
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, withsecondary=RoleMan.SECONDARY_USER_GROUP_TABLE_NAME
andbackref="groups"
.roles
: many-to-many relationship to the Roles model, withsecondary=RoleMan.SECONDARY_GROUP_ROLE_TABLE_NAME
andbackref="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
Built Distribution
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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1f9b84d8e2919aa2161d7d1b88f4339eb2c813125374b1ed856e6c8e9bb8e77b |
|
MD5 | bd774126b998b03d2e5b1bbf47130265 |
|
BLAKE2b-256 | 0957a27ce246bf5a99eff187c72745d3455c6bd6139d5424668d343082d297a3 |
File details
Details for the file flask_roleman-1.0.3-py3-none-any.whl
.
File metadata
- Download URL: flask_roleman-1.0.3-py3-none-any.whl
- Upload date:
- Size: 6.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.12.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0078fa2619533fc94addde3b2452fcf358228d0c7d8bd33309231da76ed5c176 |
|
MD5 | 954c16e286615e64e11fa92b2f4b8a78 |
|
BLAKE2b-256 | 0fbc5ab14931786b964ce3e9b5cd2c358d2fe19881d5f48b47936aa43e6319cc |