mirror of https://github.com/jumpserver/jumpserver
commit
4d37dca0de
|
@ -8,7 +8,7 @@ from rest_framework import serializers
|
||||||
from rest_framework.fields import ChoiceField, empty
|
from rest_framework.fields import ChoiceField, empty
|
||||||
|
|
||||||
from common.db.fields import TreeChoices, JSONManyToManyField as ModelJSONManyToManyField
|
from common.db.fields import TreeChoices, JSONManyToManyField as ModelJSONManyToManyField
|
||||||
from common.utils import decrypt_password
|
from common.utils import decrypt_password, is_uuid
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"ReadableHiddenField",
|
"ReadableHiddenField",
|
||||||
|
@ -127,12 +127,14 @@ class LabelRelatedField(serializers.RelatedField):
|
||||||
if isinstance(data, dict) and (data.get("id") or data.get("pk")):
|
if isinstance(data, dict) and (data.get("id") or data.get("pk")):
|
||||||
pk = data.get("id") or data.get("pk")
|
pk = data.get("id") or data.get("pk")
|
||||||
label = Label.objects.get(pk=pk)
|
label = Label.objects.get(pk=pk)
|
||||||
|
elif is_uuid(data):
|
||||||
|
label = Label.objects.get(pk=data)
|
||||||
else:
|
else:
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
k = data.get("name")
|
k = data.get("name")
|
||||||
v = data.get("value")
|
v = data.get("value")
|
||||||
elif isinstance(data, str) and ":" in data:
|
elif isinstance(data, str) and ":" in data:
|
||||||
k, v = data.split(":", 1)
|
k, v = [x.strip() for x in data.split(":", 1)]
|
||||||
else:
|
else:
|
||||||
raise serializers.ValidationError(_("Invalid data type"))
|
raise serializers.ValidationError(_("Invalid data type"))
|
||||||
label, __ = Label.objects.get_or_create(name=k, value=v, defaults={'name': k, 'value': v})
|
label, __ = Label.objects.get_or_create(name=k, value=v, defaults={'name': k, 'value': v})
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
"ConnectError": "Error while fetching data",
|
"ConnectError": "Error while fetching data",
|
||||||
"ConnectSuccess": "Connected successfully",
|
"ConnectSuccess": "Connected successfully",
|
||||||
"Connected": "Connected",
|
"Connected": "Connected",
|
||||||
|
"Copy": "Copy",
|
||||||
|
"CopyFailed": "Copy failed",
|
||||||
"CopyNotAllowed": "You are not allowed to copy, please contact the administrator to open it!",
|
"CopyNotAllowed": "You are not allowed to copy, please contact the administrator to open it!",
|
||||||
|
"CopySucceeded": "Copy succeeded",
|
||||||
"Current": "Current",
|
"Current": "Current",
|
||||||
"DatabaseExplorer": "Database Explorer",
|
"DatabaseExplorer": "Database Explorer",
|
||||||
"DatabaseProperties": "Datasource properties",
|
"DatabaseProperties": "Datasource properties",
|
||||||
|
@ -33,6 +36,7 @@
|
||||||
"InitializeDatasource": "Initialize datasource",
|
"InitializeDatasource": "Initialize datasource",
|
||||||
"InitializeDatasourceFailed": "Initialize datasource failed",
|
"InitializeDatasourceFailed": "Initialize datasource failed",
|
||||||
"InitializingDatasourceMessage": "Initializing data source, please wait...",
|
"InitializingDatasourceMessage": "Initializing data source, please wait...",
|
||||||
|
"InsertStatement": "Insert statement",
|
||||||
"JDBCURL": "JDBC URL",
|
"JDBCURL": "JDBC URL",
|
||||||
"LogOutput": "Log Output",
|
"LogOutput": "Log Output",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
|
@ -67,11 +71,14 @@
|
||||||
"Submit": "Submit",
|
"Submit": "Submit",
|
||||||
"Total": "Total",
|
"Total": "Total",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
|
"UpdateStatement": "Update statement",
|
||||||
"User": "User",
|
"User": "User",
|
||||||
"UserCancelCommandReviewError": "The user has cancelled the command review.",
|
"UserCancelCommandReviewError": "The user has cancelled the command review.",
|
||||||
"Version": "Version",
|
"Version": "Version",
|
||||||
"ViewData": "View data",
|
"ViewData": "View data",
|
||||||
"WaitCommandReviewMessage": "The review request has been initiated, please wait for the review results",
|
"WaitCommandReviewMessage": "The review request has been initiated, please wait for the review results",
|
||||||
"Warning": "Warning",
|
"Warning": "Warning",
|
||||||
"initializingDatasourceFailedMessage": "Connection failed, please check if the database connection configuration is correct"
|
"initializingDatasourceFailedMessage": "Connection failed, please check if the database connection configuration is correct",
|
||||||
}
|
"Scope": "Scope",
|
||||||
|
"Format": "Format"
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
"ConnectError": "接続に失敗しました",
|
"ConnectError": "接続に失敗しました",
|
||||||
"ConnectSuccess": "接続に成功しました",
|
"ConnectSuccess": "接続に成功しました",
|
||||||
"Connected": "接続済み",
|
"Connected": "接続済み",
|
||||||
|
"Copy": "コピー",
|
||||||
|
"CopyFailed": "コピーしっぱい",
|
||||||
"CopyNotAllowed": "コピーは許可されていません。管理者に連絡して権限を開いてください!",
|
"CopyNotAllowed": "コピーは許可されていません。管理者に連絡して権限を開いてください!",
|
||||||
|
"CopySucceeded": "コピーせいこう",
|
||||||
"Current": "現在",
|
"Current": "現在",
|
||||||
"DatabaseExplorer": "データベースエクスプローラー",
|
"DatabaseExplorer": "データベースエクスプローラー",
|
||||||
"DatabaseProperties": "データソースプロパティ",
|
"DatabaseProperties": "データソースプロパティ",
|
||||||
|
@ -29,10 +32,12 @@
|
||||||
"ExportCurrent": "現在のページをエクスポート",
|
"ExportCurrent": "現在のページをエクスポート",
|
||||||
"ExportData": "データをエクスポート",
|
"ExportData": "データをエクスポート",
|
||||||
"FetchError": "データの取得に失敗しました",
|
"FetchError": "データの取得に失敗しました",
|
||||||
|
"Format": "フォーマット",
|
||||||
"FormatHotKey": "フォーマット (Ctrl + L)",
|
"FormatHotKey": "フォーマット (Ctrl + L)",
|
||||||
"InitializeDatasource": "データソースを初期化",
|
"InitializeDatasource": "データソースを初期化",
|
||||||
"InitializeDatasourceFailed": "データソースの初期化に失敗しました",
|
"InitializeDatasourceFailed": "データソースの初期化に失敗しました",
|
||||||
"InitializingDatasourceMessage": "データソースを初期化中、しばらくお待ちください...",
|
"InitializingDatasourceMessage": "データソースを初期化中、しばらくお待ちください...",
|
||||||
|
"InsertStatement": "インサート文",
|
||||||
"JDBCURL": "JDBC URL",
|
"JDBCURL": "JDBC URL",
|
||||||
"LogOutput": "ログ出力",
|
"LogOutput": "ログ出力",
|
||||||
"Name": "名前",
|
"Name": "名前",
|
||||||
|
@ -56,6 +61,7 @@
|
||||||
"Save": "保存",
|
"Save": "保存",
|
||||||
"SaveSQL": "SQLを保存",
|
"SaveSQL": "SQLを保存",
|
||||||
"SaveSucceed": "保存に成功しました",
|
"SaveSucceed": "保存に成功しました",
|
||||||
|
"Scope": "範囲",
|
||||||
"SelectSQL": "SQLを選択",
|
"SelectSQL": "SQLを選択",
|
||||||
"SessionClosedBy": "セッションが%sによって閉じられました",
|
"SessionClosedBy": "セッションが%sによって閉じられました",
|
||||||
"SessionFinished": "セッションが終了しました",
|
"SessionFinished": "セッションが終了しました",
|
||||||
|
@ -67,6 +73,7 @@
|
||||||
"Submit": "提出",
|
"Submit": "提出",
|
||||||
"Total": "合計",
|
"Total": "合計",
|
||||||
"Type": "タイプ",
|
"Type": "タイプ",
|
||||||
|
"UpdateStatement": "アップデート文",
|
||||||
"User": "ユーザー",
|
"User": "ユーザー",
|
||||||
"UserCancelCommandReviewError": "ユーザーがコマンドレビューをキャンセルしました",
|
"UserCancelCommandReviewError": "ユーザーがコマンドレビューをキャンセルしました",
|
||||||
"Version": "バージョン",
|
"Version": "バージョン",
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
"ConnectError": "Falha na conexão",
|
"ConnectError": "Falha na conexão",
|
||||||
"ConnectSuccess": "Conectado com sucesso",
|
"ConnectSuccess": "Conectado com sucesso",
|
||||||
"Connected": "Conectado",
|
"Connected": "Conectado",
|
||||||
|
"Copy": "cópia",
|
||||||
|
"CopyFailed": "Cópia falhada",
|
||||||
"CopyNotAllowed": "Cópia não permitida, por favor contate o administrador para liberar a permissão!",
|
"CopyNotAllowed": "Cópia não permitida, por favor contate o administrador para liberar a permissão!",
|
||||||
|
"CopySucceeded": "Cópia bem-sucedida",
|
||||||
"Current": "Atual",
|
"Current": "Atual",
|
||||||
"DatabaseExplorer": "Navegador de Banco de Dados",
|
"DatabaseExplorer": "Navegador de Banco de Dados",
|
||||||
"DatabaseProperties": "Propriedades da fonte de dados",
|
"DatabaseProperties": "Propriedades da fonte de dados",
|
||||||
|
@ -29,10 +32,12 @@
|
||||||
"ExportCurrent": "Exportar página atual",
|
"ExportCurrent": "Exportar página atual",
|
||||||
"ExportData": "Exportar dados",
|
"ExportData": "Exportar dados",
|
||||||
"FetchError": "Falha ao obter os dados",
|
"FetchError": "Falha ao obter os dados",
|
||||||
|
"Format": "Formato ",
|
||||||
"FormatHotKey": "Formatar (Ctrl + L)",
|
"FormatHotKey": "Formatar (Ctrl + L)",
|
||||||
"InitializeDatasource": "Inicializar fonte de dados",
|
"InitializeDatasource": "Inicializar fonte de dados",
|
||||||
"InitializeDatasourceFailed": "Falha ao inicializar a fonte de dados",
|
"InitializeDatasourceFailed": "Falha ao inicializar a fonte de dados",
|
||||||
"InitializingDatasourceMessage": "Inicializando a fonte de dados, por favor aguarde...",
|
"InitializingDatasourceMessage": "Inicializando a fonte de dados, por favor aguarde...",
|
||||||
|
"InsertStatement": "instrução de inserção",
|
||||||
"JDBCURL": "URL JDBC",
|
"JDBCURL": "URL JDBC",
|
||||||
"LogOutput": "Log de saída",
|
"LogOutput": "Log de saída",
|
||||||
"Name": "Nome",
|
"Name": "Nome",
|
||||||
|
@ -56,6 +61,7 @@
|
||||||
"Save": "Salvar",
|
"Save": "Salvar",
|
||||||
"SaveSQL": "Salve o SQL",
|
"SaveSQL": "Salve o SQL",
|
||||||
"SaveSucceed": "Salvo com sucesso",
|
"SaveSucceed": "Salvo com sucesso",
|
||||||
|
"Scope": " Alcance",
|
||||||
"SelectSQL": "Selecionar SQL",
|
"SelectSQL": "Selecionar SQL",
|
||||||
"SessionClosedBy": "A sessão foi fechada por %s",
|
"SessionClosedBy": "A sessão foi fechada por %s",
|
||||||
"SessionFinished": "A sessão terminou",
|
"SessionFinished": "A sessão terminou",
|
||||||
|
@ -67,6 +73,7 @@
|
||||||
"Submit": "Submeter",
|
"Submit": "Submeter",
|
||||||
"Total": "Total",
|
"Total": "Total",
|
||||||
"Type": "Escrever",
|
"Type": "Escrever",
|
||||||
|
"UpdateStatement": "instrução de atualização",
|
||||||
"User": "Usuário",
|
"User": "Usuário",
|
||||||
"UserCancelCommandReviewError": "O usuário cancelou a revisão do comando",
|
"UserCancelCommandReviewError": "O usuário cancelou a revisão do comando",
|
||||||
"Version": "Versão",
|
"Version": "Versão",
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
"ConnectError": "连接失败",
|
"ConnectError": "连接失败",
|
||||||
"ConnectSuccess": "连接成功",
|
"ConnectSuccess": "连接成功",
|
||||||
"Connected": "已连接",
|
"Connected": "已连接",
|
||||||
|
"Copy": "复制",
|
||||||
|
"CopyFailed": "复制失败",
|
||||||
"CopyNotAllowed": "不允许复制,请联系管理员开启权限!",
|
"CopyNotAllowed": "不允许复制,请联系管理员开启权限!",
|
||||||
|
"CopySucceeded": "复制成功",
|
||||||
"Current": "当前",
|
"Current": "当前",
|
||||||
"DatabaseExplorer": "数据库浏览器",
|
"DatabaseExplorer": "数据库浏览器",
|
||||||
"DatabaseProperties": "数据源属性",
|
"DatabaseProperties": "数据源属性",
|
||||||
|
@ -33,6 +36,7 @@
|
||||||
"InitializeDatasource": "初始化数据源",
|
"InitializeDatasource": "初始化数据源",
|
||||||
"InitializeDatasourceFailed": "初始化数据源失败",
|
"InitializeDatasourceFailed": "初始化数据源失败",
|
||||||
"InitializingDatasourceMessage": "正在初始化数据源,请稍候...",
|
"InitializingDatasourceMessage": "正在初始化数据源,请稍候...",
|
||||||
|
"InsertStatement": "插入语句",
|
||||||
"JDBCURL": "JDBC URL",
|
"JDBCURL": "JDBC URL",
|
||||||
"LogOutput": "日志输出",
|
"LogOutput": "日志输出",
|
||||||
"Name": "名称",
|
"Name": "名称",
|
||||||
|
@ -67,11 +71,14 @@
|
||||||
"Submit": "提交",
|
"Submit": "提交",
|
||||||
"Total": "总计",
|
"Total": "总计",
|
||||||
"Type": "类型",
|
"Type": "类型",
|
||||||
|
"UpdateStatement": "更新语句",
|
||||||
"User": "用户",
|
"User": "用户",
|
||||||
"UserCancelCommandReviewError": "用户取消命令复核",
|
"UserCancelCommandReviewError": "用户取消命令复核",
|
||||||
"Version": "版本",
|
"Version": "版本",
|
||||||
"ViewData": "查看数据",
|
"ViewData": "查看数据",
|
||||||
"WaitCommandReviewMessage": "复核请求已发起, 请等待复核结果",
|
"WaitCommandReviewMessage": "复核请求已发起, 请等待复核结果",
|
||||||
"Warning": "警告",
|
"Warning": "警告",
|
||||||
"initializingDatasourceFailedMessage": "连接失败,请检查数据库连接配置是否正确"
|
"initializingDatasourceFailedMessage": "连接失败,请检查数据库连接配置是否正确",
|
||||||
}
|
"Scope": "范围",
|
||||||
|
"Format": "格式"
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
"ConnectError": "連接失敗",
|
"ConnectError": "連接失敗",
|
||||||
"ConnectSuccess": "連接成功",
|
"ConnectSuccess": "連接成功",
|
||||||
"Connected": "已連接",
|
"Connected": "已連接",
|
||||||
|
"Copy": "複製",
|
||||||
|
"CopyFailed": "複製失敗",
|
||||||
"CopyNotAllowed": "不允許複製,請聯絡管理員開啟權限!",
|
"CopyNotAllowed": "不允許複製,請聯絡管理員開啟權限!",
|
||||||
|
"CopySucceeded": "複製成功",
|
||||||
"Current": "目前",
|
"Current": "目前",
|
||||||
"DatabaseExplorer": "資料庫瀏覽器",
|
"DatabaseExplorer": "資料庫瀏覽器",
|
||||||
"DatabaseProperties": "資料源屬性",
|
"DatabaseProperties": "資料源屬性",
|
||||||
|
@ -29,10 +32,12 @@
|
||||||
"ExportCurrent": "匯出當前頁面",
|
"ExportCurrent": "匯出當前頁面",
|
||||||
"ExportData": "匯出資料",
|
"ExportData": "匯出資料",
|
||||||
"FetchError": "獲取資料失敗",
|
"FetchError": "獲取資料失敗",
|
||||||
|
"Format": "格式",
|
||||||
"FormatHotKey": "格式化 (Ctrl + L)",
|
"FormatHotKey": "格式化 (Ctrl + L)",
|
||||||
"InitializeDatasource": "初始化資料源",
|
"InitializeDatasource": "初始化資料源",
|
||||||
"InitializeDatasourceFailed": "初始化資料源失敗",
|
"InitializeDatasourceFailed": "初始化資料源失敗",
|
||||||
"InitializingDatasourceMessage": "正在初始化資料源,請稍候...",
|
"InitializingDatasourceMessage": "正在初始化資料源,請稍候...",
|
||||||
|
"InsertStatement": "插入語句",
|
||||||
"JDBCURL": "JDBC URL",
|
"JDBCURL": "JDBC URL",
|
||||||
"LogOutput": "日誌輸出",
|
"LogOutput": "日誌輸出",
|
||||||
"Name": "名稱",
|
"Name": "名稱",
|
||||||
|
@ -56,6 +61,7 @@
|
||||||
"Save": "保存",
|
"Save": "保存",
|
||||||
"SaveSQL": "儲存 SQL",
|
"SaveSQL": "儲存 SQL",
|
||||||
"SaveSucceed": "儲存成功",
|
"SaveSucceed": "儲存成功",
|
||||||
|
"Scope": "範圍",
|
||||||
"SelectSQL": "選擇 SQL",
|
"SelectSQL": "選擇 SQL",
|
||||||
"SessionClosedBy": "會話被 %s 關閉",
|
"SessionClosedBy": "會話被 %s 關閉",
|
||||||
"SessionFinished": "會話已結束",
|
"SessionFinished": "會話已結束",
|
||||||
|
@ -67,6 +73,7 @@
|
||||||
"Submit": "提交",
|
"Submit": "提交",
|
||||||
"Total": "總計",
|
"Total": "總計",
|
||||||
"Type": "類型",
|
"Type": "類型",
|
||||||
|
"UpdateStatement": "更新語句",
|
||||||
"User": "用戶",
|
"User": "用戶",
|
||||||
"UserCancelCommandReviewError": "用戶取消命令覆核",
|
"UserCancelCommandReviewError": "用戶取消命令覆核",
|
||||||
"Version": "版本",
|
"Version": "版本",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -462,6 +462,7 @@
|
||||||
"Edit": "Edit",
|
"Edit": "Edit",
|
||||||
"EditRecipient": "Edit recipient",
|
"EditRecipient": "Edit recipient",
|
||||||
"Edition": "Version",
|
"Edition": "Version",
|
||||||
|
"Effective": "Effective",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"EmailContent": "Custom content",
|
"EmailContent": "Custom content",
|
||||||
"EmailTemplate": "Template",
|
"EmailTemplate": "Template",
|
||||||
|
@ -1422,5 +1423,8 @@
|
||||||
"disallowSelfUpdateFields": "Not allowed to modify the current fields yourself",
|
"disallowSelfUpdateFields": "Not allowed to modify the current fields yourself",
|
||||||
"forceEnableMFAHelpText": "If force enable, user can not disable by themselves",
|
"forceEnableMFAHelpText": "If force enable, user can not disable by themselves",
|
||||||
"removeWarningMsg": "Are you sure you want to remove",
|
"removeWarningMsg": "Are you sure you want to remove",
|
||||||
"setVariable": "Set variable"
|
"setVariable": "Set variable",
|
||||||
|
"VerifyFace": "Verify face",
|
||||||
|
"ServerBusyRetry": "The server is busy, please try again later.",
|
||||||
|
"DeeplyThoughtAbout": "Deeply thought about"
|
||||||
}
|
}
|
|
@ -432,6 +432,7 @@
|
||||||
"Datetime": "日時",
|
"Datetime": "日時",
|
||||||
"Day": "日",
|
"Day": "日",
|
||||||
"DeclassificationLogNum": "パスワード変更ログ数",
|
"DeclassificationLogNum": "パスワード変更ログ数",
|
||||||
|
"DeeplyThoughtAbout": "深く考えた結果",
|
||||||
"DefaultDatabase": "デフォルトのデータベース",
|
"DefaultDatabase": "デフォルトのデータベース",
|
||||||
"DefaultPort": "デフォルトポート",
|
"DefaultPort": "デフォルトポート",
|
||||||
"DefaultValue": "デフォルト値",
|
"DefaultValue": "デフォルト値",
|
||||||
|
@ -478,6 +479,7 @@
|
||||||
"Edit": "編集",
|
"Edit": "編集",
|
||||||
"EditRecipient": "受取人の編集",
|
"EditRecipient": "受取人の編集",
|
||||||
"Edition": "バージョン",
|
"Edition": "バージョン",
|
||||||
|
"Effective": "効果",
|
||||||
"Email": "メールボックス",
|
"Email": "メールボックス",
|
||||||
"EmailContent": "メールコンテンツのカスタマイズ",
|
"EmailContent": "メールコンテンツのカスタマイズ",
|
||||||
"EmailTemplate": "メールテンプレート",
|
"EmailTemplate": "メールテンプレート",
|
||||||
|
@ -1139,6 +1141,7 @@
|
||||||
"SerialNumber": "シリアルナンバー",
|
"SerialNumber": "シリアルナンバー",
|
||||||
"Server": "サービス",
|
"Server": "サービス",
|
||||||
"ServerAccountKey": "サービスアカウントキー",
|
"ServerAccountKey": "サービスアカウントキー",
|
||||||
|
"ServerBusyRetry": "サーバーが混雑していますので、後ほど再度お試しください。",
|
||||||
"ServerError": "サーバーエラー",
|
"ServerError": "サーバーエラー",
|
||||||
"ServerTime": "サーバータイム",
|
"ServerTime": "サーバータイム",
|
||||||
"Session": "コンバセーション",
|
"Session": "コンバセーション",
|
||||||
|
@ -1420,6 +1423,7 @@
|
||||||
"VaultHCPMountPoint": "Vault サーバのマウントポイント、デフォルトはjumpserver",
|
"VaultHCPMountPoint": "Vault サーバのマウントポイント、デフォルトはjumpserver",
|
||||||
"VaultHelpText": "1. セキュリティ上の理由から、設定ファイルに VAULT_ENABLED=true および VAULT_BACKEND=hcp/azure/aws のパラメータを追加して、Vault ストレージを有効にします。<br>2. オンにした後、他の設定を入力してテストを行います。<br>3. データ同期を行います。同期は一方向です。ローカルデータベースからリモートの Vault にのみ同期します。同期が終了すればローカルデータベースはパスワードを保管していませんので、データのバックアップをお願いします。<br>4. Vault の設定を二度変更した後はサービスを再起動する必要があります。",
|
"VaultHelpText": "1. セキュリティ上の理由から、設定ファイルに VAULT_ENABLED=true および VAULT_BACKEND=hcp/azure/aws のパラメータを追加して、Vault ストレージを有効にします。<br>2. オンにした後、他の設定を入力してテストを行います。<br>3. データ同期を行います。同期は一方向です。ローカルデータベースからリモートの Vault にのみ同期します。同期が終了すればローカルデータベースはパスワードを保管していませんので、データのバックアップをお願いします。<br>4. Vault の設定を二度変更した後はサービスを再起動する必要があります。",
|
||||||
"VerificationCodeSent": "認証コードが送信されました",
|
"VerificationCodeSent": "認証コードが送信されました",
|
||||||
|
"VerifyFace": "顔認証を行います",
|
||||||
"VerifySignTmpl": "認証コードのSMSテンプレート",
|
"VerifySignTmpl": "認証コードのSMSテンプレート",
|
||||||
"Version": "バージョン",
|
"Version": "バージョン",
|
||||||
"View": "閲覧",
|
"View": "閲覧",
|
||||||
|
|
|
@ -417,6 +417,7 @@
|
||||||
"Datetime": "Data e Hora",
|
"Datetime": "Data e Hora",
|
||||||
"Day": "Dia",
|
"Day": "Dia",
|
||||||
"DeclassificationLogNum": "Quantidade de logs de modificação de senha",
|
"DeclassificationLogNum": "Quantidade de logs de modificação de senha",
|
||||||
|
"DeeplyThoughtAbout": "Já refletido profundamente ",
|
||||||
"DefaultDatabase": "Banco de Dados Padrão",
|
"DefaultDatabase": "Banco de Dados Padrão",
|
||||||
"DefaultPort": "Porta padrão",
|
"DefaultPort": "Porta padrão",
|
||||||
"DefaultValue": " Valor padrão",
|
"DefaultValue": " Valor padrão",
|
||||||
|
@ -463,6 +464,7 @@
|
||||||
"Edit": "Editar",
|
"Edit": "Editar",
|
||||||
"EditRecipient": "Editar receptor",
|
"EditRecipient": "Editar receptor",
|
||||||
"Edition": "Versão",
|
"Edition": "Versão",
|
||||||
|
"Effective": "Eficaz",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"EmailContent": "Personalização de conteúdo de e-mail",
|
"EmailContent": "Personalização de conteúdo de e-mail",
|
||||||
"EmailTemplate": " Modelo de e-mail",
|
"EmailTemplate": " Modelo de e-mail",
|
||||||
|
@ -1107,6 +1109,7 @@
|
||||||
"SerialNumber": "Número de Série",
|
"SerialNumber": "Número de Série",
|
||||||
"Server": "Serviços",
|
"Server": "Serviços",
|
||||||
"ServerAccountKey": "Chave da conta de serviço",
|
"ServerAccountKey": "Chave da conta de serviço",
|
||||||
|
"ServerBusyRetry": " O servidor está ocupado, por favor, tente novamente mais tarde.",
|
||||||
"ServerError": "Erro do servidor",
|
"ServerError": "Erro do servidor",
|
||||||
"ServerTime": "Horário do Servidor",
|
"ServerTime": "Horário do Servidor",
|
||||||
"Session": "Sessão",
|
"Session": "Sessão",
|
||||||
|
@ -1382,6 +1385,7 @@
|
||||||
"VaultHCPMountPoint": "Ponto de montagem do servidor Vault, padrão é jumpserver",
|
"VaultHCPMountPoint": "Ponto de montagem do servidor Vault, padrão é jumpserver",
|
||||||
"VaultHelpText": "1. Por razões de segurança, é necessário adicionar os parâmetros VAULT_ENABLED=true e VAULT_BACKEND=hcp/azure/aws no arquivo de configuração para ativar o armazenamento Vault.<br>2. Depois de ativado, preencha as outras configurações e faça o teste.<br>3. Proceda com a sincronização de dados, a sincronização é unidirecional, sincronizará apenas do banco de dados local para o Vault remoto, após a conclusão da sincronização, o banco de dados local não armazenará mais a senha, por favor, faça backup dos dados.<br>4. Após a segunda modificação da configuração do Vault, é necessário reiniciar o serviço.",
|
"VaultHelpText": "1. Por razões de segurança, é necessário adicionar os parâmetros VAULT_ENABLED=true e VAULT_BACKEND=hcp/azure/aws no arquivo de configuração para ativar o armazenamento Vault.<br>2. Depois de ativado, preencha as outras configurações e faça o teste.<br>3. Proceda com a sincronização de dados, a sincronização é unidirecional, sincronizará apenas do banco de dados local para o Vault remoto, após a conclusão da sincronização, o banco de dados local não armazenará mais a senha, por favor, faça backup dos dados.<br>4. Após a segunda modificação da configuração do Vault, é necessário reiniciar o serviço.",
|
||||||
"VerificationCodeSent": "O código de verificação foi enviado",
|
"VerificationCodeSent": "O código de verificação foi enviado",
|
||||||
|
"VerifyFace": " Verificar rosto ",
|
||||||
"VerifySignTmpl": "Modelo de SMS com código de verificação",
|
"VerifySignTmpl": "Modelo de SMS com código de verificação",
|
||||||
"Version": "Versão",
|
"Version": "Versão",
|
||||||
"View": " Visualizar",
|
"View": " Visualizar",
|
||||||
|
|
|
@ -463,6 +463,7 @@
|
||||||
"Edit": "编辑",
|
"Edit": "编辑",
|
||||||
"EditRecipient": "编辑接收人",
|
"EditRecipient": "编辑接收人",
|
||||||
"Edition": "版本",
|
"Edition": "版本",
|
||||||
|
"Effective": "生效",
|
||||||
"Email": "邮箱",
|
"Email": "邮箱",
|
||||||
"EmailContent": "邮件内容定制",
|
"EmailContent": "邮件内容定制",
|
||||||
"EmailTemplate": "邮件模版",
|
"EmailTemplate": "邮件模版",
|
||||||
|
@ -1427,5 +1428,8 @@
|
||||||
"disallowSelfUpdateFields": "不允许自己修改当前字段",
|
"disallowSelfUpdateFields": "不允许自己修改当前字段",
|
||||||
"forceEnableMFAHelpText": "如果强制启用,用户无法自行禁用",
|
"forceEnableMFAHelpText": "如果强制启用,用户无法自行禁用",
|
||||||
"removeWarningMsg": "你确定要移除",
|
"removeWarningMsg": "你确定要移除",
|
||||||
"setVariable": "设置参数"
|
"setVariable": "设置参数",
|
||||||
|
"VerifyFace": "验证人脸",
|
||||||
|
"ServerBusyRetry": "服务器繁忙,请稍后再试。",
|
||||||
|
"DeeplyThoughtAbout": "已深度思考"
|
||||||
}
|
}
|
|
@ -550,6 +550,7 @@
|
||||||
"Day": "日",
|
"Day": "日",
|
||||||
"DeactiveSelected": "禁用所選",
|
"DeactiveSelected": "禁用所選",
|
||||||
"DeclassificationLogNum": "改密日誌數",
|
"DeclassificationLogNum": "改密日誌數",
|
||||||
|
"DeeplyThoughtAbout": "已深度思考",
|
||||||
"Default": "預設的",
|
"Default": "預設的",
|
||||||
"DefaultDatabase": "默認資料庫",
|
"DefaultDatabase": "默認資料庫",
|
||||||
"DefaultPort": "默認埠",
|
"DefaultPort": "默認埠",
|
||||||
|
@ -614,6 +615,7 @@
|
||||||
"Edit": "編輯",
|
"Edit": "編輯",
|
||||||
"EditRecipient": "編輯接收人",
|
"EditRecipient": "編輯接收人",
|
||||||
"Edition": "版本",
|
"Edition": "版本",
|
||||||
|
"Effective": "生效",
|
||||||
"Email": "信箱",
|
"Email": "信箱",
|
||||||
"EmailContent": "郵件內容訂製",
|
"EmailContent": "郵件內容訂製",
|
||||||
"EmailTemplate": " Email Template",
|
"EmailTemplate": " Email Template",
|
||||||
|
@ -1455,6 +1457,7 @@
|
||||||
"SerialNumber": "序號",
|
"SerialNumber": "序號",
|
||||||
"Server": "服務",
|
"Server": "服務",
|
||||||
"ServerAccountKey": "服務帳號金鑰",
|
"ServerAccountKey": "服務帳號金鑰",
|
||||||
|
"ServerBusyRetry": "伺服器繁忙,請稍後再試。",
|
||||||
"ServerError": "伺服器錯誤",
|
"ServerError": "伺服器錯誤",
|
||||||
"ServerTime": "伺服器時間",
|
"ServerTime": "伺服器時間",
|
||||||
"ServiceRatio": "組件負載統計",
|
"ServiceRatio": "組件負載統計",
|
||||||
|
@ -1815,6 +1818,7 @@
|
||||||
"VaultHelpText": "1. 由於安全原因,需要在配置文件中增加參數 VAULT_ENABLED=true 和 VAULT_BACKEND=hcp/azure/aws 以開啟 Vault 存儲。<br>2. 開啟後,填寫其他配置,進行測試。<br>3. 進行數據同步,同步是單向的,只會從本地資料庫同步到遠端 Vault,同步完成本地資料庫不再儲存密碼,請備份好數據。<br>4. 二次修改 Vault 配置後需重啟服務。",
|
"VaultHelpText": "1. 由於安全原因,需要在配置文件中增加參數 VAULT_ENABLED=true 和 VAULT_BACKEND=hcp/azure/aws 以開啟 Vault 存儲。<br>2. 開啟後,填寫其他配置,進行測試。<br>3. 進行數據同步,同步是單向的,只會從本地資料庫同步到遠端 Vault,同步完成本地資料庫不再儲存密碼,請備份好數據。<br>4. 二次修改 Vault 配置後需重啟服務。",
|
||||||
"Vendor": "製造商",
|
"Vendor": "製造商",
|
||||||
"VerificationCodeSent": "驗證碼已發送",
|
"VerificationCodeSent": "驗證碼已發送",
|
||||||
|
"VerifyFace": "驗證面孔",
|
||||||
"VerifySignTmpl": "驗證碼簡訊模板",
|
"VerifySignTmpl": "驗證碼簡訊模板",
|
||||||
"Version": "版本",
|
"Version": "版本",
|
||||||
"View": "查看",
|
"View": "查看",
|
||||||
|
|
|
@ -232,5 +232,6 @@
|
||||||
"start time": "start time",
|
"start time": "start time",
|
||||||
"success": "success",
|
"success": "success",
|
||||||
"system user": "system user",
|
"system user": "system user",
|
||||||
"user": "user"
|
"user": "user",
|
||||||
|
"SessionIsBeingMonitored": "session is being monitored"
|
||||||
}
|
}
|
|
@ -230,5 +230,6 @@
|
||||||
"start time": "开始时间",
|
"start time": "开始时间",
|
||||||
"success": "成功",
|
"success": "成功",
|
||||||
"system user": "系统用户",
|
"system user": "系统用户",
|
||||||
"user": "用户"
|
"user": "用户",
|
||||||
|
"SessionIsBeingMonitored": "会话正在被监控"
|
||||||
}
|
}
|
|
@ -681,10 +681,15 @@ class Config(dict):
|
||||||
|
|
||||||
# Chat AI
|
# Chat AI
|
||||||
'CHAT_AI_ENABLED': False,
|
'CHAT_AI_ENABLED': False,
|
||||||
'GPT_API_KEY': '',
|
'CHAT_AI_TYPE': 'gpt',
|
||||||
'GPT_BASE_URL': '',
|
'GPT_BASE_URL': '',
|
||||||
|
'GPT_API_KEY': '',
|
||||||
'GPT_PROXY': '',
|
'GPT_PROXY': '',
|
||||||
'GPT_MODEL': 'gpt-3.5-turbo',
|
'GPT_MODEL': 'gpt-4o-mini',
|
||||||
|
'DEEPSEEK_BASE_URL': '',
|
||||||
|
'DEEPSEEK_API_KEY': '',
|
||||||
|
'DEEPSEEK_PROXY': '',
|
||||||
|
'DEEPSEEK_MODEL': 'deepseek-chat',
|
||||||
'VIRTUAL_APP_ENABLED': False,
|
'VIRTUAL_APP_ENABLED': False,
|
||||||
|
|
||||||
'FILE_UPLOAD_SIZE_LIMIT_MB': 200,
|
'FILE_UPLOAD_SIZE_LIMIT_MB': 200,
|
||||||
|
|
|
@ -222,10 +222,15 @@ ASSET_SIZE = 'small'
|
||||||
|
|
||||||
# Chat AI
|
# Chat AI
|
||||||
CHAT_AI_ENABLED = CONFIG.CHAT_AI_ENABLED
|
CHAT_AI_ENABLED = CONFIG.CHAT_AI_ENABLED
|
||||||
GPT_API_KEY = CONFIG.GPT_API_KEY
|
CHAT_AI_TYPE = CONFIG.CHAT_AI_TYPE
|
||||||
GPT_BASE_URL = CONFIG.GPT_BASE_URL
|
GPT_BASE_URL = CONFIG.GPT_BASE_URL
|
||||||
|
GPT_API_KEY = CONFIG.GPT_API_KEY
|
||||||
GPT_PROXY = CONFIG.GPT_PROXY
|
GPT_PROXY = CONFIG.GPT_PROXY
|
||||||
GPT_MODEL = CONFIG.GPT_MODEL
|
GPT_MODEL = CONFIG.GPT_MODEL
|
||||||
|
DEEPSEEK_BASE_URL = CONFIG.DEEPSEEK_BASE_URL
|
||||||
|
DEEPSEEK_API_KEY = CONFIG.DEEPSEEK_API_KEY
|
||||||
|
DEEPSEEK_PROXY = CONFIG.DEEPSEEK_PROXY
|
||||||
|
DEEPSEEK_MODEL = CONFIG.DEEPSEEK_MODEL
|
||||||
|
|
||||||
VIRTUAL_APP_ENABLED = CONFIG.VIRTUAL_APP_ENABLED
|
VIRTUAL_APP_ENABLED = CONFIG.VIRTUAL_APP_ENABLED
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
from common.serializers.fields import ReadableHiddenField, LabeledChoiceField, EncryptedField
|
from common.serializers.fields import ReadableHiddenField, LabeledChoiceField
|
||||||
from common.serializers.mixin import CommonBulkModelSerializer
|
from common.serializers.mixin import CommonBulkModelSerializer
|
||||||
from ops.const import FieldType
|
from ops.const import FieldType
|
||||||
from ops.models import Variable, AdHoc, Job, Playbook
|
from ops.models import Variable, AdHoc, Job, Playbook
|
||||||
|
@ -28,7 +28,9 @@ class VariableSerializer(CommonBulkModelSerializer):
|
||||||
type = LabeledChoiceField(
|
type = LabeledChoiceField(
|
||||||
choices=FieldType.choices, default=FieldType.text, label=_("Variable Type")
|
choices=FieldType.choices, default=FieldType.text, label=_("Variable Type")
|
||||||
)
|
)
|
||||||
default_value = serializers.CharField(max_length=2048, label=_('Default Value'), required=False, allow_blank=True)
|
default_value = serializers.CharField(
|
||||||
|
max_length=2048, label=_('Default Value'), required=False, allow_blank=True, allow_null=True
|
||||||
|
)
|
||||||
extra_args = serializers.CharField(
|
extra_args = serializers.CharField(
|
||||||
max_length=1024, label=_("ExtraVars"), required=False, allow_blank=True,
|
max_length=1024, label=_("ExtraVars"), required=False, allow_blank=True,
|
||||||
help_text=_(
|
help_text=_(
|
||||||
|
|
|
@ -5,8 +5,8 @@ from contextlib import contextmanager
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from inspect import signature
|
from inspect import signature
|
||||||
|
|
||||||
from werkzeug.local import LocalProxy
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from werkzeug.local import LocalProxy
|
||||||
|
|
||||||
from common.local import thread_local
|
from common.local import thread_local
|
||||||
from .models import Organization
|
from .models import Organization
|
||||||
|
@ -57,6 +57,8 @@ def get_org_from_request(request):
|
||||||
def set_current_org(org):
|
def set_current_org(org):
|
||||||
if isinstance(org, (str, uuid.UUID)):
|
if isinstance(org, (str, uuid.UUID)):
|
||||||
org = Organization.get_instance(org)
|
org = Organization.get_instance(org)
|
||||||
|
if not org:
|
||||||
|
return
|
||||||
setattr(thread_local, 'current_org_id', org.id)
|
setattr(thread_local, 'current_org_id', org.id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,20 +99,24 @@ def get_current_org_id_for_serializer():
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def tmp_to_root_org():
|
def tmp_to_root_org():
|
||||||
ori_org = get_current_org()
|
ori_org = get_current_org()
|
||||||
set_to_root_org()
|
try:
|
||||||
yield
|
set_to_root_org()
|
||||||
if ori_org is not None:
|
yield
|
||||||
set_current_org(ori_org)
|
finally:
|
||||||
|
if ori_org is not None:
|
||||||
|
set_current_org(ori_org)
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def tmp_to_org(org):
|
def tmp_to_org(org):
|
||||||
ori_org = get_current_org()
|
ori_org = get_current_org()
|
||||||
if org:
|
try:
|
||||||
set_current_org(org)
|
if org:
|
||||||
yield
|
set_current_org(org)
|
||||||
if ori_org is not None:
|
yield
|
||||||
set_current_org(ori_org)
|
finally:
|
||||||
|
if ori_org is not None:
|
||||||
|
set_current_org(ori_org)
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
@ -122,9 +128,10 @@ def tmp_to_builtin_org(system=0, default=0):
|
||||||
else:
|
else:
|
||||||
raise ValueError("Must set system or default")
|
raise ValueError("Must set system or default")
|
||||||
ori_org = get_current_org()
|
ori_org = get_current_org()
|
||||||
set_current_org(org_id)
|
try:
|
||||||
yield
|
set_current_org(org_id)
|
||||||
if ori_org is not None:
|
yield
|
||||||
|
finally:
|
||||||
set_current_org(ori_org)
|
set_current_org(ori_org)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ from rest_framework.response import Response
|
||||||
from common.api import JMSModelViewSet
|
from common.api import JMSModelViewSet
|
||||||
from common.permissions import IsValidUser, OnlySuperUser
|
from common.permissions import IsValidUser, OnlySuperUser
|
||||||
from .. import serializers
|
from .. import serializers
|
||||||
|
from ..const import ChatAITypeChoices
|
||||||
from ..models import ChatPrompt
|
from ..models import ChatPrompt
|
||||||
from ..prompt import DefaultChatPrompt
|
from ..prompt import DefaultChatPrompt
|
||||||
|
|
||||||
|
@ -40,12 +41,21 @@ class ChatAITestingAPI(GenericAPIView):
|
||||||
data={'msg': _('Chat AI is not enabled')}
|
data={'msg': _('Chat AI is not enabled')}
|
||||||
)
|
)
|
||||||
|
|
||||||
proxy = config['GPT_PROXY']
|
tp = config['CHAT_AI_TYPE']
|
||||||
model = config['GPT_MODEL']
|
if tp == ChatAITypeChoices.gpt:
|
||||||
|
url = config['GPT_BASE_URL']
|
||||||
|
api_key = config['GPT_API_KEY']
|
||||||
|
proxy = config['GPT_PROXY']
|
||||||
|
model = config['GPT_MODEL']
|
||||||
|
else:
|
||||||
|
url = config['DEEPSEEK_BASE_URL']
|
||||||
|
api_key = config['DEEPSEEK_API_KEY']
|
||||||
|
proxy = config['DEEPSEEK_PROXY']
|
||||||
|
model = config['DEEPSEEK_MODEL']
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'base_url': config['GPT_BASE_URL'] or None,
|
'base_url': url or None,
|
||||||
'api_key': config['GPT_API_KEY'],
|
'api_key': api_key,
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
if proxy:
|
if proxy:
|
||||||
|
|
|
@ -5,3 +5,21 @@ class ImportStatus(TextChoices):
|
||||||
ok = 'ok', 'Ok'
|
ok = 'ok', 'Ok'
|
||||||
pending = 'pending', 'Pending'
|
pending = 'pending', 'Pending'
|
||||||
error = 'error', 'Error'
|
error = 'error', 'Error'
|
||||||
|
|
||||||
|
|
||||||
|
class ChatAITypeChoices(TextChoices):
|
||||||
|
gpt = 'gpt', 'GPT'
|
||||||
|
deep_seek = 'deep-seek', 'DeepSeek'
|
||||||
|
|
||||||
|
|
||||||
|
class GPTModelChoices(TextChoices):
|
||||||
|
gpt_4o_mini = 'gpt-4o-mini', 'gpt-4o-mini'
|
||||||
|
gpt_4o = 'gpt-4o', 'gpt-4o'
|
||||||
|
o3_mini = 'o3-mini', 'o3-mini'
|
||||||
|
o1_mini = 'o1-mini', 'o1-mini'
|
||||||
|
o1 = 'o1', 'o1'
|
||||||
|
|
||||||
|
|
||||||
|
class DeepSeekModelChoices(TextChoices):
|
||||||
|
deepseek_chat = 'deepseek-chat', 'DeepSeek-V3'
|
||||||
|
deepseek_reasoner = 'deepseek-reasoner', 'DeepSeek-R1'
|
||||||
|
|
|
@ -10,7 +10,9 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework.utils.encoders import JSONEncoder
|
from rest_framework.utils.encoders import JSONEncoder
|
||||||
|
|
||||||
from common.db.models import JMSBaseModel
|
from common.db.models import JMSBaseModel
|
||||||
from common.utils import signer, get_logger
|
from common.db.utils import Encryptor
|
||||||
|
from common.utils import get_logger
|
||||||
|
from .const import ChatAITypeChoices
|
||||||
from .signals import setting_changed
|
from .signals import setting_changed
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
@ -53,7 +55,7 @@ class Setting(models.Model):
|
||||||
try:
|
try:
|
||||||
value = self.value
|
value = self.value
|
||||||
if self.encrypted:
|
if self.encrypted:
|
||||||
value = signer.unsign(value)
|
value = Encryptor(value).decrypt()
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
value = json.loads(value)
|
value = json.loads(value)
|
||||||
|
@ -66,7 +68,7 @@ class Setting(models.Model):
|
||||||
try:
|
try:
|
||||||
v = json.dumps(item, cls=JSONEncoder)
|
v = json.dumps(item, cls=JSONEncoder)
|
||||||
if self.encrypted:
|
if self.encrypted:
|
||||||
v = signer.sign(v)
|
v = Encryptor(v).encrypt()
|
||||||
self.value = v
|
self.value = v
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
raise ValueError("Json dump error: {}".format(str(e)))
|
raise ValueError("Json dump error: {}".format(str(e)))
|
||||||
|
@ -190,3 +192,19 @@ class ChatPrompt(JMSBaseModel):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
def get_chatai_data():
|
||||||
|
data = {
|
||||||
|
'url': settings.GPT_BASE_URL,
|
||||||
|
'api_key': settings.GPT_API_KEY,
|
||||||
|
'proxy': settings.GPT_PROXY,
|
||||||
|
'model': settings.GPT_MODEL,
|
||||||
|
}
|
||||||
|
if settings.CHAT_AI_TYPE != ChatAITypeChoices.gpt:
|
||||||
|
data['url'] = settings.DEEPSEEK_BASE_URL
|
||||||
|
data['api_key'] = settings.DEEPSEEK_API_KEY
|
||||||
|
data['proxy'] = settings.DEEPSEEK_PROXY
|
||||||
|
data['model'] = settings.DEEPSEEK_MODEL
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
|
@ -4,7 +4,6 @@ from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from assets.const import Protocol
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
from common.utils import date_expired_default
|
from common.utils import date_expired_default
|
||||||
|
|
||||||
|
@ -14,6 +13,8 @@ __all__ = [
|
||||||
'ChatAISettingSerializer', 'VirtualAppSerializer', 'AmazonSMSerializer',
|
'ChatAISettingSerializer', 'VirtualAppSerializer', 'AmazonSMSerializer',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
from settings.const import ChatAITypeChoices, GPTModelChoices, DeepSeekModelChoices
|
||||||
|
|
||||||
|
|
||||||
class AnnouncementSerializer(serializers.Serializer):
|
class AnnouncementSerializer(serializers.Serializer):
|
||||||
ID = serializers.CharField(required=False, allow_blank=True, allow_null=True)
|
ID = serializers.CharField(required=False, allow_blank=True, allow_null=True)
|
||||||
|
@ -119,16 +120,17 @@ class AmazonSMSerializer(serializers.Serializer):
|
||||||
|
|
||||||
class ChatAISettingSerializer(serializers.Serializer):
|
class ChatAISettingSerializer(serializers.Serializer):
|
||||||
PREFIX_TITLE = _('Chat AI')
|
PREFIX_TITLE = _('Chat AI')
|
||||||
API_MODEL = Protocol.gpt_protocols()[Protocol.chatgpt]['setting']['api_mode']
|
|
||||||
GPT_MODEL_CHOICES = API_MODEL['choices']
|
|
||||||
GPT_MODEL_DEFAULT = API_MODEL['default']
|
|
||||||
|
|
||||||
CHAT_AI_ENABLED = serializers.BooleanField(
|
CHAT_AI_ENABLED = serializers.BooleanField(
|
||||||
required=False, label=_('Chat AI')
|
required=False, label=_('Chat AI')
|
||||||
)
|
)
|
||||||
|
CHAT_AI_TYPE = serializers.ChoiceField(
|
||||||
|
default=ChatAITypeChoices.gpt, choices=ChatAITypeChoices.choices,
|
||||||
|
label=_("Types"), required=False,
|
||||||
|
)
|
||||||
GPT_BASE_URL = serializers.CharField(
|
GPT_BASE_URL = serializers.CharField(
|
||||||
allow_blank=True, required=False, label=_('GPT Base URL'),
|
allow_blank=True, required=False, label=_('Base URL'),
|
||||||
help_text=_('The base URL of the GPT service. For example: https://api.openai.com/v1')
|
help_text=_('The base URL of the Chat service.')
|
||||||
)
|
)
|
||||||
GPT_API_KEY = EncryptedField(
|
GPT_API_KEY = EncryptedField(
|
||||||
allow_blank=True, required=False, label=_('API Key'),
|
allow_blank=True, required=False, label=_('API Key'),
|
||||||
|
@ -138,7 +140,23 @@ class ChatAISettingSerializer(serializers.Serializer):
|
||||||
help_text=_('The proxy server address of the GPT service. For example: http://ip:port')
|
help_text=_('The proxy server address of the GPT service. For example: http://ip:port')
|
||||||
)
|
)
|
||||||
GPT_MODEL = serializers.ChoiceField(
|
GPT_MODEL = serializers.ChoiceField(
|
||||||
default=GPT_MODEL_DEFAULT, choices=GPT_MODEL_CHOICES, label=_("GPT Model"), required=False,
|
default=GPTModelChoices.gpt_4o_mini, choices=GPTModelChoices.choices,
|
||||||
|
label=_("GPT Model"), required=False,
|
||||||
|
)
|
||||||
|
DEEPSEEK_BASE_URL = serializers.CharField(
|
||||||
|
allow_blank=True, required=False, label=_('Base URL'),
|
||||||
|
help_text=_('The base URL of the Chat service.')
|
||||||
|
)
|
||||||
|
DEEPSEEK_API_KEY = EncryptedField(
|
||||||
|
allow_blank=True, required=False, label=_('API Key'),
|
||||||
|
)
|
||||||
|
DEEPSEEK_PROXY = serializers.CharField(
|
||||||
|
allow_blank=True, required=False, label=_('Proxy'),
|
||||||
|
help_text=_('The proxy server address of the GPT service. For example: http://ip:port')
|
||||||
|
)
|
||||||
|
DEEPSEEK_MODEL = serializers.ChoiceField(
|
||||||
|
default=DeepSeekModelChoices.deepseek_chat, choices=DeepSeekModelChoices.choices,
|
||||||
|
label=_("DeepSeek Model"), required=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ class PrivateSettingSerializer(PublicSettingSerializer):
|
||||||
VAULT_ENABLED = serializers.BooleanField()
|
VAULT_ENABLED = serializers.BooleanField()
|
||||||
VIRTUAL_APP_ENABLED = serializers.BooleanField()
|
VIRTUAL_APP_ENABLED = serializers.BooleanField()
|
||||||
CHAT_AI_ENABLED = serializers.BooleanField()
|
CHAT_AI_ENABLED = serializers.BooleanField()
|
||||||
|
CHAT_AI_TYPE = serializers.CharField()
|
||||||
GPT_MODEL = serializers.CharField()
|
GPT_MODEL = serializers.CharField()
|
||||||
FILE_UPLOAD_SIZE_LIMIT_MB = serializers.IntegerField()
|
FILE_UPLOAD_SIZE_LIMIT_MB = serializers.IntegerField()
|
||||||
FTP_FILE_MAX_STORE = serializers.IntegerField()
|
FTP_FILE_MAX_STORE = serializers.IntegerField()
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
{% if INTERFACE.footer_content %}
|
{% if INTERFACE.footer_content %}
|
||||||
<style>
|
<style>
|
||||||
.markdown-footer a {
|
.markdown-footer a {
|
||||||
color: inherit;
|
color: #428bca;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-footer {
|
.markdown-footer {
|
||||||
|
@ -46,12 +46,23 @@
|
||||||
if ($('.tooltip')[0]) {
|
if ($('.tooltip')[0]) {
|
||||||
$('.tooltip').tooltip();
|
$('.tooltip').tooltip();
|
||||||
}
|
}
|
||||||
$.fn.select2.defaults.set('language', getUserLang())
|
$.fn.select2.defaults.set('language', getUserLang());
|
||||||
const md = window.markdownit();
|
const md = window.markdownit({
|
||||||
const markdownContent = document.querySelector('script[type="text/markdown"]').textContent;
|
html: true,
|
||||||
const markdownRef = document.getElementById('markdown-output')
|
linkify: true,
|
||||||
if (markdownRef) {
|
typographer: true,
|
||||||
markdownRef.innerHTML = md.render(markdownContent);
|
breaks: true
|
||||||
|
});
|
||||||
|
const markdownContent = `{{ INTERFACE.footer_content|escapejs }}`;
|
||||||
|
const markdownRef = document.getElementById('markdown-output');
|
||||||
|
|
||||||
|
if (markdownRef && markdownContent) {
|
||||||
|
const renderedContent = md.render(markdownContent.trim());
|
||||||
|
markdownRef.innerHTML = renderedContent;
|
||||||
|
markdownRef.querySelectorAll('a').forEach(link => {
|
||||||
|
link.setAttribute('target', '_blank');
|
||||||
|
link.setAttribute('rel', 'noopener noreferrer');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -9,6 +9,7 @@ from common.const.signals import OP_LOG_SKIP_SIGNAL
|
||||||
from common.db.models import JMSBaseModel
|
from common.db.models import JMSBaseModel
|
||||||
from common.utils import get_logger, lazyproperty
|
from common.utils import get_logger, lazyproperty
|
||||||
from orgs.utils import tmp_to_root_org
|
from orgs.utils import tmp_to_root_org
|
||||||
|
from settings.models import get_chatai_data
|
||||||
from terminal.const import TerminalType as TypeChoices
|
from terminal.const import TerminalType as TypeChoices
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from .status import Status
|
from .status import Status
|
||||||
|
@ -120,11 +121,13 @@ class Terminal(StorageMixin, TerminalStatusMixin, JMSBaseModel):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_chat_ai_setting():
|
def get_chat_ai_setting():
|
||||||
|
data = get_chatai_data()
|
||||||
return {
|
return {
|
||||||
'GPT_BASE_URL': settings.GPT_BASE_URL,
|
'GPT_BASE_URL': data['url'],
|
||||||
'GPT_API_KEY': settings.GPT_API_KEY,
|
'GPT_API_KEY': data['api_key'],
|
||||||
'GPT_PROXY': settings.GPT_PROXY,
|
'GPT_PROXY': data['proxy'],
|
||||||
'GPT_MODEL': settings.GPT_MODEL,
|
'GPT_MODEL': data['model'],
|
||||||
|
'CHAT_AI_TYPE': settings.CHAT_AI_TYPE,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -11,7 +11,7 @@ def create_ticket_flow_and_approval_rule(apps, schema_editor):
|
||||||
ApprovalRule = apps.get_model("tickets", "ApprovalRule")
|
ApprovalRule = apps.get_model("tickets", "ApprovalRule")
|
||||||
|
|
||||||
super_user = User.objects.get(username='admin')
|
super_user = User.objects.get(username='admin')
|
||||||
flow = TicketFlow.objects.create(created_by='System', type='apply_asset', org_id=org_id)
|
flow, created = TicketFlow.objects.get_or_create(created_by='System', type='apply_asset', org_id=org_id)
|
||||||
rule_instance = ApprovalRule.objects.create(strategy='super_admin')
|
rule_instance = ApprovalRule.objects.create(strategy='super_admin')
|
||||||
rule_instance.assignees.set([super_user])
|
rule_instance.assignees.set([super_user])
|
||||||
flow.rules.set([rule_instance, ])
|
flow.rules.set([rule_instance, ])
|
||||||
|
|
|
@ -424,7 +424,8 @@ class Ticket(StatusMixin, JMSBaseModel):
|
||||||
new_values.append(str(new_value))
|
new_values.append(str(new_value))
|
||||||
value = ', '.join(new_values)
|
value = ', '.join(new_values)
|
||||||
elif name == 'org_id':
|
elif name == 'org_id':
|
||||||
value = Organization.get_instance(value).name
|
org = Organization.get_instance(value)
|
||||||
|
value = org.name if org else ''
|
||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
value = ', '.join(value)
|
value = ', '.join(value)
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -10,7 +10,6 @@ from common.utils import get_object_or_none
|
||||||
from orgs.utils import tmp_to_root_org
|
from orgs.utils import tmp_to_root_org
|
||||||
from users.notifications import (
|
from users.notifications import (
|
||||||
ResetPasswordMsg, ResetPasswordSuccessMsg, ResetSSHKeyMsg,
|
ResetPasswordMsg, ResetPasswordSuccessMsg, ResetSSHKeyMsg,
|
||||||
ResetPublicKeySuccessMsg,
|
|
||||||
)
|
)
|
||||||
from .mixins import UserQuerysetMixin
|
from .mixins import UserQuerysetMixin
|
||||||
from .. import serializers
|
from .. import serializers
|
||||||
|
|
Loading…
Reference in New Issue