@liujitcn/kratos-admin-system 0.0.66 → 0.0.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/package/declarations/src/locales/generated.d.ts +4 -0
  2. package/dist/package/declarations/src/rpc/base/v1/ai_knowledge.d.ts +1 -1
  3. package/dist/package/declarations/src/rpc/base/v1/login.d.ts +2 -39
  4. package/dist/package/declarations/src/rpc/base/v1/oauth.d.ts +2 -2
  5. package/dist/package/declarations/src/rpc/common/v1/types.d.ts +4 -4
  6. package/dist/package/declarations/src/rpc/system/admin/v1/ai_provider.d.ts +3 -2
  7. package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +3 -3
  8. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +4 -3
  9. package/dist/package/declarations/src/rpc/system/admin/v1/base_login_policy.d.ts +2 -2
  10. package/dist/package/declarations/src/rpc/system/admin/v1/base_message_provider.d.ts +3 -2
  11. package/dist/package/declarations/src/rpc/system/admin/v1/base_oauth_provider.d.ts +3 -2
  12. package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +3 -3
  13. package/dist/package/src/components/account/ChangePasswordForm.vue +6 -4
  14. package/dist/package/src/locales/README.md +1 -1
  15. package/dist/package/src/locales/en-US.json +1 -0
  16. package/dist/package/src/locales/ja-JP.json +1 -0
  17. package/dist/package/src/locales/zh-CN.json +1 -0
  18. package/dist/package/src/locales/zh-TW.json +1 -0
  19. package/dist/package/src/module.ts +8 -0
  20. package/dist/package/src/rpc/base/v1/ai_knowledge.ts +1 -1
  21. package/dist/package/src/rpc/base/v1/login.ts +2 -42
  22. package/dist/package/src/rpc/base/v1/oauth.ts +2 -2
  23. package/dist/package/src/rpc/common/v1/types.ts +4 -4
  24. package/dist/package/src/rpc/system/admin/v1/ai_provider.ts +5 -2
  25. package/dist/package/src/rpc/system/admin/v1/auth.ts +3 -3
  26. package/dist/package/src/rpc/system/admin/v1/base_config.ts +6 -3
  27. package/dist/package/src/rpc/system/admin/v1/base_login_policy.ts +2 -2
  28. package/dist/package/src/rpc/system/admin/v1/base_message_provider.ts +5 -2
  29. package/dist/package/src/rpc/system/admin/v1/base_oauth_provider.ts +5 -2
  30. package/dist/package/src/rpc/system/admin/v1/base_user.ts +3 -3
  31. package/dist/package/src/views/ai/chat/components/XSender.vue +3 -2
  32. package/dist/package/src/views/base/ai-provider/index.vue +17 -16
  33. package/dist/package/src/views/base/config/index.vue +9 -9
  34. package/dist/package/src/views/base/login-policy/index.vue +2 -2
  35. package/dist/package/src/views/base/message-provider/index.vue +6 -4
  36. package/dist/package/src/views/base/oauth-provider/index.vue +9 -6
  37. package/dist/package/src/views/base/user/index.vue +3 -3
  38. package/dist/package/src/views/profile/components/security.vue +4 -5
  39. package/dist/package/src/views/tool/code-gen/config.ts +1 -0
  40. package/package.json +2 -2
@@ -1408,6 +1408,7 @@ export declare const LOCALE_MESSAGES: {
1408
1408
  "system.code.gen.column.value.single": string;
1409
1409
  "system.code.gen.column.value.table_comment": string;
1410
1410
  "system.code.gen.column.value.table_name": string;
1411
+ "system.code.gen.component.cascader": string;
1411
1412
  "system.code.gen.component.checkbox": string;
1412
1413
  "system.code.gen.component.checkbox_group": string;
1413
1414
  "system.code.gen.component.color_picker": string;
@@ -3293,6 +3294,7 @@ export declare const LOCALE_MESSAGES: {
3293
3294
  "system.code.gen.column.value.single": string;
3294
3295
  "system.code.gen.column.value.table_comment": string;
3295
3296
  "system.code.gen.column.value.table_name": string;
3297
+ "system.code.gen.component.cascader": string;
3296
3298
  "system.code.gen.component.checkbox": string;
3297
3299
  "system.code.gen.component.checkbox_group": string;
3298
3300
  "system.code.gen.component.color_picker": string;
@@ -5178,6 +5180,7 @@ export declare const LOCALE_MESSAGES: {
5178
5180
  "system.code.gen.column.value.single": string;
5179
5181
  "system.code.gen.column.value.table_comment": string;
5180
5182
  "system.code.gen.column.value.table_name": string;
5183
+ "system.code.gen.component.cascader": string;
5181
5184
  "system.code.gen.component.checkbox": string;
5182
5185
  "system.code.gen.component.checkbox_group": string;
5183
5186
  "system.code.gen.component.color_picker": string;
@@ -7063,6 +7066,7 @@ export declare const LOCALE_MESSAGES: {
7063
7066
  "system.code.gen.column.value.single": string;
7064
7067
  "system.code.gen.column.value.table_comment": string;
7065
7068
  "system.code.gen.column.value.table_name": string;
7069
+ "system.code.gen.component.cascader": string;
7066
7070
  "system.code.gen.component.checkbox": string;
7067
7071
  "system.code.gen.component.checkbox_group": string;
7068
7072
  "system.code.gen.component.color_picker": string;
@@ -12,7 +12,7 @@ export interface AiKnowledgeOption {
12
12
  id: number;
13
13
  /** 知识库名称 */
14
14
  name: string;
15
- /** 文档数量 */
15
+ /** 已就绪文档数,不含处理失败 */
16
16
  doc_count: number;
17
17
  }
18
18
  /** AI 知识库选项查询服务。 */
@@ -1,22 +1,5 @@
1
- import type { PasswordCrypto } from "../../common/v1/types";
1
+ import type { SecretCrypto } from "../../common/v1/types";
2
2
  import type { Empty } from "../../google/protobuf/empty";
3
- /** 密码加密场景枚举。 */
4
- export declare enum PasswordCryptoScene {
5
- /** PASSWORD_CRYPTO_SCENE_UNSPECIFIED - 未指定密码加密场景。 */
6
- PASSWORD_CRYPTO_SCENE_UNSPECIFIED = 0,
7
- /** PASSWORD_CRYPTO_SCENE_LOGIN - 登录密码加密场景。 */
8
- PASSWORD_CRYPTO_SCENE_LOGIN = 1,
9
- /** PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER - 新增后台用户密码加密场景。 */
10
- PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER = 2,
11
- /** PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD - 重置后台用户密码加密场景。 */
12
- PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD = 3,
13
- /** PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD - 个人修改密码加密场景。 */
14
- PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD = 4,
15
- /** PASSWORD_CRYPTO_SCENE_MFA - 多因素认证敏感操作场景。 */
16
- PASSWORD_CRYPTO_SCENE_MFA = 5,
17
- /** PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY - 密码策略初始化密码配置场景。 */
18
- PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY = 6
19
- }
20
3
  /**
21
4
  * LoginStatus 表示登录请求当前所处的认证阶段。
22
5
  * 只有 AUTHENTICATED 或 PASSWORD_CHANGE_REQUIRED 才会携带正式访问令牌,MFA 状态必须继续完成挑战。
@@ -38,11 +21,6 @@ export interface CaptchaRequest {
38
21
  /** 验证码类型,random 表示随机选择当前支持的验证码类型 */
39
22
  type: string;
40
23
  }
41
- /** 密码临时公钥获取条件 */
42
- export interface PasswordPublicKeyRequest {
43
- /** 使用场景 */
44
- scene: PasswordCryptoScene;
45
- }
46
24
  /** 登出请求条件 */
47
25
  export interface LogoutRequest {
48
26
  }
@@ -69,19 +47,6 @@ export interface VerifyCaptchaResponse {
69
47
  /** 有效时间,单位秒 */
70
48
  expires_in: number;
71
49
  }
72
- /** 密码临时公钥响应 */
73
- export interface PasswordPublicKeyResponse {
74
- /** 临时密钥ID */
75
- key_id: string;
76
- /** 临时公钥 */
77
- public_key: string;
78
- /** 加密算法 */
79
- algorithm: string;
80
- /** 随机值 */
81
- nonce: string;
82
- /** 有效时间,单位秒 */
83
- expires_in: number;
84
- }
85
50
  /** 刷新令牌请求参数 */
86
51
  export interface RefreshTokenRequest {
87
52
  /** 更新令牌;未填写时由服务端从HttpOnly Cookie读取。 */
@@ -105,7 +70,7 @@ export interface LoginRequest {
105
70
  /** 用户名,必选项。 */
106
71
  user_name: string;
107
72
  /** 用户的密码,必选项。 */
108
- password: PasswordCrypto | undefined;
73
+ password: SecretCrypto | undefined;
109
74
  /** 验证码 */
110
75
  captcha_code: string;
111
76
  /** 验证码Id */
@@ -142,8 +107,6 @@ export interface LoginService {
142
107
  Captcha(request: CaptchaRequest): Promise<CaptchaResponse>;
143
108
  /** 验证码预校验 */
144
109
  VerifyCaptcha(request: VerifyCaptchaRequest): Promise<VerifyCaptchaResponse>;
145
- /** 获取密码临时公钥 */
146
- PasswordPublicKey(request: PasswordPublicKeyRequest): Promise<PasswordPublicKeyResponse>;
147
110
  /** 登出 */
148
111
  Logout(request: LogoutRequest): Promise<Empty>;
149
112
  /** 刷新认证令牌 */
@@ -1,4 +1,4 @@
1
- import type { PasswordCrypto } from "../../common/v1/types";
1
+ import type { SecretCrypto } from "../../common/v1/types";
2
2
  import type { Empty } from "../../google/protobuf/empty";
3
3
  import type { LoginStatus } from "./login";
4
4
  /** 个人中心三方账号绑定列表查询条件 */
@@ -59,7 +59,7 @@ export interface BindOauthSessionRequest {
59
59
  /** 用户名 */
60
60
  user_name: string;
61
61
  /** 用户密码 */
62
- password: PasswordCrypto | undefined;
62
+ password: SecretCrypto | undefined;
63
63
  /** 验证码 */
64
64
  captcha_code: string;
65
65
  /** 验证码Id */
@@ -43,8 +43,8 @@ export interface BytesValues {
43
43
  /** 值列表。 */
44
44
  value: Uint8Array[];
45
45
  }
46
- /** 密码密文。 */
47
- export interface PasswordCrypto {
46
+ /** 敏感字段密文,密码与各类密钥字段统一使用。 */
47
+ export interface SecretCrypto {
48
48
  /** 临时密钥ID */
49
49
  key_id: string;
50
50
  /** 随机值 */
@@ -55,6 +55,6 @@ export interface PasswordCrypto {
55
55
  encrypted_key: string;
56
56
  /** 初始化向量 */
57
57
  iv: string;
58
- /** 密码加密数据 */
59
- ciphertext: string;
58
+ /** 传输时为密文,服务端解密后回填明文 */
59
+ text: string;
60
60
  }
@@ -1,4 +1,5 @@
1
1
  import type { Status } from "../../../common/v1/enum";
2
+ import type { SecretCrypto } from "../../../common/v1/types";
2
3
  import type { Empty } from "../../../google/protobuf/empty";
3
4
  /** AI模型分类枚举。 */
4
5
  export declare enum AiModelCategory {
@@ -48,8 +49,8 @@ export interface AiProviderForm {
48
49
  name: string;
49
50
  /** 模型API基础地址 */
50
51
  base_url: string;
51
- /** 模型API密钥;更新时留空表示保留现有密钥 */
52
- api_key: string;
52
+ /** 模型API密钥密文,更新时不传表示保留现有密钥 */
53
+ api_key: SecretCrypto | undefined;
53
54
  /** 是否已保存模型密钥 */
54
55
  api_key_configured: boolean;
55
56
  /** 排序值 */
@@ -1,4 +1,4 @@
1
- import type { PasswordCrypto, StringValues } from "../../../common/v1/types";
1
+ import type { SecretCrypto, StringValues } from "../../../common/v1/types";
2
2
  import type { Empty } from "../../../google/protobuf/empty";
3
3
  import type { BaseUserIDType } from "../../common/v1/common";
4
4
  import type { BaseMenuType } from "./common";
@@ -151,9 +151,9 @@ export interface RouteParams {
151
151
  /** 用户密码表单 */
152
152
  export interface UserPasswordForm {
153
153
  /** 原密码 */
154
- old_pwd: PasswordCrypto | undefined;
154
+ old_pwd: SecretCrypto | undefined;
155
155
  /** 新密码 */
156
- new_pwd: PasswordCrypto | undefined;
156
+ new_pwd: SecretCrypto | undefined;
157
157
  }
158
158
  /** 用户手机号表单 */
159
159
  export interface UserPhoneForm {
@@ -1,5 +1,6 @@
1
1
  import type { BaseConfigSite } from "../../../base/v1/config";
2
2
  import type { Status } from "../../../common/v1/enum";
3
+ import type { SecretCrypto } from "../../../common/v1/types";
3
4
  import type { Empty } from "../../../google/protobuf/empty";
4
5
  import type { BaseI18n } from "./base_i18n";
5
6
  /** 系统配置类型。 */
@@ -60,8 +61,8 @@ export interface BaseConfigForm {
60
61
  type: BaseConfigType;
61
62
  /** 配置key */
62
63
  key: string;
63
- /** 配置value */
64
- value: string;
64
+ /** 配置value,前端统一加密提交,服务端统一解密 */
65
+ value?: SecretCrypto | undefined;
65
66
  /** 配置名称多语言翻 */
66
67
  name_i18ns: BaseI18n[];
67
68
  /** 配置value文本/富文本配置值的多语言翻译 */
@@ -106,7 +107,7 @@ export interface BaseConfig {
106
107
  type: BaseConfigType;
107
108
  /** 配置key */
108
109
  key: string;
109
- /** 配置value */
110
+ /** 配置value,敏感配置恒为空 */
110
111
  value: string;
111
112
  /** 状态:枚举【Status】 */
112
113
  status: Status;
@@ -1,5 +1,5 @@
1
1
  import type { Status } from "../../../common/v1/enum";
2
- import type { PasswordCrypto } from "../../../common/v1/types";
2
+ import type { SecretCrypto } from "../../../common/v1/types";
3
3
  import type { Empty } from "../../../google/protobuf/empty";
4
4
  /** 登录策略作用域类型。 */
5
5
  export declare enum BaseLoginPolicyScopeType {
@@ -112,7 +112,7 @@ export interface BaseLoginPolicyForm {
112
112
  /** 密码至少满足的字符类别数量,字符类别包括小写、大写、数字和符号 */
113
113
  password_min_complexity_classes?: number | undefined;
114
114
  /** 初始化密码,新增用户未提交密码时使用 */
115
- initial_password: PasswordCrypto | undefined;
115
+ initial_password: SecretCrypto | undefined;
116
116
  }
117
117
  /** 登录策略列表项。 */
118
118
  export interface BaseLoginPolicy {
@@ -1,5 +1,6 @@
1
1
  import type { SelectOptionResponse } from "../../../common/v1/common";
2
2
  import type { Status } from "../../../common/v1/enum";
3
+ import type { SecretCrypto } from "../../../common/v1/types";
3
4
  import type { Empty } from "../../../google/protobuf/empty";
4
5
  /** 消息发送 Provider 选项查询条件。 */
5
6
  export interface OptionBaseMessageProviderRequest {
@@ -65,8 +66,8 @@ export interface BaseMessageProviderForm {
65
66
  icon: string;
66
67
  /** 通用凭证标识 */
67
68
  client_id: string;
68
- /** 通用凭证密钥,更新时留空表示不修改 */
69
- client_secret: string;
69
+ /** 通用凭证密钥密文,更新时不传表示不修改 */
70
+ client_secret: SecretCrypto | undefined;
70
71
  /** 是否已配置通用凭证密钥 */
71
72
  secret_configured: boolean;
72
73
  /** Provider扩展配置JSON对象 */
@@ -1,4 +1,5 @@
1
1
  import type { Status } from "../../../common/v1/enum";
2
+ import type { SecretCrypto } from "../../../common/v1/types";
2
3
  import type { Empty } from "../../../google/protobuf/empty";
3
4
  import type { BaseI18n } from "./base_i18n";
4
5
  /** OAuth登录方式分页查询条件。 */
@@ -62,8 +63,8 @@ export interface BaseOauthProviderForm {
62
63
  icon: string;
63
64
  /** 第三方应用标识 */
64
65
  client_id: string;
65
- /** 第三方应用密钥,更新时留空表示不修改 */
66
- client_secret: string;
66
+ /** 第三方应用密钥密文,更新时不传表示不修改 */
67
+ client_secret: SecretCrypto | undefined;
67
68
  /** 是否已配置第三方应用密钥 */
68
69
  secret_configured: boolean;
69
70
  /** OAuth回调地址 */
@@ -1,7 +1,7 @@
1
1
  import type { AnalyticsTimeType } from "../../../common/v1/analytics";
2
2
  import type { SelectOptionResponse } from "../../../common/v1/common";
3
3
  import type { Status } from "../../../common/v1/enum";
4
- import type { PasswordCrypto } from "../../../common/v1/types";
4
+ import type { SecretCrypto } from "../../../common/v1/types";
5
5
  import type { Empty } from "../../../google/protobuf/empty";
6
6
  import type { Timestamp } from "../../../google/protobuf/timestamp";
7
7
  import type { BaseUserIDType, BaseUserPasswordChangeStatus } from "../../common/v1/common";
@@ -164,7 +164,7 @@ export interface BaseUserForm {
164
164
  /** 性别 */
165
165
  gender: BaseUserGender;
166
166
  /** 密码 */
167
- pwd: PasswordCrypto | undefined;
167
+ pwd: SecretCrypto | undefined;
168
168
  /** 用户状态 */
169
169
  status: Status;
170
170
  /** 备注名 */
@@ -175,7 +175,7 @@ export interface ResetBaseUserPasswordRequest {
175
175
  /** 用户ID */
176
176
  id: number;
177
177
  /** 密码 */
178
- pwd: PasswordCrypto | undefined;
178
+ pwd: SecretCrypto | undefined;
179
179
  }
180
180
  /** 基础用户应用端角色设置参数 */
181
181
  export interface SetBaseUserAppRoleRequest {
@@ -29,8 +29,9 @@ import { LOGIN_URL } from "@liujitcn/kratos-admin-core/config";
29
29
  import { clearPasswordChangeRequired } from "@liujitcn/kratos-admin-core/request";
30
30
  import { useUserStore } from "@liujitcn/kratos-admin-core/stores/runtime";
31
31
  import {
32
- PASSWORD_CRYPTO_SCENE,
33
- encryptPassword
32
+ encryptPassword,
33
+ fetchSecretPublicKey,
34
+ encryptWithPublicKey
34
35
  } from "@liujitcn/kratos-admin-core/security";
35
36
 
36
37
  /** 修改密码表单状态,明文只在前端校验和加密前短暂保存。 */
@@ -91,8 +92,9 @@ async function handleSubmitPassword() {
91
92
  }
92
93
  submitLoading.value = true;
93
94
  try {
94
- const oldPwd = await encryptPassword(passwordForm.old_pwd, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD);
95
- const newPwd = await encryptPassword(passwordForm.new_pwd, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD);
95
+ const publicKey = await fetchSecretPublicKey();
96
+ const oldPwd = await encryptWithPublicKey(publicKey, passwordForm.old_pwd);
97
+ const newPwd = await encryptWithPublicKey(publicKey, passwordForm.new_pwd);
96
98
  const userPassword: UserPasswordForm = {
97
99
  old_pwd: oldPwd,
98
100
  new_pwd: newPwd
@@ -26,4 +26,4 @@
26
26
 
27
27
  语言键按文案归属使用 `common.` 或 `system.` 命名空间;语言包保持标准 JSON,不在文件内写注释。
28
28
 
29
- 新增语言的完整文件清单和迁移流程见[国际化语言扩展指南](../../../../../../../docs/国际化语言扩展指南.md)。
29
+ 新增语言的完整文件清单和迁移流程见[国际化设计与语言扩展](../../../../../../../docs/国际化最终方案.md)。
@@ -1407,6 +1407,7 @@
1407
1407
  "system.code.gen.column.value.single": "Single",
1408
1408
  "system.code.gen.column.value.table_comment": "Comment: {comment}",
1409
1409
  "system.code.gen.column.value.table_name": "Table: {name}",
1410
+ "system.code.gen.component.cascader": "Cascader",
1410
1411
  "system.code.gen.component.checkbox": "Checkbox",
1411
1412
  "system.code.gen.component.checkbox_group": "Checkbox group",
1412
1413
  "system.code.gen.component.color_picker": "Color picker",
@@ -1407,6 +1407,7 @@
1407
1407
  "system.code.gen.column.value.single": "単一の選択肢",
1408
1408
  "system.code.gen.column.value.table_comment": "テーブルの注釈: {comment}",
1409
1409
  "system.code.gen.column.value.table_name": "テーブル名: {name}",
1410
+ "system.code.gen.component.cascader": "カスケード選択",
1410
1411
  "system.code.gen.component.checkbox": "チェックボックス",
1411
1412
  "system.code.gen.component.checkbox_group": "複数選択グループ",
1412
1413
  "system.code.gen.component.color_picker": "カラーピッカー",
@@ -1407,6 +1407,7 @@
1407
1407
  "system.code.gen.column.value.single": "单选",
1408
1408
  "system.code.gen.column.value.table_comment": "表注释:{comment}",
1409
1409
  "system.code.gen.column.value.table_name": "表名:{name}",
1410
+ "system.code.gen.component.cascader": "级联选择",
1410
1411
  "system.code.gen.component.checkbox": "复选框",
1411
1412
  "system.code.gen.component.checkbox_group": "多选组",
1412
1413
  "system.code.gen.component.color_picker": "颜色选择",
@@ -1407,6 +1407,7 @@
1407
1407
  "system.code.gen.column.value.single": "單選",
1408
1408
  "system.code.gen.column.value.table_comment": "表註釋:{comment}",
1409
1409
  "system.code.gen.column.value.table_name": "表名:{name}",
1410
+ "system.code.gen.component.cascader": "級聯選擇",
1410
1411
  "system.code.gen.component.checkbox": "核取方塊",
1411
1412
  "system.code.gen.component.checkbox_group": "多選組",
1412
1413
  "system.code.gen.component.color_picker": "顏色選擇",
@@ -6,6 +6,14 @@ import Notification from "./components/notification/Notification.vue";
6
6
 
7
7
  // 语言包由同步脚本生成并注册,供 System 页面、组件和代码生成页面使用。
8
8
  import { LOCALE_MESSAGES } from "./locales/generated";
9
+ import { registerSecretRevealHandler } from "@liujitcn/kratos-admin-core/security";
10
+ import { defSecretCryptoService } from "@liujitcn/kratos-admin-core/api/base/v1/secret_crypto";
11
+
12
+ // 注册密钥明文查看实现,供 ProForm secret 字段的眼睛按需拉取。
13
+ registerSecretRevealHandler(async (resource, id, field) => {
14
+ const res = await defSecretCryptoService.RevealSecretField({ resource, id, field });
15
+ return res.text;
16
+ });
9
17
 
10
18
  const viewModules = import.meta.glob<{ default: Component }>("./views/**/*.vue");
11
19
 
@@ -22,7 +22,7 @@ export interface AiKnowledgeOption {
22
22
  id: number;
23
23
  /** 知识库名称 */
24
24
  name: string;
25
- /** 文档数量 */
25
+ /** 已就绪文档数,不含处理失败 */
26
26
  doc_count: number;
27
27
  }
28
28
 
@@ -5,27 +5,9 @@
5
5
  // source: base/v1/login.proto
6
6
 
7
7
  /* eslint-disable */
8
- import type { PasswordCrypto } from "../../common/v1/types";
8
+ import type { SecretCrypto } from "../../common/v1/types";
9
9
  import type { Empty } from "../../google/protobuf/empty";
10
10
 
11
- /** 密码加密场景枚举。 */
12
- export enum PasswordCryptoScene {
13
- /** PASSWORD_CRYPTO_SCENE_UNSPECIFIED - 未指定密码加密场景。 */
14
- PASSWORD_CRYPTO_SCENE_UNSPECIFIED = 0,
15
- /** PASSWORD_CRYPTO_SCENE_LOGIN - 登录密码加密场景。 */
16
- PASSWORD_CRYPTO_SCENE_LOGIN = 1,
17
- /** PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER - 新增后台用户密码加密场景。 */
18
- PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER = 2,
19
- /** PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD - 重置后台用户密码加密场景。 */
20
- PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD = 3,
21
- /** PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD - 个人修改密码加密场景。 */
22
- PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD = 4,
23
- /** PASSWORD_CRYPTO_SCENE_MFA - 多因素认证敏感操作场景。 */
24
- PASSWORD_CRYPTO_SCENE_MFA = 5,
25
- /** PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY - 密码策略初始化密码配置场景。 */
26
- PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY = 6,
27
- }
28
-
29
11
  /**
30
12
  * LoginStatus 表示登录请求当前所处的认证阶段。
31
13
  * 只有 AUTHENTICATED 或 PASSWORD_CHANGE_REQUIRED 才会携带正式访问令牌,MFA 状态必须继续完成挑战。
@@ -49,12 +31,6 @@ export interface CaptchaRequest {
49
31
  type: string;
50
32
  }
51
33
 
52
- /** 密码临时公钥获取条件 */
53
- export interface PasswordPublicKeyRequest {
54
- /** 使用场景 */
55
- scene: PasswordCryptoScene;
56
- }
57
-
58
34
  /** 登出请求条件 */
59
35
  export interface LogoutRequest {
60
36
  }
@@ -85,20 +61,6 @@ export interface VerifyCaptchaResponse {
85
61
  expires_in: number;
86
62
  }
87
63
 
88
- /** 密码临时公钥响应 */
89
- export interface PasswordPublicKeyResponse {
90
- /** 临时密钥ID */
91
- key_id: string;
92
- /** 临时公钥 */
93
- public_key: string;
94
- /** 加密算法 */
95
- algorithm: string;
96
- /** 随机值 */
97
- nonce: string;
98
- /** 有效时间,单位秒 */
99
- expires_in: number;
100
- }
101
-
102
64
  /** 刷新令牌请求参数 */
103
65
  export interface RefreshTokenRequest {
104
66
  /** 更新令牌;未填写时由服务端从HttpOnly Cookie读取。 */
@@ -125,7 +87,7 @@ export interface LoginRequest {
125
87
  user_name: string;
126
88
  /** 用户的密码,必选项。 */
127
89
  password:
128
- | PasswordCrypto
90
+ | SecretCrypto
129
91
  | undefined;
130
92
  /** 验证码 */
131
93
  captcha_code: string;
@@ -165,8 +127,6 @@ export interface LoginService {
165
127
  Captcha(request: CaptchaRequest): Promise<CaptchaResponse>;
166
128
  /** 验证码预校验 */
167
129
  VerifyCaptcha(request: VerifyCaptchaRequest): Promise<VerifyCaptchaResponse>;
168
- /** 获取密码临时公钥 */
169
- PasswordPublicKey(request: PasswordPublicKeyRequest): Promise<PasswordPublicKeyResponse>;
170
130
  /** 登出 */
171
131
  Logout(request: LogoutRequest): Promise<Empty>;
172
132
  /** 刷新认证令牌 */
@@ -5,7 +5,7 @@
5
5
  // source: base/v1/oauth.proto
6
6
 
7
7
  /* eslint-disable */
8
- import type { PasswordCrypto } from "../../common/v1/types";
8
+ import type { SecretCrypto } from "../../common/v1/types";
9
9
  import type { Empty } from "../../google/protobuf/empty";
10
10
  import type { LoginStatus } from "./login";
11
11
 
@@ -77,7 +77,7 @@ export interface BindOauthSessionRequest {
77
77
  user_name: string;
78
78
  /** 用户密码 */
79
79
  password:
80
- | PasswordCrypto
80
+ | SecretCrypto
81
81
  | undefined;
82
82
  /** 验证码 */
83
83
  captcha_code: string;
@@ -60,8 +60,8 @@ export interface BytesValues {
60
60
  value: Uint8Array[];
61
61
  }
62
62
 
63
- /** 密码密文。 */
64
- export interface PasswordCrypto {
63
+ /** 敏感字段密文,密码与各类密钥字段统一使用。 */
64
+ export interface SecretCrypto {
65
65
  /** 临时密钥ID */
66
66
  key_id: string;
67
67
  /** 随机值 */
@@ -72,6 +72,6 @@ export interface PasswordCrypto {
72
72
  encrypted_key: string;
73
73
  /** 初始化向量 */
74
74
  iv: string;
75
- /** 密码加密数据 */
76
- ciphertext: string;
75
+ /** 传输时为密文,服务端解密后回填明文 */
76
+ text: string;
77
77
  }
@@ -6,6 +6,7 @@
6
6
 
7
7
  /* eslint-disable */
8
8
  import type { Status } from "../../../common/v1/enum";
9
+ import type { SecretCrypto } from "../../../common/v1/types";
9
10
  import type { Empty } from "../../../google/protobuf/empty";
10
11
 
11
12
  /** AI模型分类枚举。 */
@@ -62,8 +63,10 @@ export interface AiProviderForm {
62
63
  name: string;
63
64
  /** 模型API基础地址 */
64
65
  base_url: string;
65
- /** 模型API密钥;更新时留空表示保留现有密钥 */
66
- api_key: string;
66
+ /** 模型API密钥密文,更新时不传表示保留现有密钥 */
67
+ api_key:
68
+ | SecretCrypto
69
+ | undefined;
67
70
  /** 是否已保存模型密钥 */
68
71
  api_key_configured: boolean;
69
72
  /** 排序值 */
@@ -5,7 +5,7 @@
5
5
  // source: system/admin/v1/auth.proto
6
6
 
7
7
  /* eslint-disable */
8
- import type { PasswordCrypto, StringValues } from "../../../common/v1/types";
8
+ import type { SecretCrypto, StringValues } from "../../../common/v1/types";
9
9
  import type { Empty } from "../../../google/protobuf/empty";
10
10
  import type { BaseUserIDType } from "../../common/v1/common";
11
11
  import type { BaseMenuType } from "./common";
@@ -202,10 +202,10 @@ export interface RouteParams {
202
202
  export interface UserPasswordForm {
203
203
  /** 原密码 */
204
204
  old_pwd:
205
- | PasswordCrypto
205
+ | SecretCrypto
206
206
  | undefined;
207
207
  /** 新密码 */
208
- new_pwd: PasswordCrypto | undefined;
208
+ new_pwd: SecretCrypto | undefined;
209
209
  }
210
210
 
211
211
  /** 用户手机号表单 */
@@ -7,6 +7,7 @@
7
7
  /* eslint-disable */
8
8
  import type { BaseConfigSite } from "../../../base/v1/config";
9
9
  import type { Status } from "../../../common/v1/enum";
10
+ import type { SecretCrypto } from "../../../common/v1/types";
10
11
  import type { Empty } from "../../../google/protobuf/empty";
11
12
  import type { BaseI18n } from "./base_i18n";
12
13
 
@@ -82,8 +83,10 @@ export interface BaseConfigForm {
82
83
  type: BaseConfigType;
83
84
  /** 配置key */
84
85
  key: string;
85
- /** 配置value */
86
- value: string;
86
+ /** 配置value,前端统一加密提交,服务端统一解密 */
87
+ value?:
88
+ | SecretCrypto
89
+ | undefined;
87
90
  /** 配置名称多语言翻 */
88
91
  name_i18ns: BaseI18n[];
89
92
  /** 配置value文本/富文本配置值的多语言翻译 */
@@ -134,7 +137,7 @@ export interface BaseConfig {
134
137
  type: BaseConfigType;
135
138
  /** 配置key */
136
139
  key: string;
137
- /** 配置value */
140
+ /** 配置value,敏感配置恒为空 */
138
141
  value: string;
139
142
  /** 状态:枚举【Status】 */
140
143
  status: Status;
@@ -6,7 +6,7 @@
6
6
 
7
7
  /* eslint-disable */
8
8
  import type { Status } from "../../../common/v1/enum";
9
- import type { PasswordCrypto } from "../../../common/v1/types";
9
+ import type { SecretCrypto } from "../../../common/v1/types";
10
10
  import type { Empty } from "../../../google/protobuf/empty";
11
11
 
12
12
  /** 登录策略作用域类型。 */
@@ -144,7 +144,7 @@ export interface BaseLoginPolicyForm {
144
144
  | number
145
145
  | undefined;
146
146
  /** 初始化密码,新增用户未提交密码时使用 */
147
- initial_password: PasswordCrypto | undefined;
147
+ initial_password: SecretCrypto | undefined;
148
148
  }
149
149
 
150
150
  /** 登录策略列表项。 */
@@ -7,6 +7,7 @@
7
7
  /* eslint-disable */
8
8
  import type { SelectOptionResponse } from "../../../common/v1/common";
9
9
  import type { Status } from "../../../common/v1/enum";
10
+ import type { SecretCrypto } from "../../../common/v1/types";
10
11
  import type { Empty } from "../../../google/protobuf/empty";
11
12
 
12
13
  /** 消息发送 Provider 选项查询条件。 */
@@ -87,8 +88,10 @@ export interface BaseMessageProviderForm {
87
88
  icon: string;
88
89
  /** 通用凭证标识 */
89
90
  client_id: string;
90
- /** 通用凭证密钥,更新时留空表示不修改 */
91
- client_secret: string;
91
+ /** 通用凭证密钥密文,更新时不传表示不修改 */
92
+ client_secret:
93
+ | SecretCrypto
94
+ | undefined;
92
95
  /** 是否已配置通用凭证密钥 */
93
96
  secret_configured: boolean;
94
97
  /** Provider扩展配置JSON对象 */
@@ -6,6 +6,7 @@
6
6
 
7
7
  /* eslint-disable */
8
8
  import type { Status } from "../../../common/v1/enum";
9
+ import type { SecretCrypto } from "../../../common/v1/types";
9
10
  import type { Empty } from "../../../google/protobuf/empty";
10
11
  import type { BaseI18n } from "./base_i18n";
11
12
 
@@ -83,8 +84,10 @@ export interface BaseOauthProviderForm {
83
84
  icon: string;
84
85
  /** 第三方应用标识 */
85
86
  client_id: string;
86
- /** 第三方应用密钥,更新时留空表示不修改 */
87
- client_secret: string;
87
+ /** 第三方应用密钥密文,更新时不传表示不修改 */
88
+ client_secret:
89
+ | SecretCrypto
90
+ | undefined;
88
91
  /** 是否已配置第三方应用密钥 */
89
92
  secret_configured: boolean;
90
93
  /** OAuth回调地址 */
@@ -8,7 +8,7 @@
8
8
  import type { AnalyticsTimeType } from "../../../common/v1/analytics";
9
9
  import type { SelectOptionResponse } from "../../../common/v1/common";
10
10
  import type { Status } from "../../../common/v1/enum";
11
- import type { PasswordCrypto } from "../../../common/v1/types";
11
+ import type { SecretCrypto } from "../../../common/v1/types";
12
12
  import type { Empty } from "../../../google/protobuf/empty";
13
13
  import type { Timestamp } from "../../../google/protobuf/timestamp";
14
14
  import type { BaseUserIDType, BaseUserPasswordChangeStatus } from "../../common/v1/common";
@@ -193,7 +193,7 @@ export interface BaseUserForm {
193
193
  gender: BaseUserGender;
194
194
  /** 密码 */
195
195
  pwd:
196
- | PasswordCrypto
196
+ | SecretCrypto
197
197
  | undefined;
198
198
  /** 用户状态 */
199
199
  status: Status;
@@ -206,7 +206,7 @@ export interface ResetBaseUserPasswordRequest {
206
206
  /** 用户ID */
207
207
  id: number;
208
208
  /** 密码 */
209
- pwd: PasswordCrypto | undefined;
209
+ pwd: SecretCrypto | undefined;
210
210
  }
211
211
 
212
212
  /** 基础用户应用端角色设置参数 */
@@ -169,8 +169,9 @@
169
169
  @click="handleKnowledgeToggle(option.id)"
170
170
  >
171
171
  <span class="agent-model-row__name">{{ option.name }}</span>
172
- <span v-if="option.doc_count" class="agent-model-row__raw">{{
173
- t("system.ai.knowledge.doc_count", { count: option.doc_count })
172
+ <!-- proto3 JSON 会省略零值字段,计数为 0 时前端补默认值。 -->
173
+ <span class="agent-model-row__raw">{{
174
+ t("system.ai.knowledge.doc_count", { count: option.doc_count ?? 0 })
174
175
  }}</span>
175
176
  <el-icon v-if="isKnowledgeSelected(option.id)" class="agent-model-row__check">
176
177
  <Check />
@@ -119,6 +119,7 @@ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
119
119
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
120
120
  import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
121
121
  import { t } from "@liujitcn/kratos-admin-core";
122
+ import { encodeSecretFields } from "@liujitcn/kratos-admin-core/security";
122
123
  import { defAiProviderService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/ai_provider";
123
124
  import {
124
125
  type AiProvider,
@@ -240,7 +241,7 @@ const fields = computed<ProFormField[]>(() => [
240
241
  { prop: "provider", label: t("system.base.ai_provider.field.provider"), component: "select", colSpan: 12, options: providerOptions.value, props: { disabled: dialog.editing } },
241
242
  { prop: "name", label: t("system.base.ai_provider.field.name"), component: "input", colSpan: 12, props: { maxlength: 100, autocomplete: "off" } },
242
243
  { prop: "base_url", label: t("system.base.ai_provider.field.base_url"), component: "input", colSpan: 12, props: { maxlength: 512, autocomplete: "off", placeholder: t("system.base.ai_provider.placeholder.base_url") } },
243
- { prop: "api_key", label: t("system.base.ai_provider.field.api_key"), component: "input", colSpan: 12, props: { type: "password", showPassword: true, maxlength: 1024, autocomplete: "new-password", placeholder: form.api_key_configured ? t("system.base.ai_provider.placeholder.keep_api_key") : t("system.base.ai_provider.placeholder.api_key") } },
244
+ { prop: "api_key", label: t("system.base.ai_provider.field.api_key"), component: "input", colSpan: 12, secret: { resource: "ai_provider", field: "api_key" }, props: { type: "password", showPassword: true, maxlength: 1024, autocomplete: "new-password", placeholder: form.api_key_configured ? t("system.base.ai_provider.placeholder.keep_api_key") : t("system.base.ai_provider.placeholder.api_key") } },
244
245
  { prop: "models", label: t("system.base.ai_provider.field.models"), component: "slot", slotName: "models", colSpan: 24 },
245
246
  { prop: "config_items", label: t("system.base.ai_provider.field.config"), component: "kv-list", colSpan: 24, props: { keyInputProps: { maxlength: 128 } } },
246
247
  { prop: "sort", label: t("common.field.sort"), component: "input-number", colSpan: 12, props: { min: 0, precision: 0 } },
@@ -334,7 +335,7 @@ function defaultForm(): FormState {
334
335
  provider: "openai_compatible",
335
336
  name: "",
336
337
  base_url: "",
337
- api_key: "",
338
+ api_key: undefined,
338
339
  api_key_configured: false,
339
340
  models: [],
340
341
  config: {},
@@ -409,7 +410,7 @@ async function openDialog(id?: number) {
409
410
  async function submit() {
410
411
  const valid = await dialogRef.value?.validate();
411
412
  if (!valid) return;
412
- const payload = buildAiProviderPayload();
413
+ const payload = buildAiProviderPayload(await encodeSecretFields(fields.value, form));
413
414
  if (!payload) return;
414
415
  if (dialog.editing) await defAiProviderService.UpdateAiProvider({ ai_provider: payload });
415
416
  else await defAiProviderService.CreateAiProvider({ ai_provider: payload });
@@ -423,7 +424,7 @@ async function submit() {
423
424
  async function testProviderModels() {
424
425
  const valid = await dialogRef.value?.validate();
425
426
  if (!valid) return;
426
- const payload = buildAiProviderPayload();
427
+ const payload = buildAiProviderPayload(await encodeSecretFields(fields.value, form));
427
428
  if (!payload) return;
428
429
 
429
430
  testingModels.value = true;
@@ -437,21 +438,21 @@ async function testProviderModels() {
437
438
  modelTestResults.value = Object.fromEntries(response.results.map(result => [result.model_name, result]));
438
439
  }
439
440
 
440
- /** 构造AI Provider保存或测试请求参数。 */
441
- function buildAiProviderPayload(): AiProviderForm | undefined {
442
- const config = configItemsToMap(form.config_items);
441
+ /** 构造AI Provider保存或测试请求参数,source 为加密转换后的提交模型。 */
442
+ function buildAiProviderPayload(source: Record<string, any>): AiProviderForm | undefined {
443
+ const config = configItemsToMap(source.config_items);
443
444
  if (!config) return undefined;
444
445
  return {
445
- id: form.id,
446
- provider: form.provider,
447
- name: form.name,
448
- base_url: form.base_url,
449
- api_key: form.api_key,
450
- api_key_configured: form.api_key_configured,
451
- models: form.models.map(model => buildModelPayload(model)),
446
+ id: source.id,
447
+ provider: source.provider,
448
+ name: source.name,
449
+ base_url: source.base_url,
450
+ api_key: source.api_key,
451
+ api_key_configured: source.api_key_configured,
452
+ models: source.models.map(model => buildModelPayload(model)),
452
453
  config,
453
- sort: form.sort,
454
- status: form.status
454
+ sort: source.sort,
455
+ status: source.status
455
456
  };
456
457
  }
457
458
 
@@ -144,6 +144,7 @@ import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
144
144
  import { BaseConfigType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_config";
145
145
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
146
146
  import { t } from "@liujitcn/kratos-admin-core";
147
+ import { encryptSecret } from "@liujitcn/kratos-admin-core/security";
147
148
  import DynamicI18nEditor from "@liujitcn/kratos-admin-system/components/i18n/DynamicI18nEditor.vue";
148
149
  import DynamicI18nCell from "@liujitcn/kratos-admin-system/components/i18n/DynamicI18nCell.vue";
149
150
  import {
@@ -153,11 +154,13 @@ import {
153
154
  } from "@liujitcn/kratos-admin-system/components/i18n/dynamicI18n";
154
155
 
155
156
  /** 系统配置编辑表单状态,新增时枚举字段保持为空,避免把未知值 0 显示为下拉文本。 */
156
- type BaseConfigFormState = Omit<BaseConfigForm, "site" | "type"> & {
157
+ type BaseConfigFormState = Omit<BaseConfigForm, "site" | "type" | "value"> & {
157
158
  /** 配置位置。 */
158
159
  site?: BaseConfigSite;
159
160
  /** 配置类型。 */
160
161
  type?: BaseConfigType;
162
+ /** 配置值编辑缓冲,提交时统一加密为 SecretCrypto。 */
163
+ value: string;
161
164
  };
162
165
 
163
166
  defineOptions({
@@ -337,13 +340,6 @@ const rules = computed(() => ({
337
340
  trigger: "blur"
338
341
  }
339
342
  ],
340
- value: [
341
- {
342
- required: true,
343
- message: t("common.validation.required_input", { field: t("system.base.config.field.value") }),
344
- trigger: "blur"
345
- }
346
- ],
347
343
  status: [
348
344
  {
349
345
  required: true,
@@ -661,6 +657,8 @@ async function handleOpenDialog(configId?: number) {
661
657
  commit: ({ data }) => {
662
658
  if (data) {
663
659
  Object.assign(formData, data);
660
+ // 契约中 value 为 SecretCrypto,编辑缓冲取解密后的明文或脱敏文本。
661
+ formData.value = data.value?.text ?? "";
664
662
  if (formData.type === BaseConfigType.BASE_CONFIG_TYPE_FORM) loadFormValue(formData.value);
665
663
  }
666
664
  activeTab.value = configId && formData.type === BaseConfigType.BASE_CONFIG_TYPE_FORM ? "form" : "basic";
@@ -774,6 +772,8 @@ async function handleSubmit() {
774
772
  saving.value = true;
775
773
  try {
776
774
  const submitData = JSON.parse(JSON.stringify(formData)) as BaseConfigForm;
775
+ // 配置值统一密文提交,留空表示保留现有值。
776
+ submitData.value = formData.value.trim() !== "" ? await encryptSecret(formData.value) : undefined;
777
777
  submitData.name_i18ns = serializeDynamicI18ns(
778
778
  nameI18nValues.value,
779
779
  "base_config.name",
@@ -786,7 +786,7 @@ async function handleSubmit() {
786
786
  valueI18nValues.value,
787
787
  "base_config.value",
788
788
  submitData.id,
789
- submitData.value
789
+ formData.value
790
790
  )
791
791
  : [];
792
792
 
@@ -74,7 +74,7 @@ import type { ColumnProps, HeaderActionProps, ProTableInstance } from "@liujitcn
74
74
  import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
75
75
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
76
76
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
77
- import { PASSWORD_CRYPTO_SCENE, encryptPassword } from "@liujitcn/kratos-admin-core/security";
77
+ import { encryptPassword } from "@liujitcn/kratos-admin-core/security";
78
78
  import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
79
79
  import { t } from "@liujitcn/kratos-admin-core";
80
80
  import { defBaseLoginPolicyService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_login_policy";
@@ -490,7 +490,7 @@ async function handleSubmit() {
490
490
  tenant_id: formData.tenant_id ?? 0,
491
491
  user_id: formData.user_id ?? 0,
492
492
  initial_password: formData.initial_password
493
- ? await encryptPassword(formData.initial_password, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY)
493
+ ? await encryptPassword(formData.initial_password, )
494
494
  : undefined
495
495
  };
496
496
  if (formData.id) await defBaseLoginPolicyService.UpdateBaseLoginPolicy({ base_login_policy: baseLoginPolicy });
@@ -27,6 +27,7 @@ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
27
27
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
28
28
  import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
29
29
  import { t } from "@liujitcn/kratos-admin-core";
30
+ import { encodeSecretFields } from "@liujitcn/kratos-admin-core/security";
30
31
  import { defBaseMessageProviderService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_message_provider";
31
32
  import type {
32
33
  BaseMessageProvider,
@@ -69,7 +70,7 @@ const formFields = computed<ProFormField[]>(() => [
69
70
  { prop: "description", label: t("system.base.message_provider.field.description"), component: "input", colSpan: 24, props: { maxlength: 255 } },
70
71
  { prop: "icon", label: t("system.base.message_provider.field.icon"), component: "input", props: { maxlength: 100 } },
71
72
  { prop: "client_id", label: t("system.base.message_provider.field.client_id"), component: "input", props: { maxlength: 255, autocomplete: "off" } },
72
- { prop: "client_secret", label: t("system.base.message_provider.field.client_secret"), component: "input", props: { type: "password", showPassword: true, maxlength: 1024, autocomplete: "new-password", placeholder: dialog.editing ? t("system.base.message_provider.placeholder.keep_secret") : "" } },
73
+ { prop: "client_secret", label: t("system.base.message_provider.field.client_secret"), component: "input", secret: { resource: "base_message_provider", field: "client_secret" }, props: { type: "password", showPassword: true, maxlength: 1024, autocomplete: "new-password", placeholder: dialog.editing ? t("system.base.message_provider.placeholder.keep_secret") : "" } },
73
74
  { prop: "config_items", label: t("system.base.message_provider.field.config"), component: "kv-list", props: { keyInputProps: { maxlength: 128 } } },
74
75
  { prop: "sort", label: t("common.field.sort"), component: "input-number", props: { min: 0, precision: 0 } },
75
76
  { prop: "status", label: t("common.field.status"), component: "radio-group", options: statusOptions.value }
@@ -99,7 +100,7 @@ const headerActions = computed<HeaderActionProps[]>(() => [
99
100
  ]);
100
101
 
101
102
  function defaultForm(): FormState {
102
- return { id: 0, provider: "", name: "", description: "", icon: "", client_id: "", client_secret: "", secret_configured: false, config: {}, config_items: [], sort: 0, status: Status.STATUS_DISABLE };
103
+ return { id: 0, provider: "", name: "", description: "", icon: "", client_id: "", client_secret: undefined, secret_configured: false, config: {}, config_items: [], sort: 0, status: Status.STATUS_DISABLE };
103
104
  }
104
105
 
105
106
  async function requestTable(params: Record<string, unknown>) {
@@ -121,8 +122,9 @@ async function handleSubmit() {
121
122
  const payload = JSON.parse(JSON.stringify(formData)) as BaseMessageProviderForm & { config_items?: ConfigItem[] };
122
123
  delete payload.config_items;
123
124
  payload.config = config;
124
- if (payload.id) await defBaseMessageProviderService.UpdateBaseMessageProvider({ base_message_provider: payload });
125
- else await defBaseMessageProviderService.CreateBaseMessageProvider({ base_message_provider: payload });
125
+ const form = await encodeSecretFields(formFields.value, payload) as BaseMessageProviderForm;
126
+ if (form.id) await defBaseMessageProviderService.UpdateBaseMessageProvider({ base_message_provider: form });
127
+ else await defBaseMessageProviderService.CreateBaseMessageProvider({ base_message_provider: form });
126
128
  ElMessage.success(t("common.message.operation_success"));
127
129
  dialog.visible = false;
128
130
  await proTable.value?.getTableList();
@@ -39,6 +39,7 @@ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
39
39
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
40
40
  import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
41
41
  import { t } from "@liujitcn/kratos-admin-core";
42
+ import { encodeSecretFields } from "@liujitcn/kratos-admin-core/security";
42
43
  import { defBaseOauthProviderService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_oauth_provider";
43
44
  import { loadEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_language";
44
45
  import type {
@@ -103,7 +104,7 @@ const formFields = computed<ProFormField[]>(() => [
103
104
  { prop: "description", suffixSlotName: "descriptionI18ns", label: t("system.base.oauth_provider.field.description"), component: "input", colSpan: 24, props: { maxlength: 255, placeholder: t("system.base.oauth_provider.placeholder.description") } },
104
105
  { prop: "icon", label: t("system.base.oauth_provider.field.icon"), component: "input", colSpan: 12, props: { maxlength: 255, placeholder: t("system.base.oauth_provider.placeholder.icon") } },
105
106
  { prop: "client_id", label: t("system.base.oauth_provider.field.client_id"), component: "input", colSpan: 12, props: { maxlength: 255, autocomplete: "off", placeholder: t("system.base.oauth_provider.placeholder.client_id") } },
106
- { prop: "client_secret", label: t("system.base.oauth_provider.field.client_secret"), component: "input", colSpan: 12, props: { type: "password", showPassword: true, maxlength: 512, autocomplete: "new-password", placeholder: dialog.editing ? t("system.base.oauth_provider.placeholder.keep_secret") : t("system.base.oauth_provider.placeholder.client_secret") } },
107
+ { prop: "client_secret", label: t("system.base.oauth_provider.field.client_secret"), component: "input", colSpan: 12, secret: { resource: "base_oauth_provider", field: "client_secret" }, props: { type: "password", showPassword: true, maxlength: 512, autocomplete: "new-password", placeholder: dialog.editing ? t("system.base.oauth_provider.placeholder.keep_secret") : t("system.base.oauth_provider.placeholder.client_secret") } },
107
108
  { prop: "redirect_uri", label: t("system.base.oauth_provider.field.redirect_uri"), component: "input", colSpan: 12, props: { maxlength: 512, placeholder: t("system.base.oauth_provider.placeholder.redirect_uri") } },
108
109
  { prop: "scopes", label: t("system.base.oauth_provider.field.scopes"), component: "dynamic-list", colSpan: 12, props: { inputProps: { maxlength: 128, placeholder: t("system.base.oauth_provider.placeholder.scopes") } } },
109
110
  { prop: "config_items", label: t("system.base.oauth_provider.field.config"), component: "kv-list", colSpan: 12, props: { keyInputProps: { maxlength: 128 } } },
@@ -152,7 +153,7 @@ const headerActions = computed<HeaderActionProps[]>(() => [
152
153
 
153
154
  /** 创建默认 OAuth 登录方式表单。 */
154
155
  function defaultForm(): OauthProviderFormState {
155
- return { id: 0, provider: "", name: "", description: "", icon: "", client_id: "", client_secret: "", secret_configured: false, redirect_uri: "", scopes: [], config: {}, config_items: [], sort: 0, status: Status.STATUS_DISABLE, name_i18ns: [], description_i18ns: [] };
156
+ return { id: 0, provider: "", name: "", description: "", icon: "", client_id: "", client_secret: undefined, secret_configured: false, redirect_uri: "", scopes: [], config: {}, config_items: [], sort: 0, status: Status.STATUS_DISABLE, name_i18ns: [], description_i18ns: [] };
156
157
  }
157
158
 
158
159
  /** 请求 OAuth 登录方式表格数据。 */
@@ -185,11 +186,13 @@ async function handleSubmit() {
185
186
  const payload = JSON.parse(JSON.stringify(formData)) as BaseOauthProviderForm & { config_items?: OauthProviderConfigItem[] };
186
187
  delete payload.config_items;
187
188
  payload.config = config;
189
+ const source = await encodeSecretFields(formFields.value, payload);
188
190
  payload.scopes = [...new Set(formData.scopes.map(value => value.trim()).filter(Boolean))];
189
- payload.name_i18ns = serializeDynamicI18ns(nameI18nValues.value, "base_oauth_provider.name", payload.id, payload.name);
190
- payload.description_i18ns = serializeDynamicI18ns(descriptionI18nValues.value, "base_oauth_provider.description", payload.id, payload.description);
191
- if (payload.id) await defBaseOauthProviderService.UpdateBaseOauthProvider({ base_oauth_provider: payload });
192
- else await defBaseOauthProviderService.CreateBaseOauthProvider({ base_oauth_provider: payload });
191
+ source.name_i18ns = serializeDynamicI18ns(nameI18nValues.value, "base_oauth_provider.name", source.id, source.name);
192
+ source.description_i18ns = serializeDynamicI18ns(descriptionI18nValues.value, "base_oauth_provider.description", source.id, source.name);
193
+ const form = source as BaseOauthProviderForm;
194
+ if (form.id) await defBaseOauthProviderService.UpdateBaseOauthProvider({ base_oauth_provider: form });
195
+ else await defBaseOauthProviderService.CreateBaseOauthProvider({ base_oauth_provider: form });
193
196
  ElMessage.success(t("common.message.operation_success"));
194
197
  dialog.visible = false;
195
198
  await proTable.value?.getTableList();
@@ -85,7 +85,7 @@ import { defBasePostService } from "@liujitcn/kratos-admin-system/api/system/adm
85
85
  import type { SelectOptionResponse_Option, TreeOptionResponse_Option } from "@liujitcn/kratos-admin-system/rpc/common/v1/common";
86
86
  import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
87
87
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
88
- import { PASSWORD_CRYPTO_SCENE, encryptPassword } from "@liujitcn/kratos-admin-core/security";
88
+ import { encryptPassword } from "@liujitcn/kratos-admin-core/security";
89
89
  import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
90
90
  import { t } from "@liujitcn/kratos-admin-core";
91
91
 
@@ -775,7 +775,7 @@ async function handleConfirmResetPassword() {
775
775
  resetPwdFormDialogRef.value?.validate()?.then(async valid => {
776
776
  if (!valid) return;
777
777
 
778
- const pwd = await encryptPassword(resetPwdForm.pwd, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD);
778
+ const pwd = await encryptPassword(resetPwdForm.pwd, );
779
779
  defBaseUserService.ResetBaseUserPassword({ id: resetPwdForm.id, pwd }).then(() => {
780
780
  ElMessage.success(t("system.base.user.message.reset_password_success", { name: resetPwdTargetName.value }));
781
781
  handleCloseResetPasswordDialog();
@@ -796,7 +796,7 @@ const handleSubmit = useDebounceFn(() => {
796
796
  pwd:
797
797
  submitData.id || !submitData.pwd
798
798
  ? undefined
799
- : await encryptPassword(submitData.pwd, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER)
799
+ : await encryptPassword(submitData.pwd, )
800
800
  } as BaseUserForm;
801
801
  const request = submitData.id
802
802
  ? defBaseUserService.UpdateBaseUser({ base_user: baseUser })
@@ -192,12 +192,11 @@ import ProForm from "@liujitcn/kratos-admin-core/components/ProForm/index.vue";
192
192
  import MfaSetupPanel from "@liujitcn/kratos-admin-core/components/Mfa/MfaSetupPanel.vue";
193
193
  import MfaRecoveryCodesDialog from "@liujitcn/kratos-admin-core/components/Mfa/MfaRecoveryCodesDialog.vue";
194
194
  import type { ProFormField, ProFormInstance } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
195
- import type { PasswordCrypto } from "@liujitcn/kratos-admin-core/rpc/common/v1/types";
195
+ import type { SecretCrypto } from "@liujitcn/kratos-admin-core/rpc/common/v1/types";
196
196
  import {
197
197
  getOauthProviderIcon,
198
198
  withOauthProviderDisplay,
199
199
  type OauthProviderDisplay,
200
- PASSWORD_CRYPTO_SCENE,
201
200
  encryptPassword,
202
201
  copyText,
203
202
  createWebAuthnCredential,
@@ -449,7 +448,7 @@ function openMfaRecovery() {
449
448
  }
450
449
 
451
450
  /** 开始绑定 MFA。 */
452
- async function beginMfaSetup(password: PasswordCrypto) {
451
+ async function beginMfaSetup(password: SecretCrypto) {
453
452
  mfaLoading.value = true;
454
453
  try {
455
454
  const result = await defMfaService.BeginMfaSetup({ password, setup_ticket: "" });
@@ -494,7 +493,7 @@ async function disableMfa() {
494
493
  }
495
494
  mfaLoading.value = true;
496
495
  try {
497
- const password = await encryptPassword(mfaForm.password, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_MFA);
496
+ const password = await encryptPassword(mfaForm.password);
498
497
  if (mfaForm.recoveryCode) {
499
498
  await defMfaService.DisableMfa({
500
499
  password,
@@ -574,7 +573,7 @@ async function handleMfaAction() {
574
573
  return;
575
574
  }
576
575
  try {
577
- const password = await encryptPassword(mfaForm.password, PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_MFA);
576
+ const password = await encryptPassword(mfaForm.password);
578
577
  await beginMfaSetup(password);
579
578
  mfaForm.password = "";
580
579
  } catch (error) {
@@ -81,6 +81,7 @@ const codeGenFormComponentLabelKeys: Record<ProFormComponentType, string> = {
81
81
  switch: "system.code.gen.component.switch",
82
82
  checkbox: "system.code.gen.component.checkbox",
83
83
  select: "system.code.gen.component.select",
84
+ cascader: "system.code.gen.component.cascader",
84
85
  "tenant-select": "system.code.gen.component.select",
85
86
  dict: "system.code.gen.component.dict",
86
87
  "radio-group": "system.code.gen.component.radio_group",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@liujitcn/kratos-admin-system",
3
3
  "private": false,
4
- "version": "0.0.66",
4
+ "version": "0.0.68",
5
5
  "type": "module",
6
6
  "description": "kratos-admin system management module",
7
7
  "license": "MIT",
@@ -16,7 +16,7 @@
16
16
  "sortablejs": "^1.15.2",
17
17
  "swagger-ui-dist": "^5.32.15",
18
18
  "vue-element-plus-x": "^2.0.3",
19
- "@liujitcn/kratos-admin-core": "0.0.66"
19
+ "@liujitcn/kratos-admin-core": "0.0.68"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "@element-plus/icons-vue": "^2.3.1",