User Roles and Permissions Explained
Key Concepts
- User Roles
- Permissions
- Role-Based Access Control (RBAC)
- Authorization
- Flask-Login
- Flask-Principal
User Roles
User roles define the categories or groups to which users belong. Each role typically represents a set of permissions and responsibilities. Common roles include Admin, Editor, User, and Guest. Roles help in managing and organizing users based on their functions within the application.
Permissions
Permissions are the specific actions or operations that users are allowed to perform. These can include actions like creating, reading, updating, and deleting resources. Permissions are assigned to roles, and users inherit these permissions based on their assigned roles.
Role-Based Access Control (RBAC)
Role-Based Access Control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise. In RBAC, access is granted to roles rather than to individual users, simplifying the management of permissions.
Authorization
Authorization is the process of determining whether a user has the necessary permissions to perform a specific action. It is the second step in the authentication and authorization process, following authentication, which verifies the user's identity.
Flask-Login
Flask-Login is a Flask extension that provides user session management. It handles the common tasks of logging in, logging out, and remembering users' sessions over extended periods. Flask-Login does not handle permissions but is often used in conjunction with other extensions to manage user roles and permissions.
from flask import Flask, redirect, url_for from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user app = Flask(__name__) app.secret_key = 'secret' login_manager = LoginManager() login_manager.init_app(app) class User(UserMixin): def __init__(self, id): self.id = id @login_manager.user_loader def load_user(user_id): return User(user_id) @app.route('/login') def login(): user = User(1) login_user(user) return redirect(url_for('protected')) @app.route('/protected') @login_required def protected(): return 'Logged in as: ' + str(current_user.id) @app.route('/logout') @login_required def logout(): logout_user() return 'Logged out' if __name__ == '__main__': app.run(debug=True)
Flask-Principal
Flask-Principal is a Flask extension that provides role-based permissions. It allows you to define permissions and roles and then check these permissions in your views. Flask-Principal integrates well with Flask-Login to provide a complete solution for authentication and authorization.
from flask import Flask, abort from flask_principal import Principal, Permission, RoleNeed app = Flask(__name__) app.secret_key = 'secret' principals = Principal(app) admin_permission = Permission(RoleNeed('admin')) @app.route('/admin') @admin_permission.require(http_exception=403) def admin(): return 'Admin page' if __name__ == '__main__': app.run(debug=True)
Example: Managing User Roles and Permissions
Imagine a blog application where there are three roles: Admin, Editor, and User. The Admin can create, read, update, and delete posts. The Editor can create and update posts but cannot delete them. The User can only read posts.
from flask import Flask, abort from flask_login import LoginManager, UserMixin, login_required from flask_principal import Principal, Permission, RoleNeed app = Flask(__name__) app.secret_key = 'secret' login_manager = LoginManager() login_manager.init_app(app) principals = Principal(app) admin_permission = Permission(RoleNeed('admin')) editor_permission = Permission(RoleNeed('editor')) user_permission = Permission(RoleNeed('user')) class User(UserMixin): def __init__(self, id, roles): self.id = id self.roles = roles @login_manager.user_loader def load_user(user_id): roles = ['user'] if user_id == '1': roles = ['admin'] elif user_id == '2': roles = ['editor'] return User(user_id, roles) @app.route('/admin') @login_required @admin_permission.require(http_exception=403) def admin(): return 'Admin page' @app.route('/editor') @login_required @editor_permission.require(http_exception=403) def editor(): return 'Editor page' @app.route('/user') @login_required @user_permission.require(http_exception=403) def user(): return 'User page' if __name__ == '__main__': app.run(debug=True)