Start work on role guard

manzilcheck
Casu Al Snek 6 months ago
parent cc39f23efd
commit 6b0840b0c0
  1. 44
      backend/app.py
  2. 8
      backend/db/model.py
  3. 39
      backend/utils/auth.py

@ -10,6 +10,7 @@ from flask import jsonify
import uuid
from datetime import datetime
from constants import UserRole
from utils.utils import random_string_generator, hash_string
from blueprints.profile import profile as profileBlueprint
@ -24,9 +25,8 @@ app.register_blueprint(profileBlueprint, url_prefix='/api')
def homepage():
return {'message': 'Welcome back !'}, 200
@app.route('/seed-users', methods=['GET'])
def seed_users():
@app.route('/seedData', methods=['GET'])
def seed_data():
try:
# Drop and recreate schema (only for testing, not recommended in production)
sql = text('DROP SCHEMA public CASCADE; CREATE SCHEMA public;')
@ -35,38 +35,18 @@ def seed_users():
db.create_all() # Recreate tables
# Define roles and constants (ensure UserRole.USER is an integer or map it)
default_role = UserRole.USER.value if hasattr(UserRole, 'USER') else 1
default_profile_file = "defaultUserBanner.png"
# Create seed users
users = [
User(
email=f"user{i}@example.com",
firstName=f"FirstName{i}",
lastName=f"LastName{i}",
username=f"username{i}",
hash_password=generate_password_hash("password123"),
pfpFilename=default_profile_file,
joinedDate=datetime.utcnow(),
lastOnline=datetime.utcnow(),
bio=f"This is user{i}'s bio.",
role=default_role,
isActivated=True,
sessions=[],
user_badges=[],
enrollments=[],
quizzes=[],
quiz_attempts=[],
chats=[],
notifications=[]
)
for i in range(1, 6)
]
# Add users to the database
users = [ User(
email=f"user{i}@example.com", firstName=f"FirstName{i}", lastName=f"LastName{i}",
username=f"username{i}", hash_password=generate_password_hash("password123"),
activationKey=hash_string(random_string_generator(16)), pfpFilename=DEFAULT_PROFILE_FILE,
joinedDate=datetime.utcnow(), lastOnline=datetime.utcnow(),
bio=f"This is user{i}'s bio.", role=UserRole.ADMIN if i == 1 else UserRole.USER,
isActivated=True, sessions=[], user_badges=[],
enrollments=[], quizzes=[], quiz_attempts=[], chats=[], notifications=[])
for i in range(1, 6) ]
db.session.add_all(users)
db.session.commit()
return {"message": "Users seeded successfully!"}, 201
except Exception as e:
db.session.rollback()

@ -4,8 +4,8 @@ from sqlalchemy import types, text, String, DateTime, func, Boolean, ForeignKey,
from datetime import datetime
import uuid
from typing import List
from config import *
from constants import UserRole, PublishedStatus
from ..config import *
from ..constants import UserRole, PublishedStatus
class Base(MappedAsDataclass, DeclarativeBase):
pass
@ -20,13 +20,15 @@ class User(db.Model):
firstName: Mapped[str] = mapped_column(String(32), nullable=False)
lastName: Mapped[str] = mapped_column(String(32), nullable=False)
username: Mapped[str] = mapped_column(String(32), nullable=False)
hash_password: Mapped[str] = mapped_column(String(256), nullable=False) # Added field for hashed password
hash_password: Mapped[str] = mapped_column(String(256), nullable=False)
activationKey: Mapped[str] = mapped_column(String(128), nullable=False)
sessions: Mapped[List["Session"]] = relationship(back_populates="user", cascade="all, delete-orphan")
enrollments: Mapped[List["Enrollment"]] = relationship(back_populates="user", cascade="all, delete-orphan")
quizzes: Mapped[List["Quiz"]] = relationship(back_populates="creatorUser", cascade="all, delete-orphan")
quiz_attempts: Mapped[List["QuizAttempt"]] = relationship(back_populates="user", cascade="all, delete-orphan")
chats: Mapped[List["Chat"]] = relationship(back_populates="user", cascade="all, delete-orphan")
notifications: Mapped[List["Notification"]] = relationship(back_populates="user", cascade="all, delete-orphan")
dob: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.fromisocalendar(2002, 1, 1))
user_badges: Mapped[List["UserBadge"]] = relationship(back_populates="user", cascade="all, delete-orphan")
pfpFilename: Mapped[str] = mapped_column(String(256), nullable=False, default=DEFAULT_PROFILE_FILE)
joinedDate: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=func.now())

@ -0,0 +1,39 @@
from functools import wraps
from flask import request, jsonify
from sqlalchemy import select
from ..db.model import User, Session, db
def requires_role(roles=[]):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if not auth_header:
return jsonify({'error': 'No authorization header sent'}), 401
try:
session_key = auth_header.split(' ')[1]
except IndexError:
return jsonify({'error': 'Invalid authorization header format'}), 401
session = db.session.execute(
)
if not session:
return jsonify({'error': 'Invalid or expired session'}), 401
user = User.query.get(session.userID)
if not user:
return jsonify({'error': 'User not found'}), 401
# If no roles specified, allow access
if not roles:
return f(*args, **kwargs)
# Check if user has any of the required roles
if user.role in roles:
return f(*args, **kwargs)
return jsonify({'error': 'Insufficient permissions'}), 403
return decorated_function
return decorator
Loading…
Cancel
Save