This team teach will show you how to add roles to users when they create their account
Roles can be used in your code to restrict access to certain actions and pages
class User(db.Model):
# ... (existing code)
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# Goes into your users.py file. This will create a column dedicated for roles
_role = db.Column(db.String(20), default="User", nullable=False)
#-------------------------------------------------------------------------------------------------------------------------------------------------#
def __init__(self, name, uid, password="123qwerty", dob=date.today(), role="User"):
# ... (existing code)
self._role = role
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# With this property, you can access the user's role using user_instance.role instead of user_instance._role.
@property
def role(self):
return self._role
#-------------------------------------------------------------------------------------------------------------------------------------------------#
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# With this setter, you can update the user's role using the assignment syntax: user_instance.role = "NewRole".
@role.setter
def role(self, role):
self._role = role
#-------------------------------------------------------------------------------------------------------------------------------------------------#
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# This method returns True if the user's role is "Admin" and False otherwise.
def is_admin(self):
return self._role == "Admin"
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# ... (existing code)
# CRUD read converts self to dictionary
# returns dictionary
def read(self):
return {
"id": self.id,
"name": self.name,
"uid": self.uid,
"dob": self.dob,
"age": self.age,
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# When you GET/read the endpoint, it will also return the user's role
"role": self.role,
#-------------------------------------------------------------------------------------------------------------------------------------------------#
"posts": [post.read() for post in self.posts]
}
Popcorn Hack 1: What is the function of CRUD read (Check comments)? Answer:
def initUsers():
with app.app_context():
"""Create database and tables"""
db.create_all()
"""Tester data for table"""
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# When you create the test users for the database, you can add a role for them. In this case, Thomas Edison has the role "Admin"
u1 = User(name='Thomas Edison', uid='toby', password='123toby', dob=date(1847, 2, 11), role="Admin")
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# ... (existing code)
class _Security(Resource):
def post(self):
try:
body = request.get_json()
if not body:
return {
"message": "Please provide user details", #After attempting to retrieve JSON data, this block checks if the body is empty or None.
#If there's no JSON data in the request, the function returns a JSON response indicating that the user should provide user details, along with a status code of 400 (Bad Request).
#This is a common practice to handle cases where the expected data is missing or improperly formatted.
"data": None,
"error": "Bad request"
}, 400
''' Get Data '''
uid = body.get('uid') #checks for UID
if uid is None:
return {'message': f'User ID is missing'}, 400
password = body.get('password') #checks and looks if possible password is there.
''' Find user '''
user = User.query.filter_by(_uid=uid).first()
if user is None or not user.is_password(password):
return {'message': f"Invalid user id or password"}, 400
if user:
try:
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# The only change you're making is that you include the user's role when they get authenticated
token_payload = {
"_uid": user._uid,
"role": user.role # Add the role information to the token
}
#-------------------------------------------------------------------------------------------------------------------------------------------------#
token = jwt.encode(
token_payload,
current_app.config["SECRET_KEY"],
algorithm="HS256"
)
# ... (existing code)
from functools import wraps
import jwt
from flask import request, abort
from flask import current_app
from model.users import User
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# Whenver you call this function in your code, you can add an argument like Roles="Admin" to only allow admins to access a certan part.
def token_required(roles=None):
#-------------------------------------------------------------------------------------------------------------------------------------------------#
def decorator(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.cookies.get("jwt")
if not token:
return {
"message": "Authentication Token is missing!",
"data": None,
"error": "Unauthorized"
}, 401
try:
data = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
current_user = User.query.filter_by(_uid=data["_uid"]).first()
if current_user is None:
return {
"message": "Invalid Authentication token!",
"data": None,
"error": "Unauthorized"
}, 401
#-------------------------------------------------------------------------------------------------------------------------------------------------#
# Check if roles are provided and user has the required role
if roles and current_user.role not in roles:
return {
"message": "Insufficient permissions. Required roles: {}".format(roles),
"data": None,
"error": "Forbidden"
}, 403
#-------------------------------------------------------------------------------------------------------------------------------------------------#
except Exception as e:
return {
"message": "Something went wrong",
"data": None,
"error": str(e)
}, 500
return f(current_user, *args, **kwargs)
return decorated
return decorator
Popcorn Hack 2: What is the purpose of “def token_required(roles=None):” ? Answer: