Files
opsxsql/backend/app/models/instance_group.py
T
logan 4111e1eee8 refactor: 权限组简化为2组(readonly/write) + Transfer穿梭框选择数据库
- access_type 从3值(readonly/datachange/ddl)简化为2值(readonly/write)
- readonly=只读查看(关联只读/从库用于查询) write=写入变更(关联主库用于工单)
- 前端InstanceGroupPage重写: 2权限类型卡片+自定义Transfer穿梭框组件
- Transfer组件: 左侧可选数据库→右侧已授权数据库, 搜索/勾选/箭头移动
- role_permissions.py更新: 2值权限映射, get_accessible_instances按access_type过滤
- 后端schema/模型校验更新为readonly|write正则
- 15个测试全部通过
2026-05-24 19:27:04 +08:00

69 lines
2.7 KiB
Python

from __future__ import annotations
import json
from typing import List, Optional
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey, Table, func
from sqlalchemy.orm import relationship
from app.core.database import Base
# 用户-权限组关联表
user_groups = Table(
"user_groups",
Base.metadata,
Column("user_id", Integer, ForeignKey("users.id", ondelete="CASCADE"), primary_key=True),
Column("group_id", Integer, ForeignKey("instance_groups.id", ondelete="CASCADE"), primary_key=True),
Column("permissions", Text, nullable=True), # JSON: 覆盖组默认权限 (legacy, kept for compat)
)
class InstanceGroup(Base):
__tablename__ = "instance_groups"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(100), nullable=False, unique=True)
description = Column(Text, nullable=True)
db_type = Column(String(20), nullable=False, default="all") # mysql/redis/pg/mongo/all
permissions = Column(Text, nullable=True) # JSON: ["query:select", ...] (legacy, kept for compat)
access_type = Column(String(20), nullable=True, default="readonly") # readonly / write
allowed_databases = Column(Text, nullable=True) # JSON array of database names; empty = all databases
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
# 关系
instances = relationship("Instance", back_populates="group", lazy="selectin")
users = relationship("User", secondary=user_groups, back_populates="groups", lazy="selectin")
# ---- Legacy helpers (kept for backward compatibility) ----
def get_permissions(self) -> list:
if self.permissions:
try:
return json.loads(self.permissions)
except (json.JSONDecodeError, TypeError):
return []
return []
def set_permissions(self, perms: list):
self.permissions = json.dumps(perms, ensure_ascii=False) if perms else None
# ---- New access_type / allowed_databases helpers ----
def get_allowed_databases(self) -> list[str]:
"""返回允许的数据库名列表,空列表表示关联实例的所有库。"""
if self.allowed_databases:
try:
return json.loads(self.allowed_databases)
except (json.JSONDecodeError, TypeError):
return []
return []
def set_allowed_databases(self, databases: list[str] | None):
self.allowed_databases = (
json.dumps(databases, ensure_ascii=False) if databases else None
)
VALID_ACCESS_TYPES = {"readonly", "write"}