refactor(decorators): simplify require_admin decorator by reusing require_role

This commit is contained in:
JSC
2025-07-04 19:13:33 +02:00
parent 5c29fa1a4c
commit 4375718c2f
3 changed files with 107 additions and 92 deletions

View File

@@ -1,10 +1,9 @@
"""Sound played tracking model."""
from datetime import datetime
from typing import List, Optional
from app.database import db
from sqlalchemy import DateTime, ForeignKey, Integer, String
from sqlalchemy import DateTime, ForeignKey, Integer, func, text
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -17,16 +16,15 @@ class SoundPlayed(db.Model):
# Foreign keys
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id"), nullable=False
Integer, ForeignKey("users.id"), nullable=False,
)
sound_id: Mapped[int] = mapped_column(
Integer, ForeignKey("sounds.id"), nullable=False
Integer, ForeignKey("sounds.id"), nullable=False,
)
# Timestamp
played_at: Mapped[datetime] = mapped_column(
DateTime, default=datetime.utcnow, nullable=False
DateTime, default=datetime.utcnow, nullable=False,
)
# Relationships
@@ -34,8 +32,11 @@ class SoundPlayed(db.Model):
sound: Mapped["Sound"] = relationship("Sound", backref="play_history")
def __repr__(self) -> str:
"""String representation of SoundPlayed."""
return f"<SoundPlayed user_id={self.user_id} sound_id={self.sound_id} at={self.played_at}>"
"""Return string representation of SoundPlayed."""
return (
f"<SoundPlayed user_id={self.user_id} sound_id={self.sound_id} "
f"at={self.played_at}>"
)
def to_dict(self) -> dict:
"""Convert sound played record to dictionary."""
@@ -62,6 +63,7 @@ class SoundPlayed(db.Model):
cls,
user_id: int,
sound_id: int,
*,
commit: bool = True,
) -> "SoundPlayed":
"""Create a new sound played record."""
@@ -77,8 +79,8 @@ class SoundPlayed(db.Model):
@classmethod
def get_user_plays(
cls, user_id: int, limit: int = 50, offset: int = 0
) -> List["SoundPlayed"]:
cls, user_id: int, limit: int = 50, offset: int = 0,
) -> list["SoundPlayed"]:
"""Get recent plays for a specific user."""
return (
cls.query.filter_by(user_id=user_id)
@@ -90,8 +92,8 @@ class SoundPlayed(db.Model):
@classmethod
def get_sound_plays(
cls, sound_id: int, limit: int = 50, offset: int = 0
) -> List["SoundPlayed"]:
cls, sound_id: int, limit: int = 50, offset: int = 0,
) -> list["SoundPlayed"]:
"""Get recent plays for a specific sound."""
return (
cls.query.filter_by(sound_id=sound_id)
@@ -103,8 +105,8 @@ class SoundPlayed(db.Model):
@classmethod
def get_recent_plays(
cls, limit: int = 100, offset: int = 0
) -> List["SoundPlayed"]:
cls, limit: int = 100, offset: int = 0,
) -> list["SoundPlayed"]:
"""Get recent plays across all users and sounds."""
return (
cls.query.order_by(cls.played_at.desc())
@@ -125,10 +127,10 @@ class SoundPlayed(db.Model):
@classmethod
def get_popular_sounds(
cls, limit: int = 10, days: int | None = None
) -> List[dict]:
cls, limit: int = 10, days: int | None = None,
) -> list[dict]:
"""Get most popular sounds with play counts."""
from sqlalchemy import func, text
from app.models.sound import Sound
query = (
db.session.query(
@@ -150,14 +152,16 @@ class SoundPlayed(db.Model):
# Get sound details
popular_sounds = []
for result in results:
from app.models.sound import Sound
sound = Sound.query.get(result.sound_id)
if sound:
popular_sounds.append({
"sound": sound.to_dict(),
"play_count": result.play_count,
"last_played": result.last_played.isoformat() if result.last_played else None,
"last_played": (
result.last_played.isoformat()
if result.last_played
else None
),
})
return popular_sounds
@@ -165,7 +169,7 @@ class SoundPlayed(db.Model):
@classmethod
def get_user_stats(cls, user_id: int) -> dict:
"""Get comprehensive stats for a user."""
from sqlalchemy import func
from app.models.sound import Sound
total_plays = cls.query.filter_by(user_id=user_id).count()
@@ -199,8 +203,6 @@ class SoundPlayed(db.Model):
favorite_sound = None
if favorite_query:
from app.models.sound import Sound
sound = Sound.query.get(favorite_query.sound_id)
if sound:
favorite_sound = {
@@ -224,6 +226,10 @@ class SoundPlayed(db.Model):
"total_plays": total_plays,
"unique_sounds": unique_sounds,
"favorite_sound": favorite_sound,
"first_play": first_play.played_at.isoformat() if first_play else None,
"last_play": last_play.played_at.isoformat() if last_play else None,
"first_play": (
first_play.played_at.isoformat() if first_play else None
),
"last_play": (
last_play.played_at.isoformat() if last_play else None
),
}