fix: return model keys in admin details and allow clearing

This commit is contained in:
ageerle
2026-09-22 23:05:59 +08:00
parent 8e3b286190
commit 197dc40510
8 changed files with 49 additions and 14 deletions

View File

@@ -0,0 +1,23 @@
package org.ruoyi.common.chat.domain.vo.chat;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.beans.BeanUtils;
/** 模型管理编辑详情,允许有查询权限的管理员回显已保存的密钥。 */
public class ChatModelDetailVo extends ChatModelVo {
@Override
@JsonProperty(access = JsonProperty.Access.READ_WRITE)
public String getApiKey() {
return super.getApiKey();
}
public static ChatModelDetailVo from(ChatModelVo model) {
if (model == null) {
return null;
}
ChatModelDetailVo detail = new ChatModelDetailVo();
BeanUtils.copyProperties(model, detail);
return detail;
}
}

View File

@@ -77,8 +77,7 @@ public class ChatModelVo implements Serializable {
private String apiHost;
/**
* 密钥仅用于服务端模型调用和写入配置。任何读取接口、日志字符串或 Excel 导出
* 都不得把它带出服务端边界。
* 列表、日志及导出不包含密钥;管理员编辑详情由 ChatModelDetailVo 回显原值。
*/
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@ToString.Exclude

View File

@@ -9,6 +9,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo;
import org.ruoyi.common.chat.domain.bo.chat.ModelBatchKeyBo;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelDetailVo;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
@@ -61,6 +62,20 @@ class ModelApiKeyValidationTest {
assertFalse(view.toString().contains("test-secret"));
}
@Test
void adminDetailReturnsExactKeyWithoutChangingListOrLogSerialization() throws Exception {
var mapper = new ObjectMapper();
var model = new ChatModelVo();
model.setId(12L);
model.setApiKey(" 任意/key: value ");
var detail = ChatModelDetailVo.from(model);
assertEquals(model.getApiKey(), mapper.readTree(mapper.writeValueAsString(detail)).get("apiKey").asText());
assertEquals(model.getId(), detail.getId());
assertFalse(mapper.writeValueAsString(model).contains("apiKey"));
assertFalse(detail.toString().contains(model.getApiKey()));
assertNull(ChatModelDetailVo.from(null));
}
@Test
void customEndpointsNeedNoDeploymentVariablesAndSupportLocalServices() {
assertEquals("http://localhost:11434/v1", CustomApiCredentialPolicy.normalizeBaseUrl(