Files
ipam/backend/app/models/auth.py
T
Your Name 1e1e5957e8 fix(ipam): 修复IP管理页面网段筛选不生效及下拉框过窄
- Ips.vue: el-select 添加 width: 280px,修复网段下拉框过窄
- Ips.vue: query 参数 networkId → network_id(与 FastAPI snake_case 一致)
- Scan.vue: el-select 用 network.id 代替整个 network 对象作为 value,修复切换网段不生效
- enhanced_scan_service.py: 替换失效的 scapy ARP 扫描为 arp-scan 命令;扫描结果自动创建缺失 IP 记录
2026-07-18 09:45:30 +08:00

98 lines
3.4 KiB
Python

from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Enum, Text
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.core.database import Base
import enum
class UserRole(str, enum.Enum):
"""用户角色枚举"""
SUPER_ADMIN = "super_admin" # 超级管理员 - 所有权限
ADMIN = "admin" # 管理员 - 除用户管理外的所有权限
OPERATOR = "operator" # 操作员 - 可查看和操作,不能配置
VIEWER = "viewer" # 只读用户 - 只能查看
class UserStatus(str, enum.Enum):
"""用户状态"""
ACTIVE = "active" # 正常
INACTIVE = "inactive" # 禁用
LOCKED = "locked" # 锁定(登录失败过多)
class User(Base):
"""用户表"""
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, index=True, nullable=False)
email = Column(String(100), unique=True, index=True)
phone = Column(String(20), index=True)
real_name = Column(String(50), comment="真实姓名")
password_hash = Column(String(255), nullable=False)
role = Column(Enum(UserRole), default=UserRole.VIEWER, nullable=False)
status = Column(Enum(UserStatus), default=UserStatus.ACTIVE, nullable=False)
# 登录信息
last_login_at = Column(DateTime(timezone=True))
last_login_ip = Column(String(50))
login_failed_count = Column(Integer, default=0)
# 通知配置
email_notification = Column(Boolean, default=True)
wechat_notification = Column(Boolean, default=False)
dingtalk_notification = Column(Boolean, default=False)
created_by = Column(Integer, ForeignKey("users.id"), nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
# 关系
creator = relationship("User", remote_side=[id])
class Permission(Base):
"""权限项"""
__tablename__ = "permissions"
id = Column(Integer, primary_key=True, index=True)
code = Column(String(100), unique=True, nullable=False, comment="权限代码,如:network:create")
name = Column(String(100), nullable=False, comment="权限名称")
description = Column(Text)
category = Column(String(50), comment="权限分类:network, ip, scan, snmp, alert, system")
created_at = Column(DateTime(timezone=True), server_default=func.now())
class RolePermission(Base):
"""角色权限关联表"""
__tablename__ = "role_permissions"
id = Column(Integer, primary_key=True, index=True)
role = Column(Enum(UserRole), nullable=False)
permission_id = Column(Integer, ForeignKey("permissions.id"), nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
class RefreshToken(Base):
"""刷新令牌"""
__tablename__ = "refresh_tokens"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
token = Column(String(500), unique=True, nullable=False)
expires_at = Column(DateTime(timezone=True), nullable=False)
ip_address = Column(String(50))
user_agent = Column(String(500))
revoked = Column(Boolean, default=False)
revoked_at = Column(DateTime(timezone=True))
created_at = Column(DateTime(timezone=True), server_default=func.now())
# 关系
user = relationship("User")