mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 06:40:45 +08:00
Keep from netx_api.models import X working while grouping alarms, UME, managed NE, topology, auth, config sync, and port traffic tables. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
3.2 KiB
Python
63 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from uuid import uuid4
|
|
|
|
from sqlalchemy import BigInteger, Boolean, DateTime, Float, ForeignKey, Integer, LargeBinary, String, Text, UniqueConstraint
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from ..db import Base
|
|
from ..timeutil import utcnow_naive
|
|
from ._types import JsonType as _JsonType
|
|
|
|
class AppUser(Base):
|
|
"""Local netx application user (login account)."""
|
|
|
|
__tablename__ = "app_user"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True, default=lambda: uuid4().hex)
|
|
username: Mapped[str] = mapped_column(String(128), unique=True, index=True)
|
|
password_hash: Mapped[str] = mapped_column(String(255), default="")
|
|
role: Mapped[str] = mapped_column(String(32), default="user", index=True) # admin | user
|
|
# Optional capability override; empty => role defaults (see auth_scopes).
|
|
scopes: Mapped[list] = mapped_column(_JsonType, default=list)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True, index=True)
|
|
must_change_password: Mapped[bool] = mapped_column(Boolean, default=False)
|
|
created_by: Mapped[str] = mapped_column(String(64), default="")
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive)
|
|
|
|
|
|
class AuditLog(Base):
|
|
"""Application audit trail for authenticated (and auth) actions."""
|
|
|
|
__tablename__ = "audit_log"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True, default=lambda: uuid4().hex)
|
|
ts: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive, index=True)
|
|
actor_user_id: Mapped[str] = mapped_column(String(64), default="", index=True)
|
|
actor_username: Mapped[str] = mapped_column(String(128), default="", index=True)
|
|
action: Mapped[str] = mapped_column(String(128), default="", index=True)
|
|
method: Mapped[str] = mapped_column(String(16), default="")
|
|
path: Mapped[str] = mapped_column(String(512), default="", index=True)
|
|
status_code: Mapped[int] = mapped_column(Integer, default=0)
|
|
client_ip: Mapped[str] = mapped_column(String(128), default="")
|
|
user_agent: Mapped[str] = mapped_column(String(512), default="")
|
|
detail: Mapped[dict] = mapped_column(_JsonType, default=dict)
|
|
|
|
|
|
class ApiToken(Base):
|
|
"""Long-lived API token (MCP/scripts); hashed at rest."""
|
|
|
|
__tablename__ = "api_token"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True, default=lambda: uuid4().hex)
|
|
name: Mapped[str] = mapped_column(String(128), default="")
|
|
token_hash: Mapped[str] = mapped_column(String(128), unique=True, index=True)
|
|
user_id: Mapped[str] = mapped_column(String(64), index=True)
|
|
# Capability subset; empty inherits owner user scopes (then intersected).
|
|
scopes: Mapped[list] = mapped_column(_JsonType, default=list)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive)
|
|
expires_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, index=True)
|
|
last_used_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
revoked_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|