3f2ec19ec2
新增统一限制规则、临时不限和风控免告警白名单,接入比价、短信登录、广告、引导视频与账号冷却等业务链路。补充设备选择、权限、审计、迁移及回归测试。
78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
"""Per-subject limit policy overrides used by the admin whitelist page."""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import (
|
|
Boolean,
|
|
DateTime,
|
|
Index,
|
|
Integer,
|
|
String,
|
|
UniqueConstraint,
|
|
func,
|
|
true,
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class LimitPolicyOverride(Base):
|
|
"""One rule override for one phone or device.
|
|
|
|
``reset_at`` is a non-destructive usage baseline. Business records and
|
|
security events remain intact; quota readers only count rows at or after
|
|
this timestamp.
|
|
"""
|
|
|
|
__tablename__ = "limit_policy_override"
|
|
__table_args__ = (
|
|
UniqueConstraint(
|
|
"subject_type",
|
|
"subject_value",
|
|
"rule_code",
|
|
name="uq_limit_policy_subject_rule",
|
|
),
|
|
Index(
|
|
"ix_limit_policy_lookup",
|
|
"subject_type",
|
|
"subject_value",
|
|
"rule_code",
|
|
"enabled",
|
|
),
|
|
Index("ix_limit_policy_expires", "expires_at"),
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
subject_type: Mapped[str] = mapped_column(String(16), nullable=False)
|
|
subject_value: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
rule_code: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
# 产品只保留“临时不限/免告警”。即使有内部脚本绕过 API 直接建 ORM
|
|
# 对象,也不能再悄悄落成已经下线的 override 模式。
|
|
mode: Mapped[str] = mapped_column(String(24), nullable=False, default="unlimited")
|
|
limit_value: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
enabled: Mapped[bool] = mapped_column(
|
|
Boolean, nullable=False, default=True, server_default=true()
|
|
)
|
|
starts_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
expires_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
reset_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
reason: Mapped[str | None] = mapped_column(String(256), nullable=True)
|
|
created_by_admin_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), nullable=False
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
nullable=False,
|
|
)
|