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

39 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-05-23 19:04 +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 debug = enum.auto() 

27 normal = enum.auto() 

28 high = enum.auto() 

29 

30 

31class AdminAction(Base, kw_only=True): 

32 __tablename__ = "admin_actions" 

33 

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

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

36 

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

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

39 

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

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

42 

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

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

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

46 

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

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

49 

50 __table_args__ = ( 

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

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

53 ) 

54 

55 

56class AdminTag(Base, kw_only=True): 

57 __tablename__ = "admin_tags" 

58 

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

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

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

62 

63 

64class UserAdminTag(Base, kw_only=True): 

65 __tablename__ = "user_admin_tags" 

66 

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

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

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

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

71 

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

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

74 

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