Track site-created 3x-ui clients and per-panel inbound whitelist for users

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
test2
2026-07-25 22:32:26 +03:00
co-authored by Cursor
parent 1b2fea4539
commit ad7e1db6b7
9 changed files with 746 additions and 13 deletions
+56
View File
@@ -110,3 +110,59 @@ class XuiPanel(Base):
last_checked: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
is_enabled: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
site_clients: Mapped[list["XuiSiteClient"]] = relationship(
back_populates="panel", cascade="all, delete-orphan"
)
inbounds: Mapped[list["XuiPanelInbound"]] = relationship(
back_populates="panel", cascade="all, delete-orphan"
)
class XuiPanelInbound(Base):
"""Cached 3x-ui inbound; admin marks which are available for users."""
__tablename__ = "xui_panel_inbounds"
__table_args__ = (UniqueConstraint("panel_id", "inbound_id", name="uq_xui_panel_inbound"),)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
panel_id: Mapped[int] = mapped_column(ForeignKey("xui_panels.id", ondelete="CASCADE"), index=True)
inbound_id: Mapped[int] = mapped_column(Integer)
protocol: Mapped[str] = mapped_column(String(32), index=True)
remark: Mapped[str | None] = mapped_column(String(255), nullable=True)
port: Mapped[int | None] = mapped_column(Integer, nullable=True)
enable: Mapped[bool] = mapped_column(Boolean, default=True)
is_available_for_users: Mapped[bool] = mapped_column(Boolean, default=False)
last_synced_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
panel: Mapped[XuiPanel] = relationship(back_populates="inbounds")
class XuiSiteClient(Base):
"""Clients created via this website (not imported from existing 3x-ui users)."""
__tablename__ = "xui_site_clients"
__table_args__ = (UniqueConstraint("panel_id", "email", name="uq_xui_site_client_email"),)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
panel_id: Mapped[int] = mapped_column(ForeignKey("xui_panels.id", ondelete="CASCADE"), index=True)
email: Mapped[str] = mapped_column(String(255), index=True)
protocol: Mapped[str] = mapped_column(String(32))
inbound_id: Mapped[int] = mapped_column(Integer)
inbound_remark: Mapped[str | None] = mapped_column(String(255), nullable=True)
uuid: Mapped[str | None] = mapped_column(String(128), nullable=True)
flow: Mapped[str | None] = mapped_column(String(64), nullable=True)
private_key: Mapped[str | None] = mapped_column(Text, nullable=True)
public_key: Mapped[str | None] = mapped_column(Text, nullable=True)
link: Mapped[str | None] = mapped_column(Text, nullable=True)
expiry_days: Mapped[int] = mapped_column(Integer, default=0)
start_after_first_use: Mapped[bool] = mapped_column(Boolean, default=False)
expiry_time: Mapped[int] = mapped_column(Integer, default=0)
total_gb: Mapped[int] = mapped_column(Integer, default=0)
limit_ip: Mapped[int] = mapped_column(Integer, default=0)
comment: Mapped[str | None] = mapped_column(Text, nullable=True)
created_via: Mapped[str] = mapped_column(String(32), default="website")
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
panel: Mapped[XuiPanel] = relationship(back_populates="site_clients")