fix: auto-fix code issues (cron)
- 修复重复导入/字段 - 修复异常处理 - 修复PEP8格式问题 - 添加类型注解
This commit is contained in:
@@ -19,6 +19,7 @@ try:
|
||||
from cryptography.fernet import Fernet
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
||||
|
||||
CRYPTO_AVAILABLE = True
|
||||
except ImportError:
|
||||
CRYPTO_AVAILABLE = False
|
||||
@@ -27,6 +28,7 @@ except ImportError:
|
||||
|
||||
class AuditActionType(Enum):
|
||||
"""审计动作类型"""
|
||||
|
||||
CREATE = "create"
|
||||
READ = "read"
|
||||
UPDATE = "update"
|
||||
@@ -49,26 +51,29 @@ class AuditActionType(Enum):
|
||||
|
||||
class DataSensitivityLevel(Enum):
|
||||
"""数据敏感度级别"""
|
||||
PUBLIC = "public" # 公开
|
||||
INTERNAL = "internal" # 内部
|
||||
|
||||
PUBLIC = "public" # 公开
|
||||
INTERNAL = "internal" # 内部
|
||||
CONFIDENTIAL = "confidential" # 机密
|
||||
SECRET = "secret" # 绝密
|
||||
SECRET = "secret" # 绝密
|
||||
|
||||
|
||||
class MaskingRuleType(Enum):
|
||||
"""脱敏规则类型"""
|
||||
PHONE = "phone" # 手机号
|
||||
EMAIL = "email" # 邮箱
|
||||
ID_CARD = "id_card" # 身份证号
|
||||
BANK_CARD = "bank_card" # 银行卡号
|
||||
NAME = "name" # 姓名
|
||||
ADDRESS = "address" # 地址
|
||||
CUSTOM = "custom" # 自定义
|
||||
|
||||
PHONE = "phone" # 手机号
|
||||
EMAIL = "email" # 邮箱
|
||||
ID_CARD = "id_card" # 身份证号
|
||||
BANK_CARD = "bank_card" # 银行卡号
|
||||
NAME = "name" # 姓名
|
||||
ADDRESS = "address" # 地址
|
||||
CUSTOM = "custom" # 自定义
|
||||
|
||||
|
||||
@dataclass
|
||||
class AuditLog:
|
||||
"""审计日志条目"""
|
||||
|
||||
id: str
|
||||
action_type: str
|
||||
user_id: str | None = None
|
||||
@@ -90,6 +95,7 @@ class AuditLog:
|
||||
@dataclass
|
||||
class EncryptionConfig:
|
||||
"""加密配置"""
|
||||
|
||||
id: str
|
||||
project_id: str
|
||||
is_enabled: bool = False
|
||||
@@ -107,6 +113,7 @@ class EncryptionConfig:
|
||||
@dataclass
|
||||
class MaskingRule:
|
||||
"""脱敏规则"""
|
||||
|
||||
id: str
|
||||
project_id: str
|
||||
name: str
|
||||
@@ -126,6 +133,7 @@ class MaskingRule:
|
||||
@dataclass
|
||||
class DataAccessPolicy:
|
||||
"""数据访问策略"""
|
||||
|
||||
id: str
|
||||
project_id: str
|
||||
name: str
|
||||
@@ -147,6 +155,7 @@ class DataAccessPolicy:
|
||||
@dataclass
|
||||
class AccessRequest:
|
||||
"""访问请求(用于需要审批的访问)"""
|
||||
|
||||
id: str
|
||||
policy_id: str
|
||||
user_id: str
|
||||
@@ -166,30 +175,15 @@ class SecurityManager:
|
||||
|
||||
# 预定义脱敏规则
|
||||
DEFAULT_MASKING_RULES = {
|
||||
MaskingRuleType.PHONE: {
|
||||
"pattern": r"(\d{3})\d{4}(\d{4})",
|
||||
"replacement": r"\1****\2"
|
||||
},
|
||||
MaskingRuleType.EMAIL: {
|
||||
"pattern": r"(\w{1,3})\w+(@\w+\.\w+)",
|
||||
"replacement": r"\1***\2"
|
||||
},
|
||||
MaskingRuleType.ID_CARD: {
|
||||
"pattern": r"(\d{6})\d{8}(\d{4})",
|
||||
"replacement": r"\1********\2"
|
||||
},
|
||||
MaskingRuleType.BANK_CARD: {
|
||||
"pattern": r"(\d{4})\d+(\d{4})",
|
||||
"replacement": r"\1 **** **** \2"
|
||||
},
|
||||
MaskingRuleType.NAME: {
|
||||
"pattern": r"([\u4e00-\u9fa5])[\u4e00-\u9fa5]+",
|
||||
"replacement": r"\1**"
|
||||
},
|
||||
MaskingRuleType.PHONE: {"pattern": r"(\d{3})\d{4}(\d{4})", "replacement": r"\1****\2"},
|
||||
MaskingRuleType.EMAIL: {"pattern": r"(\w{1,3})\w+(@\w+\.\w+)", "replacement": r"\1***\2"},
|
||||
MaskingRuleType.ID_CARD: {"pattern": r"(\d{6})\d{8}(\d{4})", "replacement": r"\1********\2"},
|
||||
MaskingRuleType.BANK_CARD: {"pattern": r"(\d{4})\d+(\d{4})", "replacement": r"\1 **** **** \2"},
|
||||
MaskingRuleType.NAME: {"pattern": r"([\u4e00-\u9fa5])[\u4e00-\u9fa5]+", "replacement": r"\1**"},
|
||||
MaskingRuleType.ADDRESS: {
|
||||
"pattern": r"([\u4e00-\u9fa5]{2,})([\u4e00-\u9fa5]+路|街|巷|号)(.+)",
|
||||
"replacement": r"\1\2***"
|
||||
}
|
||||
"replacement": r"\1\2***",
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self, db_path: str = "insightflow.db"):
|
||||
@@ -200,7 +194,7 @@ class SecurityManager:
|
||||
self._local = {}
|
||||
self._init_db()
|
||||
|
||||
def _init_db(self):
|
||||
def _init_db(self) -> None:
|
||||
"""初始化数据库表"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
@@ -308,9 +302,7 @@ class SecurityManager:
|
||||
|
||||
def _generate_id(self) -> str:
|
||||
"""生成唯一ID"""
|
||||
return hashlib.sha256(
|
||||
f"{datetime.now().isoformat()}{secrets.token_hex(16)}".encode()
|
||||
).hexdigest()[:32]
|
||||
return hashlib.sha256(f"{datetime.now().isoformat()}{secrets.token_hex(16)}".encode()).hexdigest()[:32]
|
||||
|
||||
# ==================== 审计日志 ====================
|
||||
|
||||
@@ -326,7 +318,7 @@ class SecurityManager:
|
||||
before_value: str | None = None,
|
||||
after_value: str | None = None,
|
||||
success: bool = True,
|
||||
error_message: str | None = None
|
||||
error_message: str | None = None,
|
||||
) -> AuditLog:
|
||||
"""记录审计日志"""
|
||||
log = AuditLog(
|
||||
@@ -341,22 +333,34 @@ class SecurityManager:
|
||||
before_value=before_value,
|
||||
after_value=after_value,
|
||||
success=success,
|
||||
error_message=error_message
|
||||
error_message=error_message,
|
||||
)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO audit_logs
|
||||
(id, action_type, user_id, user_ip, user_agent, resource_type, resource_id,
|
||||
action_details, before_value, after_value, success, error_message, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
log.id, log.action_type, log.user_id, log.user_ip, log.user_agent,
|
||||
log.resource_type, log.resource_id, log.action_details,
|
||||
log.before_value, log.after_value, int(log.success),
|
||||
log.error_message, log.created_at
|
||||
))
|
||||
""",
|
||||
(
|
||||
log.id,
|
||||
log.action_type,
|
||||
log.user_id,
|
||||
log.user_ip,
|
||||
log.user_agent,
|
||||
log.resource_type,
|
||||
log.resource_id,
|
||||
log.action_details,
|
||||
log.before_value,
|
||||
log.after_value,
|
||||
int(log.success),
|
||||
log.error_message,
|
||||
log.created_at,
|
||||
),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -372,7 +376,7 @@ class SecurityManager:
|
||||
end_time: str | None = None,
|
||||
success: bool | None = None,
|
||||
limit: int = 100,
|
||||
offset: int = 0
|
||||
offset: int = 0,
|
||||
) -> list[AuditLog]:
|
||||
"""查询审计日志"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
@@ -429,18 +433,14 @@ class SecurityManager:
|
||||
after_value=row[9],
|
||||
success=bool(row[10]),
|
||||
error_message=row[11],
|
||||
created_at=row[12]
|
||||
created_at=row[12],
|
||||
)
|
||||
logs.append(log)
|
||||
|
||||
conn.close()
|
||||
return logs
|
||||
|
||||
def get_audit_stats(
|
||||
self,
|
||||
start_time: str | None = None,
|
||||
end_time: str | None = None
|
||||
) -> dict[str, Any]:
|
||||
def get_audit_stats(self, start_time: str | None = None, end_time: str | None = None) -> dict[str, Any]:
|
||||
"""获取审计统计"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
@@ -460,12 +460,7 @@ class SecurityManager:
|
||||
cursor.execute(query, params)
|
||||
rows = cursor.fetchall()
|
||||
|
||||
stats = {
|
||||
"total_actions": 0,
|
||||
"success_count": 0,
|
||||
"failure_count": 0,
|
||||
"action_breakdown": {}
|
||||
}
|
||||
stats = {"total_actions": 0, "success_count": 0, "failure_count": 0, "action_breakdown": {}}
|
||||
|
||||
for action_type, success, count in rows:
|
||||
stats["total_actions"] += count
|
||||
@@ -500,11 +495,7 @@ class SecurityManager:
|
||||
)
|
||||
return base64.urlsafe_b64encode(kdf.derive(password.encode()))
|
||||
|
||||
def enable_encryption(
|
||||
self,
|
||||
project_id: str,
|
||||
master_password: str
|
||||
) -> EncryptionConfig:
|
||||
def enable_encryption(self, project_id: str, master_password: str) -> EncryptionConfig:
|
||||
"""启用项目加密"""
|
||||
if not CRYPTO_AVAILABLE:
|
||||
raise RuntimeError("cryptography library not available")
|
||||
@@ -523,43 +514,54 @@ class SecurityManager:
|
||||
encryption_type="aes-256-gcm",
|
||||
key_derivation="pbkdf2",
|
||||
master_key_hash=key_hash,
|
||||
salt=salt
|
||||
salt=salt,
|
||||
)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 检查是否已存在配置
|
||||
cursor.execute(
|
||||
"SELECT id FROM encryption_configs WHERE project_id = ?",
|
||||
(project_id,)
|
||||
)
|
||||
cursor.execute("SELECT id FROM encryption_configs WHERE project_id = ?", (project_id,))
|
||||
existing = cursor.fetchone()
|
||||
|
||||
if existing:
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE encryption_configs
|
||||
SET is_enabled = 1, encryption_type = ?, key_derivation = ?,
|
||||
master_key_hash = ?, salt = ?, updated_at = ?
|
||||
WHERE project_id = ?
|
||||
""", (
|
||||
config.encryption_type, config.key_derivation,
|
||||
config.master_key_hash, config.salt,
|
||||
config.updated_at, project_id
|
||||
))
|
||||
""",
|
||||
(
|
||||
config.encryption_type,
|
||||
config.key_derivation,
|
||||
config.master_key_hash,
|
||||
config.salt,
|
||||
config.updated_at,
|
||||
project_id,
|
||||
),
|
||||
)
|
||||
config.id = existing[0]
|
||||
else:
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO encryption_configs
|
||||
(id, project_id, is_enabled, encryption_type, key_derivation,
|
||||
master_key_hash, salt, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
config.id, config.project_id, int(config.is_enabled),
|
||||
config.encryption_type, config.key_derivation,
|
||||
config.master_key_hash, config.salt,
|
||||
config.created_at, config.updated_at
|
||||
))
|
||||
""",
|
||||
(
|
||||
config.id,
|
||||
config.project_id,
|
||||
int(config.is_enabled),
|
||||
config.encryption_type,
|
||||
config.key_derivation,
|
||||
config.master_key_hash,
|
||||
config.salt,
|
||||
config.created_at,
|
||||
config.updated_at,
|
||||
),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
@@ -569,16 +571,12 @@ class SecurityManager:
|
||||
action_type=AuditActionType.ENCRYPTION_ENABLE,
|
||||
resource_type="project",
|
||||
resource_id=project_id,
|
||||
action_details={"encryption_type": config.encryption_type}
|
||||
action_details={"encryption_type": config.encryption_type},
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
def disable_encryption(
|
||||
self,
|
||||
project_id: str,
|
||||
master_password: str
|
||||
) -> bool:
|
||||
def disable_encryption(self, project_id: str, master_password: str) -> bool:
|
||||
"""禁用项目加密"""
|
||||
# 验证密码
|
||||
if not self.verify_encryption_password(project_id, master_password):
|
||||
@@ -587,29 +585,24 @@ class SecurityManager:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE encryption_configs
|
||||
SET is_enabled = 0, updated_at = ?
|
||||
WHERE project_id = ?
|
||||
""", (datetime.now().isoformat(), project_id))
|
||||
""",
|
||||
(datetime.now().isoformat(), project_id),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
# 记录审计日志
|
||||
self.log_audit(
|
||||
action_type=AuditActionType.ENCRYPTION_DISABLE,
|
||||
resource_type="project",
|
||||
resource_id=project_id
|
||||
)
|
||||
self.log_audit(action_type=AuditActionType.ENCRYPTION_DISABLE, resource_type="project", resource_id=project_id)
|
||||
|
||||
return True
|
||||
|
||||
def verify_encryption_password(
|
||||
self,
|
||||
project_id: str,
|
||||
password: str
|
||||
) -> bool:
|
||||
def verify_encryption_password(self, project_id: str, password: str) -> bool:
|
||||
"""验证加密密码"""
|
||||
if not CRYPTO_AVAILABLE:
|
||||
return False
|
||||
@@ -617,10 +610,7 @@ class SecurityManager:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute(
|
||||
"SELECT master_key_hash, salt FROM encryption_configs WHERE project_id = ?",
|
||||
(project_id,)
|
||||
)
|
||||
cursor.execute("SELECT master_key_hash, salt FROM encryption_configs WHERE project_id = ?", (project_id,))
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
@@ -638,10 +628,7 @@ class SecurityManager:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute(
|
||||
"SELECT * FROM encryption_configs WHERE project_id = ?",
|
||||
(project_id,)
|
||||
)
|
||||
cursor.execute("SELECT * FROM encryption_configs WHERE project_id = ?", (project_id,))
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
@@ -657,15 +644,10 @@ class SecurityManager:
|
||||
master_key_hash=row[5],
|
||||
salt=row[6],
|
||||
created_at=row[7],
|
||||
updated_at=row[8]
|
||||
updated_at=row[8],
|
||||
)
|
||||
|
||||
def encrypt_data(
|
||||
self,
|
||||
data: str,
|
||||
password: str,
|
||||
salt: str | None = None
|
||||
) -> tuple[str, str]:
|
||||
def encrypt_data(self, data: str, password: str, salt: str | None = None) -> tuple[str, str]:
|
||||
"""加密数据"""
|
||||
if not CRYPTO_AVAILABLE:
|
||||
raise RuntimeError("cryptography library not available")
|
||||
@@ -679,12 +661,7 @@ class SecurityManager:
|
||||
|
||||
return base64.b64encode(encrypted).decode(), salt
|
||||
|
||||
def decrypt_data(
|
||||
self,
|
||||
encrypted_data: str,
|
||||
password: str,
|
||||
salt: str
|
||||
) -> str:
|
||||
def decrypt_data(self, encrypted_data: str, password: str, salt: str) -> str:
|
||||
"""解密数据"""
|
||||
if not CRYPTO_AVAILABLE:
|
||||
raise RuntimeError("cryptography library not available")
|
||||
@@ -705,7 +682,7 @@ class SecurityManager:
|
||||
pattern: str | None = None,
|
||||
replacement: str | None = None,
|
||||
description: str | None = None,
|
||||
priority: int = 0
|
||||
priority: int = 0,
|
||||
) -> MaskingRule:
|
||||
"""创建脱敏规则"""
|
||||
# 使用预定义规则或自定义规则
|
||||
@@ -722,22 +699,33 @@ class SecurityManager:
|
||||
pattern=pattern or "",
|
||||
replacement=replacement or "****",
|
||||
description=description,
|
||||
priority=priority
|
||||
priority=priority,
|
||||
)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO masking_rules
|
||||
(id, project_id, name, rule_type, pattern, replacement,
|
||||
is_active, priority, description, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
rule.id, rule.project_id, rule.name, rule.rule_type,
|
||||
rule.pattern, rule.replacement, int(rule.is_active),
|
||||
rule.priority, rule.description, rule.created_at, rule.updated_at
|
||||
))
|
||||
""",
|
||||
(
|
||||
rule.id,
|
||||
rule.project_id,
|
||||
rule.name,
|
||||
rule.rule_type,
|
||||
rule.pattern,
|
||||
rule.replacement,
|
||||
int(rule.is_active),
|
||||
rule.priority,
|
||||
rule.description,
|
||||
rule.created_at,
|
||||
rule.updated_at,
|
||||
),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
@@ -747,16 +735,12 @@ class SecurityManager:
|
||||
action_type=AuditActionType.DATA_MASKING,
|
||||
resource_type="project",
|
||||
resource_id=project_id,
|
||||
action_details={"action": "create_rule", "rule_name": name}
|
||||
action_details={"action": "create_rule", "rule_name": name},
|
||||
)
|
||||
|
||||
return rule
|
||||
|
||||
def get_masking_rules(
|
||||
self,
|
||||
project_id: str,
|
||||
active_only: bool = True
|
||||
) -> list[MaskingRule]:
|
||||
def get_masking_rules(self, project_id: str, active_only: bool = True) -> list[MaskingRule]:
|
||||
"""获取脱敏规则"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
@@ -775,27 +759,25 @@ class SecurityManager:
|
||||
|
||||
rules = []
|
||||
for row in rows:
|
||||
rules.append(MaskingRule(
|
||||
id=row[0],
|
||||
project_id=row[1],
|
||||
name=row[2],
|
||||
rule_type=row[3],
|
||||
pattern=row[4],
|
||||
replacement=row[5],
|
||||
is_active=bool(row[6]),
|
||||
priority=row[7],
|
||||
description=row[8],
|
||||
created_at=row[9],
|
||||
updated_at=row[10]
|
||||
))
|
||||
rules.append(
|
||||
MaskingRule(
|
||||
id=row[0],
|
||||
project_id=row[1],
|
||||
name=row[2],
|
||||
rule_type=row[3],
|
||||
pattern=row[4],
|
||||
replacement=row[5],
|
||||
is_active=bool(row[6]),
|
||||
priority=row[7],
|
||||
description=row[8],
|
||||
created_at=row[9],
|
||||
updated_at=row[10],
|
||||
)
|
||||
)
|
||||
|
||||
return rules
|
||||
|
||||
def update_masking_rule(
|
||||
self,
|
||||
rule_id: str,
|
||||
**kwargs
|
||||
) -> MaskingRule | None:
|
||||
def update_masking_rule(self, rule_id: str, **kwargs) -> MaskingRule | None:
|
||||
"""更新脱敏规则"""
|
||||
allowed_fields = ["name", "pattern", "replacement", "is_active", "priority", "description"]
|
||||
|
||||
@@ -818,11 +800,14 @@ class SecurityManager:
|
||||
params.append(datetime.now().isoformat())
|
||||
params.append(rule_id)
|
||||
|
||||
cursor.execute(f"""
|
||||
cursor.execute(
|
||||
f"""
|
||||
UPDATE masking_rules
|
||||
SET {', '.join(set_clauses)}
|
||||
WHERE id = ?
|
||||
""", params)
|
||||
""",
|
||||
params,
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
@@ -848,7 +833,7 @@ class SecurityManager:
|
||||
priority=row[7],
|
||||
description=row[8],
|
||||
created_at=row[9],
|
||||
updated_at=row[10]
|
||||
updated_at=row[10],
|
||||
)
|
||||
|
||||
def delete_masking_rule(self, rule_id: str) -> bool:
|
||||
@@ -864,12 +849,7 @@ class SecurityManager:
|
||||
|
||||
return success
|
||||
|
||||
def apply_masking(
|
||||
self,
|
||||
text: str,
|
||||
project_id: str,
|
||||
rule_types: list[MaskingRuleType] | None = None
|
||||
) -> str:
|
||||
def apply_masking(self, text: str, project_id: str, rule_types: list[MaskingRuleType] | None = None) -> str:
|
||||
"""应用脱敏规则到文本"""
|
||||
rules = self.get_masking_rules(project_id)
|
||||
|
||||
@@ -884,22 +864,14 @@ class SecurityManager:
|
||||
continue
|
||||
|
||||
try:
|
||||
masked_text = re.sub(
|
||||
rule.pattern,
|
||||
rule.replacement,
|
||||
masked_text
|
||||
)
|
||||
masked_text = re.sub(rule.pattern, rule.replacement, masked_text)
|
||||
except re.error:
|
||||
# 忽略无效的正则表达式
|
||||
continue
|
||||
|
||||
return masked_text
|
||||
|
||||
def apply_masking_to_entity(
|
||||
self,
|
||||
entity_data: dict[str, Any],
|
||||
project_id: str
|
||||
) -> dict[str, Any]:
|
||||
def apply_masking_to_entity(self, entity_data: dict[str, Any], project_id: str) -> dict[str, Any]:
|
||||
"""对实体数据应用脱敏"""
|
||||
masked_data = entity_data.copy()
|
||||
|
||||
@@ -924,7 +896,7 @@ class SecurityManager:
|
||||
allowed_ips: list[str] | None = None,
|
||||
time_restrictions: dict | None = None,
|
||||
max_access_count: int | None = None,
|
||||
require_approval: bool = False
|
||||
require_approval: bool = False,
|
||||
) -> DataAccessPolicy:
|
||||
"""创建数据访问策略"""
|
||||
policy = DataAccessPolicy(
|
||||
@@ -937,36 +909,43 @@ class SecurityManager:
|
||||
allowed_ips=json.dumps(allowed_ips) if allowed_ips else None,
|
||||
time_restrictions=json.dumps(time_restrictions) if time_restrictions else None,
|
||||
max_access_count=max_access_count,
|
||||
require_approval=require_approval
|
||||
require_approval=require_approval,
|
||||
)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO data_access_policies
|
||||
(id, project_id, name, description, allowed_users, allowed_roles,
|
||||
allowed_ips, time_restrictions, max_access_count, require_approval,
|
||||
is_active, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
policy.id, policy.project_id, policy.name, policy.description,
|
||||
policy.allowed_users, policy.allowed_roles, policy.allowed_ips,
|
||||
policy.time_restrictions, policy.max_access_count,
|
||||
int(policy.require_approval), int(policy.is_active),
|
||||
policy.created_at, policy.updated_at
|
||||
))
|
||||
""",
|
||||
(
|
||||
policy.id,
|
||||
policy.project_id,
|
||||
policy.name,
|
||||
policy.description,
|
||||
policy.allowed_users,
|
||||
policy.allowed_roles,
|
||||
policy.allowed_ips,
|
||||
policy.time_restrictions,
|
||||
policy.max_access_count,
|
||||
int(policy.require_approval),
|
||||
int(policy.is_active),
|
||||
policy.created_at,
|
||||
policy.updated_at,
|
||||
),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return policy
|
||||
|
||||
def get_access_policies(
|
||||
self,
|
||||
project_id: str,
|
||||
active_only: bool = True
|
||||
) -> list[DataAccessPolicy]:
|
||||
def get_access_policies(self, project_id: str, active_only: bool = True) -> list[DataAccessPolicy]:
|
||||
"""获取数据访问策略"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
@@ -983,38 +962,34 @@ class SecurityManager:
|
||||
|
||||
policies = []
|
||||
for row in rows:
|
||||
policies.append(DataAccessPolicy(
|
||||
id=row[0],
|
||||
project_id=row[1],
|
||||
name=row[2],
|
||||
description=row[3],
|
||||
allowed_users=row[4],
|
||||
allowed_roles=row[5],
|
||||
allowed_ips=row[6],
|
||||
time_restrictions=row[7],
|
||||
max_access_count=row[8],
|
||||
require_approval=bool(row[9]),
|
||||
is_active=bool(row[10]),
|
||||
created_at=row[11],
|
||||
updated_at=row[12]
|
||||
))
|
||||
policies.append(
|
||||
DataAccessPolicy(
|
||||
id=row[0],
|
||||
project_id=row[1],
|
||||
name=row[2],
|
||||
description=row[3],
|
||||
allowed_users=row[4],
|
||||
allowed_roles=row[5],
|
||||
allowed_ips=row[6],
|
||||
time_restrictions=row[7],
|
||||
max_access_count=row[8],
|
||||
require_approval=bool(row[9]),
|
||||
is_active=bool(row[10]),
|
||||
created_at=row[11],
|
||||
updated_at=row[12],
|
||||
)
|
||||
)
|
||||
|
||||
return policies
|
||||
|
||||
def check_access_permission(
|
||||
self,
|
||||
policy_id: str,
|
||||
user_id: str,
|
||||
user_ip: str | None = None
|
||||
self, policy_id: str, user_id: str, user_ip: str | None = None
|
||||
) -> tuple[bool, str | None]:
|
||||
"""检查访问权限"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute(
|
||||
"SELECT * FROM data_access_policies WHERE id = ? AND is_active = 1",
|
||||
(policy_id,)
|
||||
)
|
||||
cursor.execute("SELECT * FROM data_access_policies WHERE id = ? AND is_active = 1", (policy_id,))
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
@@ -1034,7 +1009,7 @@ class SecurityManager:
|
||||
require_approval=bool(row[9]),
|
||||
is_active=bool(row[10]),
|
||||
created_at=row[11],
|
||||
updated_at=row[12]
|
||||
updated_at=row[12],
|
||||
)
|
||||
|
||||
# 检查用户白名单
|
||||
@@ -1074,11 +1049,14 @@ class SecurityManager:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT * FROM access_requests
|
||||
WHERE policy_id = ? AND user_id = ? AND status = 'approved'
|
||||
AND (expires_at IS NULL OR expires_at > ?)
|
||||
""", (policy_id, user_id, datetime.now().isoformat()))
|
||||
""",
|
||||
(policy_id, user_id, datetime.now().isoformat()),
|
||||
)
|
||||
|
||||
request = cursor.fetchone()
|
||||
conn.close()
|
||||
@@ -1104,11 +1082,7 @@ class SecurityManager:
|
||||
return ip == pattern
|
||||
|
||||
def create_access_request(
|
||||
self,
|
||||
policy_id: str,
|
||||
user_id: str,
|
||||
request_reason: str | None = None,
|
||||
expires_hours: int = 24
|
||||
self, policy_id: str, user_id: str, request_reason: str | None = None, expires_hours: int = 24
|
||||
) -> AccessRequest:
|
||||
"""创建访问请求"""
|
||||
request = AccessRequest(
|
||||
@@ -1116,21 +1090,28 @@ class SecurityManager:
|
||||
policy_id=policy_id,
|
||||
user_id=user_id,
|
||||
request_reason=request_reason,
|
||||
expires_at=(datetime.now() + timedelta(hours=expires_hours)).isoformat()
|
||||
expires_at=(datetime.now() + timedelta(hours=expires_hours)).isoformat(),
|
||||
)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO access_requests
|
||||
(id, policy_id, user_id, request_reason, status, expires_at, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
request.id, request.policy_id, request.user_id,
|
||||
request.request_reason, request.status, request.expires_at,
|
||||
request.created_at
|
||||
))
|
||||
""",
|
||||
(
|
||||
request.id,
|
||||
request.policy_id,
|
||||
request.user_id,
|
||||
request.request_reason,
|
||||
request.status,
|
||||
request.expires_at,
|
||||
request.created_at,
|
||||
),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
@@ -1138,10 +1119,7 @@ class SecurityManager:
|
||||
return request
|
||||
|
||||
def approve_access_request(
|
||||
self,
|
||||
request_id: str,
|
||||
approved_by: str,
|
||||
expires_hours: int = 24
|
||||
self, request_id: str, approved_by: str, expires_hours: int = 24
|
||||
) -> AccessRequest | None:
|
||||
"""批准访问请求"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
@@ -1150,11 +1128,14 @@ class SecurityManager:
|
||||
expires_at = (datetime.now() + timedelta(hours=expires_hours)).isoformat()
|
||||
approved_at = datetime.now().isoformat()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE access_requests
|
||||
SET status = 'approved', approved_by = ?, approved_at = ?, expires_at = ?
|
||||
WHERE id = ?
|
||||
""", (approved_by, approved_at, expires_at, request_id))
|
||||
""",
|
||||
(approved_by, approved_at, expires_at, request_id),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
|
||||
@@ -1175,23 +1156,22 @@ class SecurityManager:
|
||||
approved_by=row[5],
|
||||
approved_at=row[6],
|
||||
expires_at=row[7],
|
||||
created_at=row[8]
|
||||
created_at=row[8],
|
||||
)
|
||||
|
||||
def reject_access_request(
|
||||
self,
|
||||
request_id: str,
|
||||
rejected_by: str
|
||||
) -> AccessRequest | None:
|
||||
def reject_access_request(self, request_id: str, rejected_by: str) -> AccessRequest | None:
|
||||
"""拒绝访问请求"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE access_requests
|
||||
SET status = 'rejected', approved_by = ?
|
||||
WHERE id = ?
|
||||
""", (rejected_by, request_id))
|
||||
""",
|
||||
(rejected_by, request_id),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
|
||||
@@ -1211,7 +1191,7 @@ class SecurityManager:
|
||||
approved_by=row[5],
|
||||
approved_at=row[6],
|
||||
expires_at=row[7],
|
||||
created_at=row[8]
|
||||
created_at=row[8],
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user