Reputation: 563
now i write the flask login application using flask_login
library and in this part is work fine, but now what i want is how can i specify the user who can access or not access to the route, and this is my code.
from flask import Flask, render_template, url_for, request, redirect
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_required, login_user, current_user, logout_user
app = Flask(__name__)
app.config['SECRET_KEY'] = 'thisissecretekey'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sites.db'
db = SQLAlchemy(app)
login_manager = LoginManager(app)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
# ----------- Database Tables -------------
class User(db.Model, UserMixin):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(50), unique=True)
password = db.Column(db.String(40))
role_code = db.Column(db.String(30), db.ForeignKey('roles.role_code'))
def get_id(self):
return (self.id)
class Roles(db.Model, UserMixin):
__tablename__ = 'roles'
role_code = db.Column(db.String(40), primary_key = True)
role_name = db.Column(db.String(50))
# --------------- Routes ----------------
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
if request.method == "POST":
username = request.form['username']
password = request.form['password']
user = User.query.filter(User.username == username).first()
if user and password == user.password:
login_user(user)
return redirect(url_for('index'))
else:
return redirect(url_for('login'))
return render_template('login.html')
@app.route('/index')
@login_required
def index():
return render_template('index.html')
@app.route('/logout', methods=['GET', 'POST'])
def logout():
logout_user()
return redirect(url_for('login'))
if __name__ == '__main__':
app.run(debug=True)
For example i have this data in database.
Roles table
Roles(role_code='a', role_name='Admin')
Roles(role_code='o', role_name='Operator')
User table
User(username='tom', password='pass', role_code='a')
User(username='frank', password='pass', role_code='e')
If i want specify the /index
route can only access by user who have role_code
equal to a
or Admin
, what is the best way can i do that?
Upvotes: 1
Views: 3402
Reputation: 4269
flask-login
provides @login_required
decorator so you need to create your own @admin_required
decorator, the code below is taken from flask-base
a starter project (github repo )
[..]
from functools import wraps
[..]
class Permission:
GENERAL = 0x01
ADMINISTER = 0xff
[..]
def permission_required(permission):
"""Restrict a view to users with the given permission."""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.can(permission):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
def admin_required(f):
return permission_required(Permission.ADMINISTER)(f)
then you can decorate /index
route with @admin_required
, please note the order how to call decorators:
@app.route('/index')
@login_required
@admin_required
def index():
return render_template('index.html')
and in your template:
<table class="ui compact definition table">
<tr><td>Full name</td><td>{{ '%s %s' % (user.first_name, user.last_name) }}</td></tr>
<tr><td>Email address</td><td>{{ user.email }}</td></tr>
<tr><td>Account type</td><td>{{ user.role.name }}</td></tr>
</table>
Upvotes: 3