Coverage for app/backend/src/couchers/models/admin.py: 100%

40 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-08 13:36 +0000

1import enum 

2from datetime import datetime 

3from typing import TYPE_CHECKING, Any 

4 

5from sqlalchemy import ( 

6 BigInteger, 

7 CheckConstraint, 

8 DateTime, 

9 Enum, 

10 ForeignKey, 

11 Index, 

12 String, 

13 UniqueConstraint, 

14 func, 

15) 

16from sqlalchemy.dialects.postgresql import JSONB 

17from sqlalchemy.orm import Mapped, mapped_column, relationship 

18 

19from couchers.models.base import Base 

20 

21if TYPE_CHECKING: 

22 from couchers.models.users import User 

23 

24 

25class AdminActionLevel(enum.Enum): 

26 trace = enum.auto() 

27 debug = enum.auto() 

28 normal = enum.auto() 

29 high = enum.auto() 

30 

31 

32class AdminAction(Base, kw_only=True): 

33 __tablename__ = "admin_actions" 

34 

35 id: Mapped[int] = mapped_column(BigInteger, primary_key=True, init=False) 

36 created: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), init=False) 

37 

38 admin_user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) 

39 target_user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) 

40 

41 action_type: Mapped[str] = mapped_column(String) 

42 level: Mapped[AdminActionLevel] = mapped_column(Enum(AdminActionLevel), server_default="normal") 

43 

44 note: Mapped[str | None] = mapped_column(String, default=None) 

45 data: Mapped[Any | None] = mapped_column(JSONB(none_as_null=True), default=None) 

46 tag: Mapped[str | None] = mapped_column(String, default=None) 

47 

48 admin_user: Mapped[User] = relationship(init=False, foreign_keys="AdminAction.admin_user_id") 

49 target_user: Mapped[User] = relationship(init=False, foreign_keys="AdminAction.target_user_id") 

50 

51 __table_args__ = ( 

52 Index("ix_admin_actions_target_created", target_user_id, created), 

53 CheckConstraint("note IS NULL OR data IS NULL", name="note_xor_data"), 

54 ) 

55 

56 

57class AdminTag(Base, kw_only=True): 

58 __tablename__ = "admin_tags" 

59 

60 id: Mapped[int] = mapped_column(BigInteger, primary_key=True, init=False) 

61 tag: Mapped[str] = mapped_column(String, unique=True) 

62 created: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), init=False) 

63 

64 

65class UserAdminTag(Base, kw_only=True): 

66 __tablename__ = "user_admin_tags" 

67 

68 id: Mapped[int] = mapped_column(BigInteger, primary_key=True, init=False) 

69 user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) 

70 admin_tag_id: Mapped[int] = mapped_column(ForeignKey("admin_tags.id"), index=True) 

71 created: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), init=False) 

72 

73 user: Mapped[User] = relationship(init=False, foreign_keys="UserAdminTag.user_id") 

74 admin_tag: Mapped[AdminTag] = relationship(init=False) 

75 

76 __table_args__ = (UniqueConstraint("user_id", "admin_tag_id"),)