Refactor user authentication and dashboard features

- Added `is_admin` field to User model for role management.
- Updated user context middleware to include current user in templates.
- Enhanced session management with improved debug middleware.
- Refactored dashboard view to fetch user-specific data and recent events.
- Improved login and registration templates for better user experience.
- Added admin routes with access control for admin users.
- Updated Docker configuration for better error logging and dependency management.
- Updated requirements to include new dependencies and specify versions.
This commit is contained in:
Christian Krakau-Louis
2025-04-13 18:49:27 +02:00
parent 0de2eb5830
commit 4a79c5cacb
20 changed files with 790 additions and 579 deletions
+91 -10
View File
@@ -1,7 +1,8 @@
#!/usr/bin/env python3
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, DateTime, Text, Table
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, DateTime, Text, Float
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from datetime import datetime
from .db import Base
class User(Base):
@@ -11,15 +12,20 @@ class User(Base):
email = Column(String(255), unique=True, index=True, nullable=False)
hashed_password = Column(String(255), nullable=True)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
is_active = Column(Boolean, default=True)
is_verified = Column(Boolean, default=False)
is_admin = Column(Boolean, default=False)
verification_token = Column(String(255), nullable=True)
reset_token = Column(String(255), nullable=True)
reset_token_expires_at = Column(DateTime, nullable=True)
last_login = Column(DateTime, nullable=True)
# Relationship to teams
# Relationships
memberships = relationship("TeamMembership", back_populates="user")
teams = relationship("TeamMember", back_populates="user")
points = relationship("UserPoints", back_populates="user")
events_attended = relationship("EventAttendee", back_populates="user")
class OAuthAccount(Base):
@@ -40,14 +46,14 @@ class Team(Base):
__tablename__ = "teams"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), unique=True, nullable=False)
# Add fields for team detail view
description = Column(Text, nullable=True)
is_public = Column(Boolean, default=False) # For team privacy setting
created_at = Column(DateTime, server_default=func.now()) # For team founded date
description = Column(Text, nullable=True) # Optional team description
# Relationship to memberships
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
# Relationships
memberships = relationship("TeamMembership", back_populates="team")
members = relationship("TeamMember", back_populates="team")
class TeamMembership(Base):
@@ -56,14 +62,25 @@ class TeamMembership(Base):
user_id = Column(Integer, ForeignKey("users.id"))
team_id = Column(Integer, ForeignKey("teams.id"))
is_admin = Column(Boolean, default=False)
# Add joined_at to track when members joined
joined_at = Column(DateTime, server_default=func.now())
user = relationship("User", back_populates="memberships")
team = relationship("Team", back_populates="memberships")
class TeamMember(Base):
__tablename__ = "team_members"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
team_id = Column(Integer, ForeignKey("teams.id"), nullable=False)
is_captain = Column(Boolean, default=False)
joined_at = Column(DateTime, server_default=func.now())
# Relationships
user = relationship("User", back_populates="teams")
team = relationship("Team", back_populates="members")
class QRTicket(Base):
__tablename__ = "qr_tickets"
id = Column(Integer, primary_key=True, index=True)
@@ -81,7 +98,6 @@ class QRTicket(Base):
event_name = Column(String(255), nullable=True)
# New model for team achievements
class TeamAchievement(Base):
__tablename__ = "team_achievements"
id = Column(Integer, primary_key=True, index=True)
@@ -92,3 +108,68 @@ class TeamAchievement(Base):
achieved_at = Column(DateTime, server_default=func.now())
team = relationship("Team")
class Event(Base):
__tablename__ = "events"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
description = Column(Text, nullable=True)
location = Column(String(200), nullable=True)
event_date = Column(DateTime, nullable=False)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
# Relationships
attendees = relationship("EventAttendee", back_populates="event")
class EventAttendee(Base):
__tablename__ = "event_attendees"
id = Column(Integer, primary_key=True, index=True)
event_id = Column(Integer, ForeignKey("events.id"), nullable=False)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
check_in_time = Column(DateTime, server_default=func.now())
# Relationships
event = relationship("Event", back_populates="attendees")
user = relationship("User", back_populates="events_attended")
class UserPoints(Base):
__tablename__ = "user_points"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
points = Column(Float, nullable=False, default=0)
reason = Column(String(200), nullable=True)
awarded_at = Column(DateTime, server_default=func.now())
# Relationships
user = relationship("User", back_populates="points")
class QRCode(Base):
__tablename__ = "qr_codes"
id = Column(Integer, primary_key=True, index=True)
code = Column(String(100), unique=True, index=True, nullable=False)
points = Column(Float, default=1.0, nullable=False)
description = Column(String(200), nullable=True)
is_active = Column(Boolean, default=True)
max_uses = Column(Integer, nullable=True) # null = unlimited
created_at = Column(DateTime, server_default=func.now())
expires_at = Column(DateTime, nullable=True) # null = never expires
# Relationships
redemptions = relationship("QRCodeRedemption", back_populates="qr_code")
class QRCodeRedemption(Base):
__tablename__ = "qr_code_redemptions"
id = Column(Integer, primary_key=True, index=True)
qr_code_id = Column(Integer, ForeignKey("qr_codes.id"), nullable=False)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
redeemed_at = Column(DateTime, server_default=func.now())
# Relationships
qr_code = relationship("QRCode", back_populates="redemptions")
user = relationship("User")