Skip to content

Commit 47351bf

Browse files
committed
new: reworked api event publisher
1 parent 62f62dc commit 47351bf

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.lowcoder.api.framework.filter;
2+
3+
import com.google.common.hash.Hashing;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.lowcoder.api.home.SessionUserService;
7+
import org.lowcoder.domain.organization.model.OrgMember;
8+
import org.lowcoder.infra.event.APICallEvent;
9+
import org.lowcoder.plugin.api.event.LowcoderEvent;
10+
import org.lowcoder.sdk.constants.Authentication;
11+
import org.springframework.context.ApplicationEventPublisher;
12+
import org.springframework.http.server.reactive.ServerHttpRequest;
13+
import org.springframework.stereotype.Component;
14+
import org.springframework.util.MultiValueMap;
15+
import org.springframework.web.server.ServerWebExchange;
16+
import org.springframework.web.server.WebFilter;
17+
import org.springframework.web.server.WebFilterChain;
18+
import reactor.core.publisher.Mono;
19+
import reactor.core.scheduler.Schedulers;
20+
21+
import java.nio.charset.StandardCharsets;
22+
23+
import static org.lowcoder.sdk.constants.GlobalContext.CURRENT_ORG_MEMBER;
24+
import static org.lowcoder.sdk.constants.GlobalContext.VISITOR_TOKEN;
25+
import static org.springframework.http.HttpHeaders.writableHttpHeaders;
26+
27+
@Slf4j
28+
@RequiredArgsConstructor
29+
@Component
30+
public class ApiEventFilter implements WebFilter {
31+
private final ApplicationEventPublisher applicationEventPublisher;
32+
private final SessionUserService sessionUserService;
33+
34+
@Override
35+
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
36+
return chain.filter(exchange).then(
37+
Mono.deferContextual(contextView -> {
38+
if (exchange.getResponse().getStatusCode().is2xxSuccessful()) {
39+
String token = contextView.get(VISITOR_TOKEN);
40+
((Mono<OrgMember>) contextView.get(CURRENT_ORG_MEMBER))
41+
.flatMap(orgMember -> {
42+
emitEvent(exchange.getRequest(), token, orgMember);
43+
return Mono.empty();
44+
})
45+
.subscribeOn(Schedulers.boundedElastic())
46+
.subscribe();
47+
}
48+
return Mono.empty();
49+
})
50+
);
51+
}
52+
53+
private void emitEvent(ServerHttpRequest request, String token, OrgMember orgMember) {
54+
MultiValueMap<String, String> headers = writableHttpHeaders(request.getHeaders());
55+
headers.remove("Cookie");
56+
String ipAddress = headers.remove("X-Real-IP").stream().findFirst().get();
57+
58+
APICallEvent event = APICallEvent.builder()
59+
.userId(orgMember.getUserId())
60+
.orgId(orgMember.getOrgId())
61+
.type(LowcoderEvent.EventType.API_CALL_EVENT)
62+
.isAnonymous(Authentication.isAnonymousUser(orgMember.getUserId()))
63+
.sessionHash(Hashing.sha512().hashString(token, StandardCharsets.UTF_8).toString())
64+
.httpMethod(request.getMethod().name())
65+
.requestUri(request.getURI().getPath())
66+
.headers(headers)
67+
.queryParams(request.getQueryParams())
68+
.ipAddress(ipAddress)
69+
.build();
70+
event.populateDetails();
71+
72+
log.debug("API call event emitted for '{}' from org '{}' on URI: {}", orgMember.getUserId(), orgMember.getUserId(), request.getURI().getPath());
73+
applicationEventPublisher.publishEvent(event);
74+
}
75+
76+
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/util/ApiCallEventPublisher.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
import static org.springframework.http.HttpHeaders.writableHttpHeaders;
2626

2727
@Slf4j
28-
@Aspect
28+
//@Aspect
2929
@RequiredArgsConstructor
30-
@Component
30+
//@Component
3131
public class ApiCallEventPublisher {
3232

3333
private final ApplicationEventPublisher applicationEventPublisher;

0 commit comments

Comments
 (0)