Coverage for polar/models/user_session.py: 96%
23 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
1from datetime import datetime
2from uuid import UUID
4from sqlalchemy import CHAR, TIMESTAMP, ForeignKey, Text, Uuid
5from sqlalchemy.dialects.postgresql import ARRAY
6from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship
8from polar.auth.scope import Scope
9from polar.config import settings
10from polar.kit.db.models.base import RecordModel
11from polar.kit.extensions.sqlalchemy import StringEnum
12from polar.kit.utils import utc_now
13from polar.models.user import User
16def get_expires_at() -> datetime:
17 return utc_now() + settings.USER_SESSION_TTL
20class UserSession(RecordModel):
21 __tablename__ = "user_sessions"
23 token: Mapped[str] = mapped_column(CHAR(64), unique=True, nullable=False)
24 expires_at: Mapped[datetime] = mapped_column(
25 TIMESTAMP(timezone=True), nullable=False, index=True, default=get_expires_at
26 )
27 user_agent: Mapped[str] = mapped_column(Text, nullable=False)
28 scopes: Mapped[list[Scope]] = mapped_column(
29 ARRAY(StringEnum(Scope)), nullable=False, default=list
30 )
32 user_id: Mapped[UUID] = mapped_column(
33 Uuid, ForeignKey("users.id", ondelete="cascade"), nullable=False
34 )
36 @declared_attr
37 def user(cls) -> Mapped[User]:
38 return relationship(User, lazy="joined")