Skip to content

Commit

Permalink
🚀 chore(SecurityManager, UsersService, LoggerFilter): Remove un…
Browse files Browse the repository at this point in the history
…necessary serialization calls and simplify logic

This commit eliminates redundant serialization calls within the `SecurityManager` and optimizes caching operations in `LoggerFilter`, enhancing code readability and efficiency.
  • Loading branch information
vnobo committed Sep 20, 2024
1 parent a0396dc commit 6dcb50f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,20 @@
* and utilizes a LoggersService to persist operation logs with enriched content.
* The filter matches requests based on a predefined matcher (defaultLoggerMatcher) and can be bypassed
* if the match is not successful.
*
* <p>
* Key Features:
* - Caches request and response bodies to ensure they can be logged even after consumption.
* - Matches requests to determine if logging should occur based on a ServerWebExchangeMatcher.
* - Processes and logs the HTTP method, status, path, headers, cookies, query parameters, and bodies.
* - Handles DataBuffer retention and release to prevent memory leaks.
* - Utilizes a separate service (LoggersService) to handle the logging operation asynchronously.
* - Supports tracing-level logging for debugging filter operations.
*
* <p>
* Dependencies:
* - ServerWebExchangeMatcher for matching requests.
* - LoggersService for persisting log entries.
* - SLF4J Logger (log) for internal logging.
*
* <p>
* Usage:
* Implemented as a Spring component (@Component), it's automatically registered in the WebFilter chain.
* Configuration may be required to customize the matching behavior or logging service interaction.
Expand Down Expand Up @@ -159,10 +159,10 @@ public static ServerHttpResponse responseDecorate(ServerWebExchange exchange) {
* This method is useful for scenarios where the request body needs to be read or processed
* multiple times without losing its original state.
*
* @param exchange The ServerWebExchange containing the current request and response.
* @param exchange The ServerWebExchange containing the current request and response.
* @param dataBuffer The DataBuffer representing the body of the request.
* @return A decorated ServerHttpRequest with the body cached for subsequent accesses.
* Returns null if the data buffer capacity is zero.
* Returns null if the data buffer capacity is zero.
*/
private static ServerHttpRequest requestDecorate(ServerWebExchange exchange, DataBuffer dataBuffer) {
if (dataBuffer.capacity() > 0) {
Expand Down Expand Up @@ -197,7 +197,7 @@ private static ServerHttpRequest requestDecorate(ServerWebExchange exchange, Dat
*
* @param dataBuffer The source DataBuffer to be converted or wrapped.
* @return A new DataBuffer instance, either wrapped or converted from the input,
* maintaining the content of the original buffer.
* maintaining the content of the original buffer.
* @throws IllegalArgumentException If the input DataBuffer is neither a NettyDataBuffer
* nor a DefaultDataBuffer, indicating an unsupported type.
*/
Expand Down Expand Up @@ -234,14 +234,14 @@ private JsonNode readRequestBody(ServerWebExchange exchange) {
* If no match is found, it simply continues the filter chain without caching or logging.
*
* @param exchange The current server web exchange to be filtered.
* @param chain The filter chain to be invoked for further processing.
* @param chain The filter chain to be invoked for further processing.
* @return A Mono that completes void when the filtering and optional caching/logging are finished.
*/
@Override
public @NonNull Mono<Void> filter(@NonNull ServerWebExchange exchange, @NonNull WebFilterChain chain) {
var filterMono = defaultLoggerMatcher.matches(exchange);
filterMono = filterMono.filter(ServerWebExchangeMatcher.MatchResult::isMatch);
filterMono = filterMono.switchIfEmpty(continueFilterChain(exchange, chain).then(Mono.empty()));
filterMono = filterMono.switchIfEmpty(Mono.defer(() -> continueFilterChain(exchange, chain).then(Mono.empty())));
return filterMono.flatMap((m) -> cacheFilterChain(exchange, chain).then(Mono.defer(ContextUtils::securityDetails))
.doOnNext(userDetails -> logRequest(exchange, userDetails)).then());
}
Expand All @@ -256,8 +256,8 @@ private JsonNode readRequestBody(ServerWebExchange exchange) {
* the client request and provides a way to manipulate the response.
* @param chain The WebFilterChain representing the remaining filters to be applied.
* @return A Mono<Void> indicating the completion or error of the deferred filter operation.
* The completion signifies that the request has been processed by the next filter
* in line, or an error indicates that the processing failed at some point in the chain.
* The completion signifies that the request has been processed by the next filter
* in line, or an error indicates that the processing failed at some point in the chain.
*/
private Mono<Void> continueFilterChain(ServerWebExchange exchange, WebFilterChain chain) {
log.debug("{}Logger filter chain [continueFilterChain] next.", exchange.getLogPrefix());
Expand All @@ -281,7 +281,7 @@ private Mono<Void> cacheFilterChain(ServerWebExchange exchange, WebFilterChain c
/**
* Processes the request body from the given ServerWebExchange and ServerHttpRequest.
*
* @param exchange The current server web exchange which holds information about the HTTP request and response.
* @param exchange The current server web exchange which holds information about the HTTP request and response.
* @param serverHttpRequest The actual HTTP request containing the body to be processed.
* @return A Mono that emits the processed request body as a String.
*/
Expand Down Expand Up @@ -361,10 +361,10 @@ private void releaseDataBuffer(Object dataBufferObject) {
* is asynchronous and the result is logged at the debug level with a prefixed log message indicating
* the operation performed.
*
* @param exchange The current server web exchange which holds both the incoming request and the
* outgoing response.
* @param userDetails Optional security details of the authenticated user, containing a username
* and a tenant code. If not provided, defaults are used.
* @param exchange The current server web exchange which holds both the incoming request and the
* outgoing response.
* @param userDetails Optional security details of the authenticated user, containing a username
* and a tenant code. If not provided, defaults are used.
*/
private void logRequest(ServerWebExchange exchange, SecurityDetails userDetails) {
ServerHttpRequest request = exchange.getRequest();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.plate.boot.security;

import com.plate.boot.commons.base.AbstractDatabase;
import com.plate.boot.commons.utils.ContextUtils;
import com.plate.boot.security.core.group.authority.GroupAuthority;
import com.plate.boot.security.core.group.member.GroupMemberResponse;
import com.plate.boot.security.core.tenant.member.TenantMemberResponse;
Expand Down Expand Up @@ -211,7 +210,7 @@ private Mono<SecurityDetails> buildUserDetails(User user, Set<GrantedAuthority>
private Mono<List<GroupMemberResponse>> loadGroups(String userCode) {
return this.queryWithCache("USER_GROUPS-" + userCode,
QUERY_GROUP_MEMBERS_SQL, Map.of("userCode", userCode), GroupMemberResponse.class)
.flatMap(ContextUtils::serializeUserAuditor).collectSortedList();
.collectSortedList();
}

/**
Expand All @@ -225,7 +224,7 @@ private Mono<List<GroupMemberResponse>> loadGroups(String userCode) {
private Mono<List<TenantMemberResponse>> loadTenants(String userCode) {
return this.queryWithCache("USER_TENANTS-" + userCode,
QUERY_TENANT_MEMBERS_SQL, Map.of("userCode", userCode), TenantMemberResponse.class)
.flatMap(ContextUtils::serializeUserAuditor).collectSortedList();
.collectSortedList();
}

/**
Expand All @@ -239,8 +238,7 @@ private Mono<List<TenantMemberResponse>> loadTenants(String userCode) {
*/
private Mono<List<GrantedAuthority>> authorities(String userCode) {
return this.getAuthorities(userCode)
.concatWith(this.getGroupAuthorities(userCode))
.flatMap(ContextUtils::serializeUserAuditor).distinct().collectList();
.concatWith(this.getGroupAuthorities(userCode)).distinct().collectList();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ public Mono<User> add(UserRequest request) {
*/
public Mono<User> modify(UserRequest request) {
return this.usersRepository.findByUsername(request.getUsername())
.switchIfEmpty(Mono.defer(() -> Mono.error(RestServerException.withMsg(
"User not found!", "User by username [" + request.getUsername() + "] not found!"))))
.switchIfEmpty(Mono.error(RestServerException.withMsg(
"User not found!", "User by username [" + request.getUsername() + "] not found!")))
.flatMap(user -> {
request.setId(user.getId());
request.setCode(user.getCode());
Expand Down

0 comments on commit 6dcb50f

Please sign in to comment.