@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.
- package/dist/package/declarations/src/locales/generated.d.ts +4 -0
- package/dist/package/declarations/src/rpc/base/v1/ai_knowledge.d.ts +1 -1
- package/dist/package/declarations/src/rpc/base/v1/login.d.ts +2 -39
- package/dist/package/declarations/src/rpc/base/v1/oauth.d.ts +2 -2
- package/dist/package/declarations/src/rpc/common/v1/types.d.ts +4 -4
- package/dist/package/declarations/src/rpc/system/admin/v1/ai_provider.d.ts +3 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +3 -3
- package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +4 -3
- package/dist/package/declarations/src/rpc/system/admin/v1/base_login_policy.d.ts +2 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/base_message_provider.d.ts +3 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/base_oauth_provider.d.ts +3 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +3 -3
- package/dist/package/src/components/account/ChangePasswordForm.vue +6 -4
- package/dist/package/src/locales/README.md +1 -1
- package/dist/package/src/locales/en-US.json +1 -0
- package/dist/package/src/locales/ja-JP.json +1 -0
- package/dist/package/src/locales/zh-CN.json +1 -0
- package/dist/package/src/locales/zh-TW.json +1 -0
- package/dist/package/src/module.ts +8 -0
- package/dist/package/src/rpc/base/v1/ai_knowledge.ts +1 -1
- package/dist/package/src/rpc/base/v1/login.ts +2 -42
- package/dist/package/src/rpc/base/v1/oauth.ts +2 -2
- package/dist/package/src/rpc/common/v1/types.ts +4 -4
- package/dist/package/src/rpc/system/admin/v1/ai_provider.ts +5 -2
- package/dist/package/src/rpc/system/admin/v1/auth.ts +3 -3
- package/dist/package/src/rpc/system/admin/v1/base_config.ts +6 -3
- package/dist/package/src/rpc/system/admin/v1/base_login_policy.ts +2 -2
- package/dist/package/src/rpc/system/admin/v1/base_message_provider.ts +5 -2
- package/dist/package/src/rpc/system/admin/v1/base_oauth_provider.ts +5 -2
- package/dist/package/src/rpc/system/admin/v1/base_user.ts +3 -3
- package/dist/package/src/views/ai/chat/components/XSender.vue +3 -2
- package/dist/package/src/views/base/ai-provider/index.vue +17 -16
- package/dist/package/src/views/base/config/index.vue +9 -9
- package/dist/package/src/views/base/login-policy/index.vue +2 -2
- package/dist/package/src/views/base/message-provider/index.vue +6 -4
- package/dist/package/src/views/base/oauth-provider/index.vue +9 -6
- package/dist/package/src/views/base/user/index.vue +3 -3
- package/dist/package/src/views/profile/components/security.vue +4 -5
- package/dist/package/src/views/tool/code-gen/config.ts +1 -0
- 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;
|
|
@@ -1,22 +1,5 @@
|
|
|
1
|
-
import type {
|
|
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:
|
|
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 {
|
|
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:
|
|
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
|
|
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
|
-
|
|
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:
|
|
52
|
+
/** 模型API密钥密文,更新时不传表示保留现有密钥 */
|
|
53
|
+
api_key: SecretCrypto | undefined;
|
|
53
54
|
/** 是否已保存模型密钥 */
|
|
54
55
|
api_key_configured: boolean;
|
|
55
56
|
/** 排序值 */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
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:
|
|
154
|
+
old_pwd: SecretCrypto | undefined;
|
|
155
155
|
/** 新密码 */
|
|
156
|
-
new_pwd:
|
|
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
|
|
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 {
|
|
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:
|
|
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:
|
|
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:
|
|
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 {
|
|
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:
|
|
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:
|
|
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
|
-
|
|
33
|
-
|
|
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
|
|
95
|
-
const
|
|
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
|
|
@@ -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
|
|
|
@@ -5,27 +5,9 @@
|
|
|
5
5
|
// source: base/v1/login.proto
|
|
6
6
|
|
|
7
7
|
/* eslint-disable */
|
|
8
|
-
import type {
|
|
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
|
-
|
|
|
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 {
|
|
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
|
-
|
|
|
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
|
|
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
|
-
|
|
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:
|
|
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 {
|
|
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
|
-
|
|
|
205
|
+
| SecretCrypto
|
|
206
206
|
| undefined;
|
|
207
207
|
/** 新密码 */
|
|
208
|
-
new_pwd:
|
|
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
|
|
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 {
|
|
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:
|
|
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:
|
|
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:
|
|
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 {
|
|
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
|
-
|
|
|
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:
|
|
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
|
-
|
|
173
|
-
|
|
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(
|
|
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:
|
|
446
|
-
provider:
|
|
447
|
-
name:
|
|
448
|
-
base_url:
|
|
449
|
-
api_key:
|
|
450
|
-
api_key_configured:
|
|
451
|
-
models:
|
|
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:
|
|
454
|
-
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
|
-
|
|
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 {
|
|
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,
|
|
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:
|
|
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
|
-
|
|
125
|
-
|
|
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:
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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 {
|
|
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,
|
|
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,
|
|
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 {
|
|
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:
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
19
|
+
"@liujitcn/kratos-admin-core": "0.0.68"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"@element-plus/icons-vue": "^2.3.1",
|