Skip to content

Commit f1c28a0

Browse files
Msquittto陈潇文
andauthored
新增北向接口 (#324)
* [app-platform] 新增apikey-service * [app-platform] 新增apikey-auth-default插件 * [app-platform] 新增apikey-auth-oms插件 * [app-platform] 修改apikey-service pom文件 * [app-platform] 修改apikey插件 pom文件 * [app-platform] 修改apikey-auth-default插件application文件 * [app-platform] 新增NorthFilter * [app-platform] 修改LoginFilter mismatch条件 * [app-platform] 更新已有北向接口请求前缀 * [app-platform] 新增用户反馈相关的北向接口 * [app-platform] 新增会话历史相关的北向接口 * [app-platform] 修改会话历史相关的北向接口groupName * [app-platform] OmsApikeyAuthService修改ssl解码问题 * [app-platform] 修复北向对话接口参数转换问题 * [app-platform] 修复北向查询应用列表参数问题 * [app-platform] 修复北向删除会话参数名 * [app-platform] 去除北向会话接口参数默认值 * [app-platform] 修复换行符问题 * [app-platform] 检视意见修改 * [app-platform] 新增北向查询应用列表测试用例 * [app-platform] 检视意见修改 * [app-platform] 修改北向接口前缀 * [app-platform] 修改http请求过滤器匹配前缀 * [app-platform] 修改common目录下插件的pom文件,提取公共依赖插件 * [app-platform] 移除apikey-auth非默认插件 * [app-platform] 检视意见修改 * [app-platform] 检视意见修改 --------- Co-authored-by: 陈潇文 <[email protected]>
1 parent abfe996 commit f1c28a0

File tree

37 files changed

+849
-249
lines changed

37 files changed

+849
-249
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
package modelengine.fit.jober.aipp.northbound;
8+
9+
import modelengine.fit.jane.common.entity.OperationContext;
10+
import modelengine.fit.jober.aipp.dto.aipplog.AippInstLogData;
11+
import modelengine.fit.jober.aipp.dto.aipplog.AippInstLogDataDto;
12+
import modelengine.fit.jober.aipp.genericable.adapter.AippLogServiceAdapter;
13+
import modelengine.fit.jober.aipp.service.AippLogService;
14+
import modelengine.fitframework.annotation.Component;
15+
16+
import java.util.List;
17+
18+
/**
19+
* {@link AippLogServiceAdapter} 的适配器类的实现类。
20+
*
21+
* @author 陈潇文
22+
* @since 2025-07-08
23+
*/
24+
@Component
25+
public class AippLogServiceAdapterImpl implements AippLogServiceAdapter {
26+
private final AippLogService aippLogService;
27+
28+
/**
29+
* 用 aipp 实例历史记录服务接口的 {@link AippLogService} 构造 {@link AippLogServiceAdapterImpl}。
30+
*
31+
* @param aippLogService 表示 aipp 实例历史记录服务接口的 {@link AippLogService}。
32+
*/
33+
public AippLogServiceAdapterImpl(AippLogService aippLogService) {
34+
this.aippLogService = aippLogService;
35+
}
36+
37+
@Override
38+
public List<AippInstLogData> queryChatRecentChatLog(String chatId, String appId, OperationContext context) {
39+
List<AippInstLogDataDto> logDataDtoList = this.aippLogService.queryChatRecentChatLog(chatId, appId, context);
40+
return logDataDtoList.stream()
41+
.map(dto -> AippInstLogData.builder()
42+
.aippId(dto.getAippId())
43+
.version(dto.getVersion())
44+
.instanceId(dto.getInstanceId())
45+
.status(dto.getStatus())
46+
.appName(dto.getAppName())
47+
.appIcon(dto.getAppIcon())
48+
.createAt(dto.getCreateAt())
49+
.question(this.convertQuestion(dto.getQuestion()))
50+
.instanceLogBodies(this.convertLogBodies(dto.getInstanceLogBodies()))
51+
.build())
52+
.toList();
53+
}
54+
55+
private AippInstLogData.AippInstLogBody convertBody(AippInstLogDataDto.AippInstanceLogBody dtoBody) {
56+
if (dtoBody == null) {
57+
return null;
58+
}
59+
return AippInstLogData.AippInstLogBody.builder()
60+
.logId(dtoBody.getLogId())
61+
.logData(dtoBody.getLogData())
62+
.logType(dtoBody.getLogType())
63+
.createAt(dtoBody.getCreateAt())
64+
.createUserAccount(dtoBody.getCreateUserAccount())
65+
.build();
66+
}
67+
68+
private AippInstLogData.AippInstLogBody convertQuestion(AippInstLogDataDto.AippInstanceLogBody question) {
69+
if (question == null) {
70+
return null;
71+
}
72+
return this.convertBody(question);
73+
}
74+
75+
private List<AippInstLogData.AippInstLogBody> convertLogBodies(
76+
List<AippInstLogDataDto.AippInstanceLogBody> logBodies) {
77+
if (logBodies == null) {
78+
return null;
79+
}
80+
return logBodies.stream().map(this::convertBody).toList();
81+
}
82+
}

app-builder/jane/plugins/aipp-plugin/src/main/java/modelengine/fit/jober/aipp/northbound/AppBuilderAppServiceAdapterImpl.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,25 @@
3232
public class AppBuilderAppServiceAdapterImpl implements AppBuilderAppServiceAdapter {
3333
private final AppBuilderAppService appBuilderAppService;
3434

35+
/**
36+
* 用应用创建服务接口{@link AppBuilderAppService} 构造 {@link AppBuilderAppServiceAdapterImpl}。
37+
*
38+
* @param appBuilderAppService 表示应用创建服务接口的 {@link AppBuilderAppService}。
39+
*/
3540
public AppBuilderAppServiceAdapterImpl(AppBuilderAppService appBuilderAppService) {
3641
this.appBuilderAppService = notNull(appBuilderAppService, "The app builder app service cannot be null.");
3742
}
3843

3944
@Override
4045
public RangedResultSet<AppMetadata> list(AppQueryParams params, OperationContext context) {
41-
AppQueryCondition appQueryCondition = BeanUtils.copyProperties(params, AppQueryCondition.class);
46+
AppQueryCondition appQueryCondition = this.convertParams(params);
4247
if (params.getType() == null) {
4348
params.setType("app");
4449
}
4550
appQueryCondition.setTenantId(context.getTenantId());
4651
appQueryCondition.setType(params.getType());
47-
Rsp<RangedResultSet<AppBuilderAppMetadataDto>> rsp = this.appBuilderAppService.list(appQueryCondition,
48-
context, params.getOffset(), params.getLimit());
52+
Rsp<RangedResultSet<AppBuilderAppMetadataDto>> rsp =
53+
this.appBuilderAppService.list(appQueryCondition, context, params.getOffset(), params.getLimit());
4954
return this.appMetadataDtoConvertToAdapter(rsp.getData());
5055
}
5156

@@ -55,4 +60,19 @@ RangedResultSet<AppMetadata> appMetadataDtoConvertToAdapter(RangedResultSet<AppB
5560
.map(appBuilderAppMetadataDto -> BeanUtils.copyProperties(appBuilderAppMetadataDto, AppMetadata.class))
5661
.collect(Collectors.toList()), dto.getRange());
5762
}
63+
64+
private AppQueryCondition convertParams(AppQueryParams params) {
65+
if (params == null) {
66+
return null;
67+
}
68+
return AppQueryCondition.builder()
69+
.ids(params.getIds())
70+
.name(params.getName())
71+
.state(params.getState())
72+
.excludeNames(params.getExcludeNames())
73+
.offset(Long.valueOf(params.getOffset()))
74+
.limit(params.getLimit())
75+
.type(params.getType())
76+
.build();
77+
}
5878
}

app-builder/jane/plugins/aipp-plugin/src/main/java/modelengine/fit/jober/aipp/northbound/AppChatServiceAdapterImpl.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@
1313
import modelengine.fit.jober.aipp.dto.chat.CreateAppChatRequest;
1414
import modelengine.fit.jober.aipp.genericable.adapter.AppChatServiceAdapter;
1515
import modelengine.fit.jober.aipp.service.AppChatService;
16-
1716
import modelengine.fitframework.annotation.Component;
18-
import modelengine.fitframework.annotation.Fit;
1917
import modelengine.fitframework.flowable.Choir;
20-
import modelengine.fitframework.serialization.ObjectSerializer;
2118

2219
import java.util.Map;
2320

@@ -30,17 +27,19 @@
3027
@Component
3128
public class AppChatServiceAdapterImpl implements AppChatServiceAdapter {
3229
private final AppChatService appChatService;
33-
private final ObjectSerializer serializer;
3430

35-
public AppChatServiceAdapterImpl(AppChatService appChatService, @Fit(alias = "json") ObjectSerializer serializer) {
31+
/**
32+
* 用历史会话服务接口 {@link AppChatService} 构造 {@link AppChatServiceAdapterImpl}。
33+
*
34+
* @param appChatService 表示历史会话服务接口的 {@link AppChatService}。
35+
*/
36+
public AppChatServiceAdapterImpl(AppChatService appChatService) {
3637
this.appChatService = notNull(appChatService, "The app chat service must not be null.");
37-
this.serializer = notNull(serializer, "The serializer must not be null.");
3838
}
3939

4040
@Override
4141
public Choir<Object> chat(String appId, ChatRequest params, OperationContext operationContext, boolean isDebug) {
42-
CreateAppChatRequest createAppChatRequest =
43-
this.serializer.deserialize(this.serializer.serialize(params), CreateAppChatRequest.class);
42+
CreateAppChatRequest createAppChatRequest = this.convertToCreateAppChatRequest(params);
4443
createAppChatRequest.setAppId(appId);
4544
return this.appChatService.chat(createAppChatRequest, operationContext, isDebug);
4645
}
@@ -50,4 +49,27 @@ public Choir<Object> restartChat(String currentInstanceId, Map<String, Object> a
5049
OperationContext operationContext) {
5150
return this.appChatService.restartChat(currentInstanceId, additionalContext, operationContext);
5251
}
52+
53+
private CreateAppChatRequest convertToCreateAppChatRequest(ChatRequest params) {
54+
if (params == null) {
55+
return null;
56+
}
57+
ChatRequest.Context ctx = params.getContext();
58+
CreateAppChatRequest.Context newCtx = null;
59+
if (ctx != null) {
60+
newCtx = CreateAppChatRequest.Context.builder()
61+
.useMemory(ctx.getUseMemory())
62+
.userContext(ctx.getUserContext())
63+
.atAppId(ctx.getAtAppId())
64+
.atChatId(ctx.getAtChatId())
65+
.dimension(ctx.getDimension())
66+
.dimensionId(ctx.getDimensionId())
67+
.build();
68+
}
69+
return CreateAppChatRequest.builder()
70+
.chatId(params.getChatId())
71+
.question(params.getQuestion())
72+
.context(newCtx)
73+
.build();
74+
}
5375
}

app-builder/jane/plugins/aipp-plugin/src/test/java/modelengine/fit/jober/aipp/northbound/AppBuilderAppServiceAdapterImplTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,28 @@
77
package modelengine.fit.jober.aipp.northbound;
88

99
import static org.assertj.core.api.Assertions.assertThat;
10+
import static org.mockito.ArgumentMatchers.any;
11+
import static org.mockito.ArgumentMatchers.anyInt;
12+
import static org.mockito.ArgumentMatchers.anyLong;
1013
import static org.mockito.Mockito.mock;
1114
import static org.mockito.Mockito.when;
1215

16+
import modelengine.fit.jane.common.entity.OperationContext;
1317
import modelengine.fit.jane.common.response.Rsp;
18+
import modelengine.fit.jober.aipp.condition.AppQueryCondition;
1419
import modelengine.fit.jober.aipp.dto.AppBuilderAppMetadataDto;
1520
import modelengine.fit.jober.aipp.dto.chat.AppMetadata;
21+
import modelengine.fit.jober.aipp.dto.chat.AppQueryParams;
1622
import modelengine.fit.jober.aipp.service.AppBuilderAppService;
1723
import modelengine.fit.jober.common.RangeResult;
1824
import modelengine.fit.jober.common.RangedResultSet;
1925

2026
import org.junit.jupiter.api.DisplayName;
2127
import org.junit.jupiter.api.Test;
2228

29+
import java.util.ArrayList;
2330
import java.util.Arrays;
31+
import java.util.List;
2432

2533
/**
2634
* {@link AippChatServiceAdapterImpl} 的单元测试。
@@ -60,4 +68,31 @@ void testDtoConvertToAdapter() {
6068
.containsExactly("testName1", "testName2");
6169
assertThat(result.getResults()).extracting(AppMetadata::getType).containsExactly("testType1", "testType2");
6270
}
71+
72+
@Test
73+
@DisplayName("测试查询应用列表")
74+
void shouldOkWhenTestQueryAppList() {
75+
AppQueryParams params = AppQueryParams.builder()
76+
.ids(Arrays.asList("id1", "id2"))
77+
.excludeNames(Arrays.asList("name1", "name2"))
78+
.name("name")
79+
.state("active")
80+
.offset(100)
81+
.limit(20)
82+
.type("app")
83+
.build();
84+
OperationContext operationContext = new OperationContext();
85+
operationContext.setTenantId("tenantId");
86+
List<AppBuilderAppMetadataDto> metaDtoList = new ArrayList<>();
87+
metaDtoList.add(AppBuilderAppMetadataDto.builder().name("name1").build());
88+
Rsp<RangedResultSet<AppBuilderAppMetadataDto>> rsp =
89+
Rsp.ok(RangedResultSet.create(metaDtoList, params.getOffset(), params.getLimit(), metaDtoList.size()));
90+
when(this.appBuilderAppService.list(any(AppQueryCondition.class),
91+
any(OperationContext.class),
92+
anyLong(),
93+
anyInt())).thenReturn(rsp);
94+
RangedResultSet<AppMetadata> resultSet = this.appBuilderAppServiceAdapterImpl.list(params, operationContext);
95+
assertThat(resultSet.getResults().size()).isEqualTo(1);
96+
assertThat(resultSet.getResults().get(0).getName()).isEqualTo("name1");
97+
}
6398
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
package modelengine.fit.jober.aipp.northbound;
8+
9+
import static org.mockito.ArgumentMatchers.any;
10+
import static org.mockito.ArgumentMatchers.anyBoolean;
11+
import static org.mockito.Mockito.mock;
12+
import static org.mockito.Mockito.when;
13+
14+
import modelengine.fit.jane.common.entity.OperationContext;
15+
import modelengine.fit.jober.aipp.dto.chat.ChatRequest;
16+
import modelengine.fit.jober.aipp.dto.chat.CreateAppChatRequest;
17+
import modelengine.fit.jober.aipp.service.AppChatService;
18+
import modelengine.fitframework.flowable.Choir;
19+
20+
import org.junit.jupiter.api.Assertions;
21+
import org.junit.jupiter.api.DisplayName;
22+
import org.junit.jupiter.api.Test;
23+
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
27+
/**
28+
* {@link AppChatServiceAdapterImpl} 的单元测试。
29+
*
30+
* @author 陈潇文
31+
* @since 2025-07-15
32+
*/
33+
public class AppChatServiceAdapterImplTest {
34+
private final AppChatService appChatService = mock(AppChatService.class);
35+
private final AppChatServiceAdapterImpl appChatServiceAdapter =
36+
new AppChatServiceAdapterImpl(appChatService);
37+
38+
@Test
39+
@DisplayName("测试对话")
40+
void shouldOkWhenTestChat() {
41+
String appId = "appId";
42+
ChatRequest params = ChatRequest.builder().chatId("chatId").question("q").build();
43+
Map<String, Object> userContext = new HashMap<>();
44+
userContext.put("a", "aaa");
45+
ChatRequest.Context context = ChatRequest.Context.builder()
46+
.atChatId("atChatId")
47+
.atAppId("atAppId")
48+
.useMemory(true)
49+
.dimension("dimension")
50+
.dimensionId("dimensionId")
51+
.userContext(userContext)
52+
.build();
53+
params.setContext(context);
54+
OperationContext operationContext = new OperationContext();
55+
boolean isDebug = true;
56+
when(this.appChatService.chat(any(CreateAppChatRequest.class),
57+
any(OperationContext.class),
58+
anyBoolean())).thenReturn(mock(Choir.class));
59+
// when
60+
Choir<Object> objectChoir = Assertions.assertDoesNotThrow(() -> this.appChatServiceAdapter.chat(appId,
61+
params,
62+
operationContext,
63+
isDebug));
64+
// then
65+
Assertions.assertNotNull(objectChoir);
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.jober.aipp.dto.aipplog;
8+
9+
import lombok.AllArgsConstructor;
10+
import lombok.Builder;
11+
import lombok.Data;
12+
import lombok.NoArgsConstructor;
13+
14+
import java.time.LocalDateTime;
15+
import java.util.List;
16+
17+
/**
18+
* aipp 实例历史记录数据。
19+
*
20+
* @author 陈潇文
21+
* @since 2025-07-16
22+
*/
23+
@AllArgsConstructor
24+
@Data
25+
@Builder
26+
@NoArgsConstructor
27+
public class AippInstLogData {
28+
private String aippId;
29+
private String version;
30+
private String instanceId;
31+
private String status;
32+
private String appName;
33+
private String appIcon;
34+
private LocalDateTime createAt;
35+
private AippInstLogBody question;
36+
private List<AippInstLogBody> instanceLogBodies;
37+
38+
/**
39+
* 转换实例日志为实例日志体。
40+
*/
41+
@AllArgsConstructor
42+
@Data
43+
@Builder
44+
@NoArgsConstructor
45+
public static class AippInstLogBody {
46+
private long logId;
47+
private String logData;
48+
private String logType;
49+
private LocalDateTime createAt;
50+
private String createUserAccount;
51+
}
52+
}

app-builder/jane/services/aipp-genericable/src/main/java/modelengine/fit/jober/aipp/dto/chat/AppQueryParams.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
@NoArgsConstructor
2727
@AllArgsConstructor
2828
public class AppQueryParams {
29-
@RequestQuery(name = "appIds", required = false)
29+
@RequestQuery(name = "ids", required = false)
3030
@Property(description = "查询的id列表")
31-
private List<String> appIds;
31+
private List<String> ids;
3232

3333
@RequestQuery(name = "name", required = false)
3434
@Property(description = "查询的名字")

0 commit comments

Comments
 (0)