mirror of
https://github.com/YFGaia/dify-plus.git
synced 2026-06-12 18:11:42 +08:00
feat: 新增sandbox-full支持
This commit is contained in:
@@ -68,6 +68,7 @@ from .provider import (
|
||||
TenantDefaultModel,
|
||||
TenantPreferredModelProvider,
|
||||
)
|
||||
from .system_extend import SystemIntegrationExtend # Extend System Integration
|
||||
from .source import DataSourceApiKeyAuthBinding, DataSourceOauthBinding
|
||||
from .task import CeleryTask, CeleryTaskSet
|
||||
from .tools import (
|
||||
@@ -184,4 +185,5 @@ __all__ = [
|
||||
"WorkflowToolProvider",
|
||||
"WorkflowType",
|
||||
"db",
|
||||
"SystemIntegrationExtend", # Extend System Integration
|
||||
]
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
from extensions.ext_database import db
|
||||
|
||||
from .types import StringUUID
|
||||
|
||||
|
||||
class AccountMoneyExtend(db.Model):
|
||||
__tablename__ = "account_money_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="account_money_pkey"),
|
||||
db.Index("idx_account_money_account_id", "account_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
account_id = db.Column(StringUUID, nullable=False)
|
||||
total_quota = db.Column(db.Numeric(16, 7))
|
||||
used_quota = db.Column(db.Numeric(16, 7))
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
|
||||
class AccountLayoverRecordExtend(db.Model):
|
||||
__tablename__ = "account_layover_record_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="account_layover_record_extend_pkey"),
|
||||
db.Index("idx_account_layover_record_account_id", "account_id"),
|
||||
db.Index("idx_account_layover_record_forwarding_id", "forwarding_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
account_id = db.Column(StringUUID, nullable=False)
|
||||
forwarding_id = db.Column(StringUUID, nullable=False)
|
||||
money = db.Column(db.Numeric(16, 7))
|
||||
info = db.Column(db.JSON, default={})
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
@@ -0,0 +1,19 @@
|
||||
from extensions.ext_database import db
|
||||
|
||||
from .types import StringUUID
|
||||
|
||||
|
||||
class AccountMoneyMonthlyStatExtend(db.Model):
|
||||
__tablename__ = "account_money_monthly_stat_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="account_money_monthly_stat_pkey"),
|
||||
db.Index("idx_account_money_monthly_stat_account_id", "account_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
account_id = db.Column(StringUUID, nullable=False)
|
||||
total_quota = db.Column(db.Numeric(16, 7))
|
||||
used_quota = db.Column(db.Numeric(16, 7))
|
||||
stat_at = db.Column(db.DateTime, nullable=False)
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
@@ -0,0 +1,82 @@
|
||||
from extensions.ext_database import db
|
||||
|
||||
from .types import StringUUID
|
||||
|
||||
|
||||
class ApiTokenMoneyExtend(db.Model):
|
||||
__tablename__ = "api_token_money_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="api_token_money_extend_pkey"),
|
||||
db.Index("api_tokens_money_app_token_id_idx", "app_token_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
app_token_id = db.Column(StringUUID, nullable=True) # 密钥ID
|
||||
accumulated_quota = db.Column(db.Numeric(16, 7)) # 已使用额度(累计不归零)
|
||||
day_used_quota = db.Column(db.Numeric(16, 7)) # 当天使用额度(定时脚本每日更新)
|
||||
month_used_quota = db.Column(db.Numeric(16, 7)) # 当月使用额度(定时脚本每月更新)
|
||||
day_limit_quota = db.Column(db.Numeric(16, 7)) # 每天使用额度限制(创建密钥时设置)
|
||||
month_limit_quota = db.Column(db.Numeric(16, 7)) # 每月使用额度限制(创建密钥时设置)
|
||||
description = db.Column(db.String(50)) # 密钥描述
|
||||
is_deleted = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
|
||||
# 日快照统计表
|
||||
class ApiTokenMoneyDailyStatExtend(db.Model):
|
||||
__tablename__ = "api_token_money_daily_stat_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="api_token_money_daily_stat_pkey"),
|
||||
db.Index("idx_api_token_money_daily_stat_app_token_id", "app_token_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
app_token_id = db.Column(StringUUID, nullable=False)
|
||||
accumulated_quota = db.Column(db.Numeric(16, 7)) # 已使用额度(累计不归零)
|
||||
day_used_quota = db.Column(db.Numeric(16, 7)) # 当天使用额度(定时脚本每日更新)
|
||||
day_limit_quota = db.Column(db.Numeric(16, 7)) # 每天使用额度限制(创建密钥时设置)
|
||||
stat_at = db.Column(db.DateTime, nullable=False)
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
|
||||
# 月快照统计表
|
||||
class ApiTokenMoneyMonthlyStatExtend(db.Model):
|
||||
__tablename__ = "api_token_money_monthly_stat_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="api_token_money_monthly_stat_pkey"),
|
||||
db.Index("idx_api_token_money_monthly_stat_app_token_id", "app_token_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
app_token_id = db.Column(StringUUID, nullable=False)
|
||||
accumulated_quota = db.Column(db.Numeric(16, 7)) # 已使用额度(累计不归零)
|
||||
month_used_quota = db.Column(db.Numeric(16, 7)) # 当月使用额度(定时脚本每月更新)
|
||||
month_limit_quota = db.Column(db.Numeric(16, 7)) # 每月使用额度限制(创建密钥时设置)
|
||||
stat_at = db.Column(db.DateTime, nullable=False)
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
|
||||
# 密钥 - 对话消息关联表
|
||||
class ApiTokenMessageJoinsExtend(db.Model):
|
||||
__tablename__ = "api_token_message_joins_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="api_token_message_joins_extend_pkey"),
|
||||
db.Index("api_token_message_joins_extend_app_token_id_idx", "app_token_id"),
|
||||
db.Index("api_token_message_joins_extend_record_id_idx", "record_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
app_token_id = db.Column(StringUUID, nullable=True) # 密钥ID
|
||||
record_id = db.Column(StringUUID, nullable=True) # 关联记录ID
|
||||
app_mode = db.Column(db.String(255), nullable=True) # 应用类型
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
def add_app_token_record_id(self):
|
||||
db.session.add(
|
||||
ApiTokenMessageJoinsExtend(app_token_id=self.app_token_id, record_id=self.record_id, app_mode=self.app_mode)
|
||||
)
|
||||
db.session.commit()
|
||||
+54
-2
@@ -219,6 +219,18 @@ class App(db.Model): # type: ignore[name-defined]
|
||||
return tags or []
|
||||
|
||||
|
||||
class AppStatisticsExtend(db.Model):
|
||||
__tablename__ = "app_statistics_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="app_statistics_extend_pkey"),
|
||||
db.Index("app_statistics_extend_app_id_idx", "app_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
app_id = db.Column(StringUUID, nullable=False)
|
||||
number = db.Column(db.Integer, nullable=False, default=0)
|
||||
|
||||
|
||||
class AppModelConfig(db.Model): # type: ignore[name-defined]
|
||||
__tablename__ = "app_model_configs"
|
||||
__table_args__ = (db.PrimaryKeyConstraint("id", name="app_model_config_pkey"), db.Index("app_app_id_idx", "app_id"))
|
||||
@@ -466,6 +478,32 @@ class AppModelConfig(db.Model): # type: ignore[name-defined]
|
||||
return new_app_model_config
|
||||
|
||||
|
||||
class RecommendedCategoryExtend(db.Model):
|
||||
__tablename__ = "recommended_category_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="category_extend_id_pkey"),
|
||||
db.Index("idx_extend_tag_bind_tag_id", "tag_id"),
|
||||
db.Index("idx_extend_table", "table"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, primary_key=True, server_default=db.text("uuid_generate_v4()"))
|
||||
table = db.Column(db.String(255), nullable=False)
|
||||
tag_id = db.Column(StringUUID, nullable=True)
|
||||
|
||||
|
||||
class RecommendedAppsCategoryJoinExtend(db.Model):
|
||||
__tablename__ = "recommended_apps_category_join_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="recommended_apps_category_id_pkey"),
|
||||
db.Index("idx_recommended_id", "recommended_id"),
|
||||
db.Index("idx_recommended_category_id", "category_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, primary_key=True, server_default=db.text("uuid_generate_v4()"))
|
||||
recommended_id = db.Column(StringUUID, nullable=False)
|
||||
category_id = db.Column(StringUUID, nullable=False)
|
||||
|
||||
|
||||
class RecommendedApp(db.Model): # type: ignore[name-defined]
|
||||
__tablename__ = "recommended_apps"
|
||||
__table_args__ = (
|
||||
@@ -739,9 +777,23 @@ class Conversation(db.Model): # type: ignore[name-defined]
|
||||
def from_end_user_session_id(self):
|
||||
if self.from_end_user_id:
|
||||
end_user = db.session.query(EndUser).filter(EndUser.id == self.from_end_user_id).first()
|
||||
if end_user:
|
||||
# Extend: start In the Log and Annotation User columns, the end_user displayed is changed to the
|
||||
# associated username
|
||||
if end_user is not None and (
|
||||
end_user.external_user_id is None
|
||||
or (end_user.external_user_id is not None and len(end_user.external_user_id) == 0)
|
||||
):
|
||||
return end_user.session_id
|
||||
|
||||
elif end_user is not None:
|
||||
user: Account = db.session.query(Account).filter(Account.id == end_user.external_user_id).first()
|
||||
if user:
|
||||
return user.name
|
||||
elif self.from_account_id:
|
||||
user: Account = db.session.query(Account).filter(Account.id == self.from_account_id).first()
|
||||
if user:
|
||||
return user.name
|
||||
# Extend: stop In the Log and Annotation User columns, the end_user displayed is changed to the
|
||||
# associated username
|
||||
return None
|
||||
|
||||
@property
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from extensions.ext_database import db
|
||||
|
||||
from .types import StringUUID
|
||||
|
||||
|
||||
class EndUserAccountJoinsExtend(db.Model):
|
||||
__tablename__ = "end_user_account_joins_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="end_user_account_joins_pkey"),
|
||||
db.Index("end_user_account_joins_account_id_idx", "account_id"),
|
||||
db.Index("end_user_account_joins_end_user_id_app_id_idx", "end_user_id", "app_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
end_user_id = db.Column(StringUUID, nullable=False)
|
||||
account_id = db.Column(StringUUID, nullable=False)
|
||||
app_id = db.Column(StringUUID, nullable=False)
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
@@ -0,0 +1,51 @@
|
||||
from Crypto.Util.Padding import unpad
|
||||
from Crypto.Cipher import Blowfish
|
||||
from configs import dify_config
|
||||
from .engine import db
|
||||
import base64
|
||||
|
||||
class SystemIntegrationClassify:
|
||||
SYSTEM_INTEGRATION_DINGTALK = 1 # 钉钉
|
||||
SYSTEM_INTEGRATION_WEIXIN = 2 # 微信
|
||||
SYSTEM_INTEGRATION_FEI_SU = 3 # 飞书
|
||||
|
||||
|
||||
class SystemIntegrationExtend(db.Model):
|
||||
__tablename__ = "system_integration_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="system_integration_joins_pkey"),
|
||||
db.Index("system_integration_joins_classify_idx", "classify"),
|
||||
)
|
||||
id = db.Column(db.BigInteger, db.Sequence("system_integration_id_sequence"), primary_key=True, autoincrement=True)
|
||||
classify = db.Column(db.Integer, nullable=False, server_default=db.text("1"))
|
||||
status = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||
corp_id = db.Column(db.String(120), nullable=True)
|
||||
agent_id = db.Column(db.String(120), nullable=True)
|
||||
app_key = db.Column(db.String(120), nullable=True)
|
||||
app_secret = db.Column(db.Text, nullable=True)
|
||||
|
||||
def decodeSecret(self):
|
||||
if len(self.app_secret) == 0:
|
||||
return ""
|
||||
# Decode the base64 encoded text
|
||||
ciphertext = base64.b64decode(self.app_secret)
|
||||
|
||||
# Ensure the text length is sufficient
|
||||
if len(ciphertext) < Blowfish.block_size:
|
||||
raise ValueError("Invalid ciphertext")
|
||||
|
||||
# Extract the initialization vector (IV) from the beginning of the ciphertext
|
||||
iv = ciphertext[:Blowfish.block_size]
|
||||
ciphertext = ciphertext[Blowfish.block_size:]
|
||||
|
||||
# Create the cipher object and decrypt the plaintext
|
||||
cipher = Blowfish.new(dify_config.SECRET_KEY.encode('utf-8'), Blowfish.MODE_CBC, iv)
|
||||
plaintext = cipher.decrypt(ciphertext)
|
||||
|
||||
# Unpad the plaintext using PKCS7 unpadding
|
||||
try:
|
||||
plaintext = unpad(plaintext, Blowfish.block_size)
|
||||
except ValueError as e:
|
||||
raise ValueError("Invalid padding") from e
|
||||
|
||||
return plaintext.decode('utf-8')
|
||||
@@ -0,0 +1,50 @@
|
||||
from extensions.ext_database import db
|
||||
|
||||
from .types import StringUUID
|
||||
|
||||
|
||||
class TenantModelSyncExtend(db.Model):
|
||||
"""
|
||||
模型-工作区同步关联
|
||||
"""
|
||||
|
||||
__tablename__ = "tenant_model_sync_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="tenant_model_sync_extend_pkey"),
|
||||
db.Index("tenant_model_sync_extend_tenant_idx", "tenant_id"),
|
||||
db.Index("tenant_model_sync_extend_model_idx", "model_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
tenant_id = db.Column(StringUUID, nullable=False)
|
||||
model_id = db.Column(StringUUID, nullable=False)
|
||||
origin_model_id = db.Column(db.String(255), nullable=False)
|
||||
is_all = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
def __repr__(self):
|
||||
return f"<tenant_model_sync(id={self.id}, tenant_id={self.tenant_id}, model_id='{self.model_id}', is_all='{self.is_all}')>"
|
||||
|
||||
|
||||
class ModelSyncConfigExtend(db.Model):
|
||||
"""
|
||||
模型-同步配置表
|
||||
"""
|
||||
|
||||
__tablename__ = "model_sync_config_extend"
|
||||
__table_args__ = (
|
||||
db.PrimaryKeyConstraint("id", name="model_sync_config_extend_pkey"),
|
||||
db.UniqueConstraint("model_id", name="unique_model_id"),
|
||||
)
|
||||
|
||||
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
|
||||
model_id = db.Column(StringUUID, nullable=True)
|
||||
is_all = db.Column(db.Boolean, nullable=True, server_default=db.text("true"))
|
||||
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
|
||||
|
||||
def __repr__(self):
|
||||
return f"<model_sync_config_extend(id={self.id}, model_id='{self.model_id}', is_all='{self.is_all}')>"
|
||||
+44
-3
@@ -771,10 +771,51 @@ class WorkflowAppLog(db.Model): # type: ignore[name-defined]
|
||||
|
||||
@property
|
||||
def created_by_end_user(self):
|
||||
from models.model import EndUser
|
||||
|
||||
from models.model_extend import EndUserAccountJoinsExtend
|
||||
# Extend: start /apps/<uuid:app_id>/workflow-app-logs update end_user to account
|
||||
created_by_role = CreatedByRole(self.created_by_role)
|
||||
return db.session.get(EndUser, self.created_by) if created_by_role == CreatedByRole.END_USER else None
|
||||
if created_by_role == CreatedByRole.END_USER:
|
||||
end_user = db.session.query(EndUserAccountJoinsExtend).filter(
|
||||
EndUserAccountJoinsExtend.end_user_id == self.created_by).first()
|
||||
# associated username
|
||||
if end_user is not None and (
|
||||
end_user.account_id is None
|
||||
or (end_user.account_id is not None and len(end_user.account_id) == 0)
|
||||
):
|
||||
return self.created_by
|
||||
elif end_user is not None:
|
||||
user: Account = db.session.query(Account).filter(Account.id == end_user.account_id).first()
|
||||
if user:
|
||||
return {
|
||||
"id": user.id,
|
||||
"type": user.status,
|
||||
"is_anonymous": "true",
|
||||
"session_id": user.name,
|
||||
}
|
||||
else:
|
||||
from models.model import EndUser
|
||||
end_user = db.session.query(EndUser).filter(EndUser.id == self.created_by).first()
|
||||
if end_user is not None and len(end_user.external_user_id) > 0:
|
||||
user: Account = db.session.query(Account).filter(Account.id == end_user.external_user_id).first()
|
||||
if user:
|
||||
return {
|
||||
"id": user.id,
|
||||
"type": user.status,
|
||||
"is_anonymous": "true",
|
||||
"session_id": user.name,
|
||||
}
|
||||
return end_user
|
||||
elif len(self.created_by) > 0:
|
||||
user: Account = db.session.query(Account).filter(Account.id == self.created_by).first()
|
||||
if user:
|
||||
return {
|
||||
"id": user.id,
|
||||
"type": user.status,
|
||||
"is_anonymous": "true",
|
||||
"session_id": user.name,
|
||||
}
|
||||
return None
|
||||
# Extend: stop /apps/<uuid:app_id>/workflow-app-logs update end_user to account
|
||||
|
||||
|
||||
class ConversationVariable(db.Model): # type: ignore[name-defined]
|
||||
|
||||
Reference in New Issue
Block a user