Files
aiagent/backend/app/models/user.py
renjianbo 876789fac1 feat: multi-tenant workspace isolation, RBAC, sidebar nav, billing, and Android enhancements
- Backend: workspace_id isolation for 14 model tables + safe migration/backfill
- Backend: RBAC system with 4 roles and 23 permissions, seeded on startup
- Backend: workspace admin endpoints (list/manage all workspaces)
- Backend: admin user management API (CRUD, reset password)
- Backend: billing API with subscription plans, usage tracking, rate limiting
- Backend: fix system_logs.py UNION query and wrong column references
- Backend: WebSocket JWT auth and workspace enforcement
- Frontend: sidebar navigation replacing top dropdown menu
- Frontend: user management page (Users.vue) for admins
- Frontend: enhanced Workspaces.vue with admin table view
- Frontend: workspace RBAC computed properties in user store
- Android: agent marketplace, billing/subscription UI, onboarding wizard
- Android: phone login, analytics tracker, crash handler, network diagnostics
- Android: splash screen, encrypted token storage, app update enhancements
- Docs: multi-tenant RBAC guide with 8 sections and role-permission matrix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-04 01:00:22 +08:00

63 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
用户模型
"""
from sqlalchemy import Boolean, Column, String, Integer, DateTime, Date, func
from sqlalchemy.dialects.mysql import CHAR
from sqlalchemy.orm import relationship
from app.core.database import Base
import uuid
class User(Base):
"""用户表"""
__tablename__ = "users"
id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid.uuid4()), comment="用户ID")
username = Column(String(50), unique=True, nullable=False, comment="用户名")
email = Column(String(100), unique=True, nullable=False, comment="邮箱")
password_hash = Column(String(255), nullable=False, comment="密码哈希")
role = Column(String(20), default="user", comment="角色: admin/user保留字段用于向后兼容")
feishu_open_id = Column(String(64), nullable=True, comment="飞书用户 open_id用于推送通知")
feishu_default_agent_id = Column(CHAR(36), nullable=True, comment="飞书对话默认 Agent ID")
phone = Column(String(20), nullable=True, comment="手机号")
phone_verified = Column(Boolean, default=False, comment="手机号是否已验证")
phone_verified_at = Column(DateTime, nullable=True, comment="手机号验证时间")
status = Column(String(20), default="active", comment="账号状态: active/disabled/deleted")
is_email_verified = Column(Boolean, default=False, comment="邮箱是否已验证")
agreed_terms = Column(Boolean, default=False, comment="是否同意用户协议")
agreed_terms_version = Column(String(20), nullable=True, comment="同意的协议版本")
agreed_terms_at = Column(DateTime, nullable=True, comment="同意协议的时间")
# v1.2: 订阅与用量
subscription_tier = Column(String(20), default="free", comment="订阅等级: free/pro/enterprise")
subscription_expires_at = Column(DateTime, nullable=True, comment="订阅到期时间")
daily_usage_count = Column(Integer, default=0, comment="今日对话次数")
daily_usage_date = Column(Date, nullable=True, comment="用量统计日期")
created_at = Column(DateTime, default=func.now(), comment="创建时间")
updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
# RBAC关系多对多
roles = relationship("Role", secondary="user_roles", back_populates="users")
def __repr__(self):
return f"<User(id={self.id}, username={self.username})>"
def has_permission(self, permission_code: str) -> bool:
"""检查用户是否有指定权限"""
# 如果是admin拥有所有权限
if self.role == "admin":
return True
# 检查用户的所有角色是否包含该权限
for role in self.roles:
for permission in role.permissions:
if permission.code == permission_code:
return True
return False
def has_role(self, role_name: str) -> bool:
"""检查用户是否有指定角色"""
# 如果是admin拥有所有角色
if self.role == "admin":
return True
return any(role.name == role_name for role in self.roles)