Files
gh-christianlouis-leagueledger/app/models.py
T
Christian Krakau-Louis 4a79c5cacb 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.
2025-04-13 18:49:27 +02:00

176 lines
7.0 KiB
Python

#!/usr/bin/env python3
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):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, index=True, nullable=False)
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)
# 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):
__tablename__ = "oauth_accounts"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"))
provider = Column(String(50)) # e.g., "google", "facebook"
provider_user_id = Column(String(255))
access_token = Column(String(255))
expires_at = Column(DateTime, nullable=True)
refresh_token = Column(String(255), nullable=True)
created_at = Column(DateTime, server_default=func.now())
user = relationship("User")
class Team(Base):
__tablename__ = "teams"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), unique=True, nullable=False)
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
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):
__tablename__ = "team_membership"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"))
team_id = Column(Integer, ForeignKey("teams.id"))
is_admin = Column(Boolean, default=False)
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)
code = Column(String(128), unique=True, index=True) # Unique token
points = Column(Integer, default=0)
redeemed_by = Column(Integer, ForeignKey("users.id"), nullable=True)
redeemed_at_team = Column(Integer, ForeignKey("teams.id"), nullable=True)
used = Column(Boolean, default=False)
# Add timestamps to track when tickets were created and redeemed
created_at = Column(DateTime, server_default=func.now())
redeemed_at = Column(DateTime, nullable=True)
# Add event name to track which quiz event this ticket belongs to
event_name = Column(String(255), nullable=True)
class TeamAchievement(Base):
__tablename__ = "team_achievements"
id = Column(Integer, primary_key=True, index=True)
team_id = Column(Integer, ForeignKey("teams.id"))
name = Column(String(255), nullable=False) # e.g., "1st Place"
event_name = Column(String(255), nullable=True) # e.g., "History Night"
description = Column(Text, nullable=True)
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")