feat(feishu): 添加飞书入站事件inbox和混合数据库协调功能 - 实现飞书入站事件持久化inbox机制,支持状态管理、租约锁定和重试退避 - 添加混合数据库基线协调工具,确保平台PostgreSQL结构安全对齐 - 增加运行组件心跳检测和readiness就绪检查机制 - 实现app_ticket事件的安全轮换和验证处理 - 添加生产环境运行编排和fail-closed安全机制 - 支持webhook快速确认和长连接独立进程处理 - 完善个人数据擦除时的待处理事件清理功能 ```
95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
from enum import StrEnum
|
|
from typing import Iterable
|
|
|
|
|
|
class FeishuUserRole(StrEnum):
|
|
USER = "user"
|
|
ADMIN = "admin"
|
|
|
|
|
|
class FeishuUserStatus(StrEnum):
|
|
ACTIVE = "active"
|
|
DISABLED = "disabled"
|
|
|
|
|
|
class FeishuCapability(StrEnum):
|
|
PERSONAL_AI = "personal_ai"
|
|
PERSONAL_DATA = "personal_data"
|
|
PRIVATE_SUBSCRIPTION = "private_subscription"
|
|
PERSONAL_MARKET = "personal_market"
|
|
COMPANY_REPORTS = "company_reports"
|
|
COMPANY_RULES = "company_rules"
|
|
USER_ADMINISTRATION = "user_administration"
|
|
GROUP_SUBSCRIPTION = "group_subscription"
|
|
|
|
|
|
class FeishuUserAuditAction(StrEnum):
|
|
REGISTER = "feishu.user.register"
|
|
AUTHENTICATE = "feishu.user.authenticate"
|
|
PERMISSION_DENIED = "feishu.permission.denied"
|
|
LIST = "feishu.user.list"
|
|
READ = "feishu.user.read"
|
|
UPDATE = "feishu.user.update"
|
|
UPDATE_DENIED = "feishu.user.update_denied"
|
|
|
|
|
|
FEISHU_USER_CODE_PREFIX = "FSU"
|
|
FEISHU_USER_TARGET_TYPE = "feishu-user"
|
|
DEFAULT_FEISHU_USER_TIMEZONE = "Asia/Shanghai"
|
|
LAST_ACTIVE_ADMIN_ERROR = "The last active Feishu administrator cannot be changed"
|
|
FEISHU_USER_NOT_FOUND = "Feishu user not found"
|
|
INVALID_FEISHU_IDENTITY = "tenant_key and open_id are required"
|
|
INVALID_FEISHU_TIMEZONE = "Invalid IANA timezone"
|
|
INVALID_QUIET_HOURS = "quiet_hours_start and quiet_hours_end must both be set or cleared"
|
|
INVALID_ADMIN_IDENTITY = (
|
|
"FEISHU_ADMIN_IDENTITIES entries must use tenant_key:open_id format"
|
|
)
|
|
|
|
_USER_CAPABILITIES = frozenset(
|
|
{
|
|
FeishuCapability.PERSONAL_AI,
|
|
FeishuCapability.PERSONAL_DATA,
|
|
FeishuCapability.PRIVATE_SUBSCRIPTION,
|
|
FeishuCapability.PERSONAL_MARKET,
|
|
}
|
|
)
|
|
_ADMIN_CAPABILITIES = frozenset(FeishuCapability)
|
|
|
|
|
|
def capabilities_for_role(role: str | FeishuUserRole) -> frozenset[FeishuCapability]:
|
|
"""Return the fixed capability set for a Feishu user role."""
|
|
|
|
if FeishuUserRole(role) == FeishuUserRole.ADMIN:
|
|
return _ADMIN_CAPABILITIES
|
|
return _USER_CAPABILITIES
|
|
|
|
|
|
def parse_admin_identities(
|
|
value: str | Iterable[str] | None,
|
|
) -> frozenset[tuple[str, str]]:
|
|
"""Parse exact tenant/open-id pairs used only for initial administrator creation."""
|
|
|
|
if value is None:
|
|
return frozenset()
|
|
entries = value.split(",") if isinstance(value, str) else value
|
|
identities: set[tuple[str, str]] = set()
|
|
for entry in entries:
|
|
text = str(entry).strip()
|
|
if not text:
|
|
continue
|
|
tenant_key, separator, open_id = text.partition(":")
|
|
tenant_key = tenant_key.strip()
|
|
open_id = open_id.strip()
|
|
if (
|
|
not separator
|
|
or not tenant_key
|
|
or not open_id
|
|
or ":" in open_id
|
|
or len(tenant_key) > 128
|
|
or len(open_id) > 128
|
|
or any(character in text for character in "\r\n")
|
|
):
|
|
raise ValueError(INVALID_ADMIN_IDENTITY)
|
|
identities.add((tenant_key, open_id))
|
|
return frozenset(identities)
|