From b33d87143e619a93dbce41bccd86d00cc165214f Mon Sep 17 00:00:00 2001 From: AlexBob Date: Tue, 24 Dec 2024 14:46:29 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=F0=9F=94=A7=20fix(`ng-ui/package.json`):?= =?UTF-8?q?=20Update=20ng-zorro-antd=20version=20from=20beta=20to=20stable?= =?UTF-8?q?=20release.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ng-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ng-ui/package.json b/ng-ui/package.json index ce927cd7..8c01d5c5 100644 --- a/ng-ui/package.json +++ b/ng-ui/package.json @@ -26,7 +26,7 @@ "bootstrap-icons": "^1.11.3", "dayjs": "^1.11.13", "express": "^4.18.2", - "ng-zorro-antd": "^19.0.0-beta", + "ng-zorro-antd": "^19.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0" }, From 0dd86a1033b7f7a82ef3fc22102129203b920002 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:05:59 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E2=9C=A8=20feat(`AbstractDatabase.java`,?= =?UTF-8?q?=20`BaseEntity.java`,=20`AbstractEntity.java`):=20Replace=20"qu?= =?UTF-8?q?ery"=20with=20"from"=20for=20R2DBC=20operations=20and=20entity?= =?UTF-8?q?=20methods.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit updates terminology from "query" to "from" in method names, parameters, and comments to better reflect the nature of R2DBC operations. --- .../boot/commons/base/AbstractDatabase.java | 44 +++++++++---------- .../boot/commons/base/AbstractEntity.java | 11 ++--- .../plate/boot/commons/base/BaseEntity.java | 22 +++++----- 3 files changed, 36 insertions(+), 41 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractDatabase.java b/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractDatabase.java index 6c8a0338..b14d565f 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractDatabase.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractDatabase.java @@ -38,7 +38,7 @@ public abstract class AbstractDatabase extends AbstractService { /** * The R2dbcEntityTemplate instance used for executing reactive database operations. - * This template facilitates interaction with the database, including query execution, + * This template facilitates interaction with the database, including from execution, * entity conversion, and transaction management specifically tailored for R2DBC (Reactive Relational Database Connectivity). */ protected R2dbcEntityTemplate entityTemplate; @@ -53,21 +53,21 @@ public abstract class AbstractDatabase extends AbstractService { /** * The R2DBC Converter instance used for converting between R2DBC Data types and domain-specific objects. - * This converter plays a crucial role in mapping query results to entity classes and vice versa, + * This converter plays a crucial role in mapping from results to entity classes and vice versa, * facilitating seamless interaction with the R2DBC database through the R2dbcEntityTemplate. */ protected R2dbcConverter r2dbcConverter; /** - * Executes a database query with caching functionality. - * It takes a cache key, a query object, and an entity class type to perform the operation. + * Executes a database from with caching functionality. + * It takes a cache key, a from object, and an entity class type to perform the operation. * The results are cached for future queries with the same key. * - * @param The type of entities expected as query results. + * @param The type of entities expected as from results. * @param key The unique identifier used as a cache key. Determines the cache entry for storing/retrieving results. - * @param query The query object defining the SQL query and its potential parameters. + * @param query The from object defining the SQL from and its potential parameters. * @param entityClass The class of the entity that each row in the result set will be mapped to. - * @return A {@link Flux} emitting the query results, potentially from cache if previously stored. + * @return A {@link Flux} emitting the from results, potentially from cache if previously stored. */ protected Flux queryWithCache(Object key, Query query, Class entityClass) { Flux source = this.entityTemplate.select(query, entityClass); @@ -76,17 +76,17 @@ protected Flux queryWithCache(Object key, Query query, Class entityCla } /** - * Executes a SQL query with caching capability. It binds provided parameters to the SQL query, + * Executes a SQL from with caching capability. It binds provided parameters to the SQL from, * maps the result set to entities of the specified class, applies user auditor serialization, - * and utilizes a cache to store query results for subsequent identical queries. + * and utilizes a cache to store from results for subsequent identical queries. * - * @param The type of entities the SQL query results will be mapped to. + * @param The type of entities the SQL from results will be mapped to. * @param key The cache key used to identify the cached data. This should uniquely represent - * the query and its parameters. - * @param sql The SQL query string to be executed. - * @param bindParams A map containing named parameter bindings for the SQL query. + * the from and its parameters. + * @param sql The SQL from string to be executed. + * @param bindParams A map containing named parameter bindings for the SQL from. * @param entityClass The class of the entity that each row in the result set will be converted into. - * @return A {@link Flux} emitting the entities resulting from the query, potentially from the cache. + * @return A {@link Flux} emitting the entities resulting from the from, potentially from the cache. */ protected Flux queryWithCache(Object key, String sql, Map bindParams, Class entityClass) { @@ -100,7 +100,7 @@ protected Flux queryWithCache(Object key, String sql, } /** - * Executes a Flux-based database query with caching functionality. + * Executes a Flux-based database from with caching functionality. * It enhances the source Flux by caching its emissions under a specified key. * If the cache contains data for the key, it returns the cached data immediately. * Otherwise, it executes the source Flux, caches the results, and then emits them. @@ -122,14 +122,14 @@ protected Flux queryWithCache(Object key, Flux sourceFlux) { } /** - * Counts entities with caching support based on the provided key, query, and entity class. + * Counts entities with caching support based on the provided key, from, and entity class. * This method enhances entity counting by storing the count result in a cache, * allowing subsequent calls with the same key to retrieve the count directly from the cache - * rather than executing the query again. + * rather than executing the from again. * * @param The type of entities for which the count is to be performed. * @param key A unique identifier used as a cache key. Determines the cached count's retrieval. - * @param query The query object defining the criteria for counting entities. + * @param query The from object defining the criteria for counting entities. * @param entityClass The class of the entities being counted. * @return A {@link Mono} emitting the count of entities as a {@link Long}, potentially from cache. */ @@ -139,12 +139,12 @@ protected Mono countWithCache(Object key, Query query, Class entity } /** - * Executes a SQL count query with caching capabilities. It prepares the SQL query with provided bind parameters, + * Executes a SQL count from with caching capabilities. It prepares the SQL from with provided bind parameters, * creates a Mono source to fetch the count, and then delegates to another method to handle caching logic. * - * @param key The unique cache key associated with the count query. Used for caching and retrieving results. - * @param sql The SQL count query string to be executed. - * @param bindParams A map containing named parameter placeholders and their respective values for the SQL query. + * @param key The unique cache key associated with the count from. Used for caching and retrieving results. + * @param sql The SQL count from string to be executed. + * @param bindParams A map containing named parameter placeholders and their respective values for the SQL from. * @return A Mono emitting the count result, potentially fetched from cache or computed from the database. */ protected Mono countWithCache(Object key, String sql, Map bindParams) { diff --git a/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractEntity.java b/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractEntity.java index 35616d93..58f695e9 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractEntity.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/base/AbstractEntity.java @@ -12,7 +12,7 @@ /** * This class, AbstractEntity, is a base class for all data entities in the system. * It provides common fields and methods for all data entities, such as id, code, tenantCode, - * extend, creator, updater, updatedTime, createdTime, query, search, and securityCode. + * extend, creator, updater, updatedTime, createdTime, from, search, and securityCode. *

* The id field is the unique identifier of the data entity. The code field is the data entity code, * and the tenantCode field is the data tenant code. @@ -20,7 +20,7 @@ * The creator field is the data entity create operator, and the updater field is the data entity update operator. * The updatedTime field is the data entity update time,timestamp column, * and the createdTime field is the data entity create time, timestamp column. - * The query field is a Map object that supports query for json column, + * The from field is a Map object that supports from for json column, * and the search field is a String object that supports full text search for tsvector column. * The securityCode field is a String object that supports security code for sensitive data. *

@@ -81,12 +81,7 @@ public abstract class AbstractEntity implements BaseEntity { protected LocalDateTime createdTime; /** - * Data full text search entity sort - */ - protected Double rank; - - /** - * Support query for json column + * Support from for json column */ @Transient protected Map query; diff --git a/boot/platform/src/main/java/com/plate/boot/commons/base/BaseEntity.java b/boot/platform/src/main/java/com/plate/boot/commons/base/BaseEntity.java index 1734103a..eefb923c 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/base/BaseEntity.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/base/BaseEntity.java @@ -43,25 +43,25 @@ default String getSearch() { /** * postgresql types @code tsvector supports full text search * - * @param search query tsvector item by string + * @param search from tsvector item by string */ default void setSearch(String search) { } /** - * Retrieves the default query conditions. - * Returns an immutable empty map, indicating that there are no specific query conditions. + * Retrieves the default from conditions. + * Returns an immutable empty map, indicating that there are no specific from conditions. * - * @return An immutable map containing the query conditions + * @return An immutable map containing the from conditions */ default Map getQuery() { return Map.of(); } /** - * Sets the query parameters for the entity. + * Sets the from parameters for the entity. * - * @param query A map containing the query parameters where the key is a string + * @param query A map containing the from parameters where the key is a string * representing the parameter name and the value is the parameter value. */ default void setQuery(Map query) { @@ -100,15 +100,15 @@ default Criteria criteria(Collection skipKeys) { /** * Constructs a QueryFragment based on the current entity's properties and conditions, - * allowing for customization of the SQL query by specifying properties to exclude. + * allowing for customization of the SQL from by specifying properties to exclude. * * @param skipKeys A collection of String property names indicating which properties - * should not be included in the generated SQL query. This can be useful + * should not be included in the generated SQL from. This can be useful * for skipping sensitive or unnecessary fields. * @return A QueryFragment object containing the SQL fragment and parameters necessary - * to form a part of an SQL query. The SQL fragment represents a conditional - * part of the query (e.g., WHERE clause), and the parameters are mapped to - * prevent SQL injection, ensuring secure query execution. + * to form a part of an SQL from. The SQL fragment represents a conditional + * part of the from (e.g., WHERE clause), and the parameters are mapped to + * prevent SQL injection, ensuring secure from execution. */ default QueryFragment querySql(Collection skipKeys) { return QueryHelper.query(this, skipKeys); From 6484ce1d46f26918f99351a55b5d8cb0ddfdcd9e Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:07:01 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=F0=9F=94=A7=20refactor(`BootApplication.?= =?UTF-8?q?java`):=20Comment=20out=20unused=20`@Component`=20annotation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/src/main/java/com/plate/boot/BootApplication.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/BootApplication.java b/boot/platform/src/main/java/com/plate/boot/BootApplication.java index ff174b2e..1a61cdcd 100644 --- a/boot/platform/src/main/java/com/plate/boot/BootApplication.java +++ b/boot/platform/src/main/java/com/plate/boot/BootApplication.java @@ -5,7 +5,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.r2dbc.core.DatabaseClient; -import org.springframework.stereotype.Component; /** * @author Alex Bob @@ -16,7 +15,7 @@ public static void main(String[] args) { SpringApplication.run(BootApplication.class, args); } - @Component + //@Component static class AppRunner implements ApplicationRunner { private final DatabaseClient databaseClient; From 4181eb74c86e4b4577579b46590d5a2fc5c61962 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:07:27 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E2=9C=A8=20feat(`GroupMembersService`,?= =?UTF-8?q?=20`GroupMemberReq`):=20Implement=20dynamic=20SQL=20queries=20f?= =?UTF-8?q?or=20group=20members=20search=20and=20pagination.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/group/member/GroupMemberReq.java | 2 +- .../group/member/GroupMembersService.java | 32 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMemberReq.java b/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMemberReq.java index a4c5d30f..bfff248b 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMemberReq.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMemberReq.java @@ -36,7 +36,7 @@ public Criteria toCriteria() { public QueryFragment toParamSql() { QueryFragment queryFragment = QueryHelper.query(this, List.of("users", "username"), "a"); if (!ObjectUtils.isEmpty(this.getUsers())) { - queryFragment.where("a.user_code in :users"); + queryFragment.where("a.user_code in (:users)"); queryFragment.put("users", this.getUsers()); } diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java b/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java index 97e994ba..8a1d793f 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java @@ -7,6 +7,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.data.relational.core.query.Criteria; import org.springframework.data.relational.core.query.Query; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; @@ -18,31 +19,32 @@ @Service @RequiredArgsConstructor public class GroupMembersService extends AbstractDatabase { - private final static String QUERY_SQL = """ - select a.*, b.name as group_name, b.extend as group_extend,c.name as login_name,c.username - from se_group_members a - inner join se_groups b on a.group_code = b.code - inner join se_users c on c.code = a.user_code - """; - private final static String COUNT_SQL = """ - select count(*) from se_group_members a - inner join se_groups b on a.group_code = b.code - inner join se_users c on c.code = a.user_code - """; private final GroupMembersRepository memberRepository; public Flux search(GroupMemberReq request, Pageable pageable) { - QueryFragment queryFragment = request.toParamSql(); + QueryFragment fragment = request.toParamSql(); + QueryFragment queryFragment = QueryFragment.withColumns("a.*", "b.name as group_name", "b.extend as group_extend", + "c.name as login_name", "c.username") + .from("se_group_members a", + "inner join se_groups b on a.group_code = b.code", + "inner join se_users c on c.code = a.user_code") + .where(fragment.getWhere().toString()); + queryFragment.putAll(fragment); + Query.query(Criteria.where("name").in("a")); return super.queryWithCache(BeanUtils.cacheKey(request, pageable), queryFragment.querySql(), queryFragment, GroupMemberResp.class); } public Mono> page(GroupMemberReq request, Pageable pageable) { var searchMono = this.search(request, pageable).collectList(); - QueryFragment QueryFragment = request.toParamSql(); - String query = COUNT_SQL + QueryFragment.whereSql(); - var countMono = this.countWithCache(BeanUtils.cacheKey(request), query, QueryFragment); + QueryFragment fragment = request.toParamSql(); + QueryFragment queryFragment = QueryFragment.withColumns("*") + .from("se_group_members a", + "inner join se_groups b on a.group_code = b.code", + "inner join se_users c on c.code = a.user_code") + .where(fragment.getWhere().toString()); + var countMono = this.countWithCache(BeanUtils.cacheKey(request), queryFragment.countSql(), queryFragment); return searchMono.zipWith(countMono) .map(tuple2 -> new PageImpl<>(tuple2.getT1(), pageable, tuple2.getT2())); } From c0d07c0aa3151fb3fab33fc3350f576efd7c4f7c Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:11:30 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E2=9C=A8=20feat(`com/plate/boot/relation?= =?UTF-8?q?al/logger`):=20Rename=20`LoggerRequest`=20to=20`LoggerReq`=20an?= =?UTF-8?q?d=20update=20related=20usages.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/plate/boot/relational/LoggerFilter.java | 10 +++++----- .../{LoggerRequest.java => LoggerReq.java} | 16 ++++++++-------- .../relational/logger/LoggersController.java | 4 ++-- .../boot/relational/logger/LoggersService.java | 14 +++++++------- 4 files changed, 22 insertions(+), 22 deletions(-) rename boot/platform/src/main/java/com/plate/boot/relational/logger/{LoggerRequest.java => LoggerReq.java} (74%) diff --git a/boot/platform/src/main/java/com/plate/boot/relational/LoggerFilter.java b/boot/platform/src/main/java/com/plate/boot/relational/LoggerFilter.java index ec76926a..bafc165d 100644 --- a/boot/platform/src/main/java/com/plate/boot/relational/LoggerFilter.java +++ b/boot/platform/src/main/java/com/plate/boot/relational/LoggerFilter.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.plate.boot.commons.exception.JsonException; import com.plate.boot.commons.utils.ContextUtils; -import com.plate.boot.relational.logger.LoggerRequest; +import com.plate.boot.relational.logger.LoggerReq; import com.plate.boot.relational.logger.LoggersService; import com.plate.boot.security.SecurityDetails; import io.netty.buffer.Unpooled; @@ -48,7 +48,7 @@ * 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. + * - Processes and logs the HTTP method, status, path, headers, cookies, from 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. @@ -355,8 +355,8 @@ private void releaseDataBuffer(Object dataBufferObject) { /** * Logs the details of an HTTP request along with optional user details for security audit purposes. * It extracts information from the provided ServerWebExchange including request and response headers, - * cookies, query parameters, body content, and response status code. The logged data is structured - * into an ObjectNode which is then used to create a LoggerRequest object. This method also associates + * cookies, from parameters, body content, and response status code. The logged data is structured + * into an ObjectNode which is then used to create a LoggerReq object. This method also associates * the log entry with a tenant code extracted from the user details, if available. The logging process * is asynchronous and the result is logged at the debug level with a prefixed log message indicating * the operation performed. @@ -387,7 +387,7 @@ private void logRequest(ServerWebExchange exchange, SecurityDetails userDetails) String tenantCode = Optional.ofNullable(userDetails.getTenantCode()).orElse("0"); String path = request.getPath().value(); - LoggerRequest logger = LoggerRequest.of(tenantCode, userDetails.getUsername(), prefix, + LoggerReq logger = LoggerReq.of(tenantCode, userDetails.getUsername(), prefix, method, status, path, contentNode); this.loggerService.operate(logger).share().subscribe(res -> log.debug("{}**操作日志** Method: {},MessageBody: {}", diff --git a/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggerRequest.java b/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggerReq.java similarity index 74% rename from boot/platform/src/main/java/com/plate/boot/relational/logger/LoggerRequest.java rename to boot/platform/src/main/java/com/plate/boot/relational/logger/LoggerReq.java index 8a73593e..0713cf93 100644 --- a/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggerRequest.java +++ b/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggerReq.java @@ -9,16 +9,16 @@ /** * Represents a logging request that extends the basic {@link Logger} functionality, * encapsulating details necessary for logging specific HTTP requests. This includes - * query parameters, security codes, and provides utility methods for constructing + * from parameters, security codes, and provides utility methods for constructing * log entries compatible with the core {@link Logger} infrastructure. */ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class LoggerRequest extends Logger { +public class LoggerReq extends Logger { /** - * Constructs a new {@link LoggerRequest} instance with specified details. + * Constructs a new {@link LoggerReq} instance with specified details. * * @param tenantCode The tenant code associated with the logging request. * @param operator The operator (user or system component) initiating the request. @@ -27,11 +27,11 @@ public class LoggerRequest extends Logger { * @param status The status of the request processing (e.g., success, error). * @param url The URL path targeted by the request. * @param context Additional contextual information in JSON format. - * @return A configured {@link LoggerRequest} object ready for logging purposes. + * @return A configured {@link LoggerReq} object ready for logging purposes. */ - public static LoggerRequest of(String tenantCode, String operator, String prefix, - String method, String status, String url, JsonNode context) { - LoggerRequest request = new LoggerRequest(); + public static LoggerReq of(String tenantCode, String operator, String prefix, + String method, String status, String url, JsonNode context) { + LoggerReq request = new LoggerReq(); request.setTenantCode(tenantCode); request.setOperator(operator); request.setPrefix(prefix); @@ -43,7 +43,7 @@ public static LoggerRequest of(String tenantCode, String operator, String prefix } /** - * Converts this {@link LoggerRequest} instance into a {@link Logger} instance. + * Converts this {@link LoggerReq} instance into a {@link Logger} instance. * Utilizes bean copying to transfer properties from the request to the logger entity, * which is suitable for persisting logging activities in the system. * diff --git a/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersController.java b/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersController.java index 032d7b8f..db1675f3 100644 --- a/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersController.java +++ b/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersController.java @@ -30,7 +30,7 @@ public class LoggersController { * which processes the request further to fetch the relevant log entries. The returned data is wrapped * in a {@link PagedModel} to facilitate standardized pagination responses. * - * @param request A {@link LoggerRequest} object encapsulating the criteria for the log search, + * @param request A {@link LoggerReq} object encapsulating the criteria for the log search, * such as filters, prefixes, or additional metadata. * @param pageable A Spring {@link Pageable} instance defining the pagination parameters like page number, * size, sorting instructions, etc. @@ -39,7 +39,7 @@ public class LoggersController { * the current page and provides access to the actual log records. */ @GetMapping("page") - public Mono> page(LoggerRequest request, Pageable pageable) { + public Mono> page(LoggerReq request, Pageable pageable) { return ContextUtils.securityDetails().flatMap(userDetails -> { request.setSecurityCode(userDetails.getTenantCode()); return this.loggersService.page(request, pageable); diff --git a/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersService.java b/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersService.java index af9d47b3..d73b4d94 100644 --- a/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersService.java +++ b/boot/platform/src/main/java/com/plate/boot/relational/logger/LoggersService.java @@ -30,11 +30,11 @@ public class LoggersService extends AbstractDatabase { /** * Searches for loggers based on the provided request and pagination information. * - * @param request A LoggerRequest object containing criteria for filtering loggers. + * @param request A LoggerReq object containing criteria for filtering loggers. * @param pageable Pagination details defining how the results should be sliced. * @return A Flux of Logger objects matching the search criteria, respecting the specified pagination. */ - public Flux search(LoggerRequest request, Pageable pageable) { + public Flux search(LoggerReq request, Pageable pageable) { QueryFragment queryFragment = QueryHelper.query(request, pageable); var cacheKey = BeanUtils.cacheKey(request, pageable); return this.queryWithCache(cacheKey, queryFragment.querySql(), queryFragment, Logger.class); @@ -43,13 +43,13 @@ public Flux search(LoggerRequest request, Pageable pageable) { /** * Retrieves a paginated list of loggers based on the provided request and pagination details. * - * @param request A {@link LoggerRequest} object containing criteria to filter loggers. + * @param request A {@link LoggerReq} object containing criteria to filter loggers. * @param pageable A {@link Pageable} instance specifying pagination information like page number, size, sorting, etc. * @return A {@link Mono} emitting a {@link Page} of {@link Logger} objects that match the given criteria, * respecting the specified pagination and sorted accordingly. The {@link Page} includes both content and * metadata such as total elements, page number, and page size. */ - public Mono> page(LoggerRequest request, Pageable pageable) { + public Mono> page(LoggerReq request, Pageable pageable) { var searchMono = this.search(request, pageable).collectList(); QueryFragment queryFragment = QueryHelper.query(request, pageable); var countMono = this.countWithCache(BeanUtils.cacheKey(request), queryFragment.countSql(), queryFragment); @@ -58,14 +58,14 @@ public Mono> page(LoggerRequest request, Pageable pageable) { } /** - * Operates on a given {@link LoggerRequest} by converting it into a {@link Logger} + * Operates on a given {@link LoggerReq} by converting it into a {@link Logger} * entity and saving it using the {@link #save(Logger)} method. After the termination * of the save operation, the cache is cleared to ensure fresh data is fetched on subsequent queries. * - * @param request The {@link LoggerRequest} containing details necessary to create or update a {@link Logger} entity. + * @param request The {@link LoggerReq} containing details necessary to create or update a {@link Logger} entity. * @return A {@link Mono} emitting the saved {@link Logger} entity upon successful completion of the save operation. */ - public Mono operate(LoggerRequest request) { + public Mono operate(LoggerReq request) { return this.save(request.toLogger()).doAfterTerminate(() -> this.cache.clear()); } From c893e65e0ddc50b608632dd65d28e448b1e23538 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:11:40 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E2=9E=96=20refactor(`Oauth2UserService.j?= =?UTF-8?q?ava`):=20Change=20`UserRequest`=20to=20`UserReq`=20in=20multipl?= =?UTF-8?q?e=20places.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/security/oauth2/Oauth2UserService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/security/oauth2/Oauth2UserService.java b/boot/platform/src/main/java/com/plate/boot/security/oauth2/Oauth2UserService.java index 3ef08d54..8e1c0313 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/oauth2/Oauth2UserService.java +++ b/boot/platform/src/main/java/com/plate/boot/security/oauth2/Oauth2UserService.java @@ -5,7 +5,7 @@ import com.plate.boot.security.SecurityDetails; import com.plate.boot.security.SecurityManager; import com.plate.boot.security.core.user.User; -import com.plate.boot.security.core.user.UserRequest; +import com.plate.boot.security.core.user.UserReq; import lombok.RequiredArgsConstructor; import org.springframework.security.oauth2.client.userinfo.DefaultReactiveOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; @@ -127,7 +127,7 @@ public Mono modifyUser(User user, String registrationId, OAuth2User oAuth2 /** * Registers a new user or modifies an existing user based on the provided OAuth2 user information. - * This method first converts the OAuth2User object into a UserRequest and then + * This method first converts the OAuth2User object into a UserReq and then * delegates the registration or modification process to the SecurityManager. * * @param registrationId The unique identifier for the OAuth2 registration. @@ -140,17 +140,17 @@ public Mono registerUser(String registrationId, OAuth2User oAuth2User) { } /** - * Converts an OAuth2User object into a UserRequest, preparing it for user registration or update. + * Converts an OAuth2User object into a UserReq, preparing it for user registration or update. * This method handles specifics based on the registrationId, setting default attributes * like a random password and populating fields from the OAuth2User's attributes. * * @param registrationId The identifier for the OAuth2 registration (e.g., 'github', 'gitee'). * @param oAuth2User The OAuth2User object containing user data fetched from the OAuth provider. - * @return A UserRequest instance populated with data necessary for user registration or profile update, + * @return A UserReq instance populated with data necessary for user registration or profile update, * including a generated password and extended attributes specific to the OAuth2 registration. */ - public UserRequest convertToUserRequest(String registrationId, OAuth2User oAuth2User) { - UserRequest request = new UserRequest(); + public UserReq convertToUserRequest(String registrationId, OAuth2User oAuth2User) { + UserReq request = new UserReq(); request.setPassword(generateRandoPassword()); ObjectNode extend = ContextUtils.OBJECT_MAPPER.createObjectNode(); if (registrationId.equalsIgnoreCase(GITHUB.name()) || "gitee".equalsIgnoreCase(registrationId)) { From 8071fdb482c31e82cd482076ece85358af5d1b8e Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:11:50 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20refactor(`ng-ui/pack?= =?UTF-8?q?age-lock.json`):=20Upgrade=20ng-zorro-antd=20to=20version=2019.?= =?UTF-8?q?0.0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ng-ui/package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ng-ui/package-lock.json b/ng-ui/package-lock.json index ec427330..f4048361 100644 --- a/ng-ui/package-lock.json +++ b/ng-ui/package-lock.json @@ -23,7 +23,7 @@ "bootstrap-icons": "^1.11.3", "dayjs": "^1.11.13", "express": "^4.18.2", - "ng-zorro-antd": "^19.0.0-beta", + "ng-zorro-antd": "^19.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0" }, @@ -10491,9 +10491,9 @@ "license": "MIT" }, "node_modules/ng-zorro-antd": { - "version": "19.0.0-beta.0", - "resolved": "https://registry.npmjs.org/ng-zorro-antd/-/ng-zorro-antd-19.0.0-beta.0.tgz", - "integrity": "sha512-sXpTQr7/8JKAZx+XSUibQrBTGUHos7KPIgvK4otDKmaMM5ydzGRE4aIbFGmX3Ou7zal8SPizbP5bkVnLLpGnIA==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/ng-zorro-antd/-/ng-zorro-antd-19.0.0.tgz", + "integrity": "sha512-H0PTE91lpyj+3TbPP7t3jt8R1/mOiizferXR63eOmAHyMne0Aqp0+lu7HCnUMPNqtbB//x7lUQcPLYLQxGSelA==", "license": "MIT", "dependencies": { "@angular/cdk": "^19.0.0", From c29623f7d8c4efa760a6b44d52e24f4e334a4bdd Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:12:01 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E2=9C=A8=20feat(`QueryFragment.java,=20Q?= =?UTF-8?q?ueryJsonHelper.java,=20QueryHelper.java`):=20Change=20'query'?= =?UTF-8?q?=20to=20'from'=20in=20various=20methods=20for=20SQL=20structure?= =?UTF-8?q?=20management.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commons/utils/query/QueryFragment.java | 46 ++++---- .../boot/commons/utils/query/QueryHelper.java | 108 +++++++++--------- .../commons/utils/query/QueryJsonHelper.java | 52 ++++----- 3 files changed, 105 insertions(+), 101 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryFragment.java b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryFragment.java index 0590b4ca..32aa2414 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryFragment.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryFragment.java @@ -14,7 +14,7 @@ * with placeholders for improved performance and security against SQL injection. * *

The QueryFragment class is designed to be flexible and modular, allowing users to build complex - * SQL queries by chaining method calls. It manages the SQL query structure, including the SELECT + * SQL queries by chaining method calls. It manages the SQL from structure, including the SELECT * columns, FROM clause, WHERE conditions, ORDER BY clause, and LIMIT/OFFSET for pagination. * *

Example usage: @@ -22,7 +22,7 @@ * {@code * QueryFragment queryFragment = QueryFragment.withNew() * .columns("id", "name", "email") - * .query("users") + * .from("users") * .where("age > :age", 18) * .orderBy("name ASC") * .orderBy("email DESC"); @@ -30,14 +30,14 @@ * // Bind parameters * queryFragment.put("age", 18); * - * // Generate SQL query + * // Generate SQL from * String sql = queryFragment.querySql(); * System.out.println(sql); * } * * In this example, a QueryFragment instance is created and configured with columns, a table name, - * a WHERE condition, and ORDER BY clauses. Parameters are added to the query fragment, and finally, - * the SQL query string is generated using the querySql() method. + * a WHERE condition, and ORDER BY clauses. Parameters are added to the from fragment, and finally, + * the SQL from string is generated using the querySql() method. * * @see QueryHelper for utility methods to construct QueryFragment instances from objects. */ @@ -56,11 +56,11 @@ public class QueryFragment extends HashMap { private final StringJoiner columns = new StringJoiner(","); /** - * A StringJoiner to accumulate the main SQL query parts (e.g., table names). + * A StringJoiner to accumulate the main SQL from parts (e.g., table names). * Example usage: *

      * {@code
-     * queryFragment.query("users");
+     * queryFragment.from("users");
      * }
      * 
*/ @@ -119,6 +119,10 @@ public QueryFragment(Map params) { super(params); } + public static QueryFragment withColumns(CharSequence... columns) { + return withMap(Map.of()).columns(columns); + } + public static QueryFragment withNew() { return withMap(Map.of()); } @@ -146,7 +150,7 @@ public QueryFragment columns(CharSequence... columns) { return this; } - public QueryFragment query(CharSequence... queries) { + public QueryFragment from(CharSequence... queries) { this.from.setEmptyValue(""); for (CharSequence query : queries) { this.from.add(query); @@ -160,7 +164,7 @@ public QueryFragment where(CharSequence where) { } /** - * Adds an ORDER BY clause to the query. + * Adds an ORDER BY clause to the from. * * @param order the order to add * @return the QueryFragment instance @@ -171,7 +175,7 @@ public QueryFragment orderBy(CharSequence order) { } /** - * Adds a GROUP BY clause to the query. + * Adds a GROUP BY clause to the from. * * @param size page size * @param offset page offset @@ -187,7 +191,7 @@ public QueryFragment ts(String column, Object value) { String lowerCamelCol = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column); String queryTable = "ts_" + lowerCamelCol; columns("TS_RANK_CD(" + lowerCamelCol + ", " + queryTable + ") AS rank"); - query(",TO_TSQUERY('chinese',:" + column + ") AS " + queryTable); + from(",TO_TSQUERY('chinese',:" + column + ") AS " + queryTable); where(queryTable + " @@ " + lowerCamelCol); put(column, value); return this; @@ -208,15 +212,15 @@ public String orderSql() { } /** - * Generates the complete SQL query string based on the configured columns, table, conditions, and pagination. + * Generates the complete SQL from string based on the configured columns, table, conditions, and pagination. * - *

The generated SQL query follows this structure: + *

The generated SQL from follows this structure: * SELECT columns FROM table WHERE conditions ORDER BY order LIMIT size OFFSET offset * - *

If no table or columns are specified, an exception is thrown to prevent generating an invalid query. + *

If no table or columns are specified, an exception is thrown to prevent generating an invalid from. * - * @return A String representing the complete SQL query. - * @throws QueryException if the querySql is null, indicating that the query structure is incomplete. + * @return A String representing the complete SQL from. + * @throws QueryException if the querySql is null, indicating that the from structure is incomplete. */ public String querySql() { if (this.from.length() > 0) { @@ -228,15 +232,15 @@ public String querySql() { } /** - * Generates the COUNT SQL query string based on the configured conditions. + * Generates the COUNT SQL from string based on the configured conditions. * - *

The generated COUNT SQL query follows this structure: + *

The generated COUNT SQL from follows this structure: * SELECT COUNT(*) FROM (SELECT columns FROM table WHERE conditions) t * - *

If no table or columns are specified, an exception is thrown to prevent generating an invalid query. + *

If no table or columns are specified, an exception is thrown to prevent generating an invalid from. * - * @return A String representing the COUNT SQL query. - * @throws QueryException if the countSql is null, indicating that the query structure is incomplete. + * @return A String representing the COUNT SQL from. + * @throws QueryException if the countSql is null, indicating that the from structure is incomplete. */ public String countSql() { if (this.from.length() > 0) { diff --git a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryHelper.java b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryHelper.java index 32a4d5fc..29f6e91b 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryHelper.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryHelper.java @@ -24,14 +24,14 @@ */ public final class QueryHelper { - public static final Set SKIP_CRITERIA_KEYS = Set.of("extend", - "createdTime", "updatedTime", "securityCode", "query", "search"); + public static final Set SKIP_CRITERIA_KEYS = Set.of("extend", "query", "search", + "createdTime", "updatedTime", "securityCode"); /** * Constructs a QueryFragment instance by converting the provided object into a map, * excluding specified keys, and then further processing this map to create the QueryFragment. * This method is used to dynamically build SQL queries based on the given object's properties, - * allowing for flexible and secure query construction. + * allowing for flexible and secure from construction. * *

The method's workflow is as follows: *

    @@ -40,25 +40,25 @@ public final class QueryHelper { *
  • Filters out the excluded keys from the map.
  • *
  • Creates a QueryFragment instance with pagination information from the Pageable object.
  • *
  • Applies sorting and WHERE conditions based on the object's properties.
  • - *
  • Generates the SQL query string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • + *
  • Generates the SQL from string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • *
* *

Example usage: *

      * {@code
-     * UserRequest userRequest = new UserRequest();
+     * UserReq userRequest = new UserReq();
      * userRequest.setUsername("john");
      * Pageable pageable = PageRequest.of(0, 10);
-     * QueryFragment queryFragment = QueryHelper.query(userRequest, pageable);
+     * QueryFragment queryFragment = QueryHelper.from(userRequest, pageable);
      * String sqlQuery = queryFragment.querySql();
      * }
      * 
- * In this example, a UserRequest object is created with a username filter, and a Pageable object is defined for pagination. - * The query method is then called to generate a QueryFragment, which can be used to execute a SQL query with pagination and filtering. + * In this example, a UserReq object is created with a username filter, and a Pageable object is defined for pagination. + * The from method is then called to generate a QueryFragment, which can be used to execute a SQL from with pagination and filtering. * - * @param object The object to be converted into a map for query construction. + * @param object The object to be converted into a map for from construction. * @param pageable The Pageable object containing pagination information. - * @return A QueryFragment instance representing the constructed query. + * @return A QueryFragment instance representing the constructed from. */ public static QueryFragment query(Object object, Pageable pageable) { return query(object, pageable, List.of(), null); @@ -68,7 +68,7 @@ public static QueryFragment query(Object object, Pageable pageable) { * Constructs a QueryFragment instance by converting the provided object into a map, * excluding specified keys, and then further processing this map to create the QueryFragment. * This method is used to dynamically build SQL queries based on the given object's properties, - * allowing for flexible and secure query construction. + * allowing for flexible and secure from construction. * *

The method's workflow is as follows: *

    @@ -77,24 +77,24 @@ public static QueryFragment query(Object object, Pageable pageable) { *
  • Filters out the excluded keys from the map.
  • *
  • Creates a QueryFragment instance with pagination information from a default Pageable object.
  • *
  • Applies sorting and WHERE conditions based on the object's properties.
  • - *
  • Generates the SQL query string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • + *
  • Generates the SQL from string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • *
* *

Example usage: *

      * {@code
-     * UserRequest userRequest = new UserRequest();
+     * UserReq userRequest = new UserReq();
      * userRequest.setUsername("john");
-     * QueryFragment queryFragment = QueryHelper.query(userRequest, List.of("username"));
+     * QueryFragment queryFragment = QueryHelper.from(userRequest, List.of("username"));
      * String sqlQuery = queryFragment.querySql();
      * }
      * 
- * In this example, a UserRequest object is created with a username filter, and a collection of keys to be excluded is defined. - * The query method is then called to generate a QueryFragment, which can be used to execute a SQL query with filtering. + * In this example, a UserReq object is created with a username filter, and a collection of keys to be excluded is defined. + * The from method is then called to generate a QueryFragment, which can be used to execute a SQL from with filtering. * - * @param object The object to be converted into a map for query construction. + * @param object The object to be converted into a map for from construction. * @param skipKeys A collection of keys to be excluded from the object map. - * @return A QueryFragment instance representing the constructed query. + * @return A QueryFragment instance representing the constructed from. */ public static QueryFragment query(Object object, Collection skipKeys) { return query(object, Pageable.ofSize(25), skipKeys, null); @@ -104,7 +104,7 @@ public static QueryFragment query(Object object, Collection skipKeys) { * Constructs a QueryFragment instance by converting the provided object into a map, * excluding specified keys, and then further processing this map to create the QueryFragment. * This method is used to dynamically build SQL queries based on the given object's properties, - * allowing for flexible and secure query construction. + * allowing for flexible and secure from construction. * *

The method's workflow is as follows: *

    @@ -113,25 +113,25 @@ public static QueryFragment query(Object object, Collection skipKeys) { *
  • Filters out the excluded keys from the map.
  • *
  • Creates a QueryFragment instance with pagination information from a default Pageable object.
  • *
  • Applies sorting and WHERE conditions based on the object's properties.
  • - *
  • Generates the SQL query string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • + *
  • Generates the SQL from string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • *
* *

Example usage: *

      * {@code
-     * UserRequest userRequest = new UserRequest();
+     * UserReq userRequest = new UserReq();
      * userRequest.setUsername("john");
-     * QueryFragment queryFragment = QueryHelper.query(userRequest, List.of("username"), "a");
+     * QueryFragment queryFragment = QueryHelper.from(userRequest, List.of("username"), "a");
      * String sqlQuery = queryFragment.querySql();
      * }
      * 
- * In this example, a UserRequest object is created with a username filter, and a collection of keys to be excluded is defined. - * The query method is then called to generate a QueryFragment, which can be used to execute a SQL query with filtering. + * In this example, a UserReq object is created with a username filter, and a collection of keys to be excluded is defined. + * The from method is then called to generate a QueryFragment, which can be used to execute a SQL from with filtering. * - * @param object The object to be converted into a map for query construction. + * @param object The object to be converted into a map for from construction. * @param skipKeys A collection of keys to be excluded from the object map. * @param prefix An optional prefix to be applied to column names. - * @return A QueryFragment instance representing the constructed query. + * @return A QueryFragment instance representing the constructed from. */ public static QueryFragment query(Object object, Collection skipKeys, String prefix) { return query(object, Pageable.ofSize(25), skipKeys, prefix); @@ -141,7 +141,7 @@ public static QueryFragment query(Object object, Collection skipKeys, St * Constructs a QueryFragment instance by converting the provided object into a map, * excluding specified keys, and then further processing this map to create the QueryFragment. * This method is used to dynamically build SQL queries based on the given object's properties, - * allowing for flexible and secure query construction. + * allowing for flexible and secure from construction. * *

The method's workflow is as follows: *

    @@ -150,26 +150,26 @@ public static QueryFragment query(Object object, Collection skipKeys, St *
  • Filters out the excluded keys from the map.
  • *
  • Creates a QueryFragment instance with pagination information from the Pageable object.
  • *
  • Applies sorting and WHERE conditions based on the object's properties.
  • - *
  • Generates the SQL query string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • + *
  • Generates the SQL from string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • *
* *

Example usage: *

      * {@code
-     * UserRequest userRequest = new UserRequest();
+     * UserReq userRequest = new UserReq();
      * userRequest.setUsername("john");
      * Pageable pageable = PageRequest.of(0, 10);
-     * QueryFragment queryFragment = QueryHelper.query(userRequest, pageable, "a");
+     * QueryFragment queryFragment = QueryHelper.from(userRequest, pageable, "a");
      * String sqlQuery = queryFragment.querySql();
      * }
      * 
- * In this example, a UserRequest object is created with a username filter, and a Pageable object is defined for pagination. - * The query method is then called to generate a QueryFragment, which can be used to execute a SQL query with pagination and filtering. + * In this example, a UserReq object is created with a username filter, and a Pageable object is defined for pagination. + * The from method is then called to generate a QueryFragment, which can be used to execute a SQL from with pagination and filtering. * - * @param object The object to be converted into a map for query construction. + * @param object The object to be converted into a map for from construction. * @param pageable The Pageable object containing pagination information. * @param prefix An optional prefix to be applied to column names. - * @return A QueryFragment instance representing the constructed query. + * @return A QueryFragment instance representing the constructed from. */ public static QueryFragment query(Object object, Pageable pageable, String prefix) { return query(object, pageable, List.of(), prefix); @@ -179,7 +179,7 @@ public static QueryFragment query(Object object, Pageable pageable, String prefi * Constructs a QueryFragment instance by converting the provided object into a map, * excluding specified keys, and then further processing this map to create the QueryFragment. * This method is used to dynamically build SQL queries based on the given object's properties, - * allowing for flexible and secure query construction. + * allowing for flexible and secure from construction. * *

The method's workflow is as follows: *

    @@ -188,28 +188,28 @@ public static QueryFragment query(Object object, Pageable pageable, String prefi *
  • Filters out the excluded keys from the map.
  • *
  • Creates a QueryFragment instance with pagination information from the Pageable object.
  • *
  • Applies sorting and WHERE conditions based on the object's properties.
  • - *
  • Generates the SQL query string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • + *
  • Generates the SQL from string by concatenating the columns, table name, WHERE clause, and ORDER BY clause.
  • *
* *

Example usage: *

      * {@code
-     * UserRequest userRequest = new UserRequest();
+     * UserReq userRequest = new UserReq();
      * userRequest.setUsername("john");
      * Pageable pageable = PageRequest.of(0, 10);
-     * QueryFragment queryFragment = QueryHelper.query(userRequest, pageable, List.of("username"), "a");
+     * QueryFragment queryFragment = QueryHelper.from(userRequest, pageable, List.of("username"), "a");
      * String sqlQuery = queryFragment.querySql();
      * }
      * 
- * In this example, a UserRequest object is created with a username filter, a Pageable object is defined for pagination, - * and a collection of keys to be excluded is provided. The query method is then called to generate a QueryFragment, - * which can be used to execute a SQL query with pagination and filtering. + * In this example, a UserReq object is created with a username filter, a Pageable object is defined for pagination, + * and a collection of keys to be excluded is provided. The from method is then called to generate a QueryFragment, + * which can be used to execute a SQL from with pagination and filtering. * - * @param object The object to be converted into a map for query construction. + * @param object The object to be converted into a map for from construction. * @param pageable The Pageable object containing pagination information. * @param skipKeys A collection of keys to be excluded from the object map. * @param prefix An optional prefix to be applied to column names. - * @return A QueryFragment instance representing the constructed query. + * @return A QueryFragment instance representing the constructed from. */ public static QueryFragment query(Object object, Pageable pageable, Collection skipKeys, String prefix) { Map objectMap = BeanUtils.beanToMap(object, false, true); @@ -230,16 +230,16 @@ public static QueryFragment query(Object object, Pageable pageable, Collection objectMap, String prefix) { - if (objectMap.containsKey("query")) { - var jsonMap = (Map) objectMap.get("query"); + if (objectMap.containsKey("from")) { + var jsonMap = (Map) objectMap.get("from"); var jsonQueryFragment = QueryJsonHelper.queryJson(jsonMap, prefix); queryFragment.getWhere().merge(jsonQueryFragment.getWhere()); queryFragment.putAll(jsonQueryFragment); @@ -247,7 +247,7 @@ private static void processQueryKey(QueryFragment queryFragment, MapThis class is essential for applications that need to query JSON data stored in SQL databases, as it + *

This class is essential for applications that need to from JSON data stored in SQL databases, as it * helps in constructing SQL queries that can understand and manipulate JSON structures. * *

Example usage: @@ -33,9 +33,9 @@ * System.out.println(sqlQuery); * } * - * In this example, a JSON-based query is constructed using the QueryJsonHelper class. The query searches - * for a user with a username like "Test User" and an email equal to "testuser@example.com". The query is - * then converted into an SQL query string that can be executed against a database. + * In this example, a JSON-based from is constructed using the QueryJsonHelper class. The from searches + * for a user with a username like "Test User" and an email equal to "testuser@example.com". The from is + * then converted into an SQL from string that can be executed against a database. * *

For a JSON object with nested fields, such as: *

@@ -63,9 +63,9 @@
  * QueryFragment queryFragment = QueryJsonHelper.queryJson(jsonParams, "a");
  * }
  * 
- * This will generate an SQL query that can search for users based on the provided JSON parameters. + * This will generate an SQL from that can search for users based on the provided JSON parameters. * - * @see QueryFragment for the class representing the SQL query structure. + * @see QueryFragment for the class representing the SQL from structure. */ public final class QueryJsonHelper { @@ -149,10 +149,10 @@ private static Sort.Order convertSortOrderToCamelCase(Sort.Order order) { } /** - * Constructs a QueryFragment representing a set of JSON-based query conditions. + * Constructs a QueryFragment representing a set of JSON-based from conditions. * *

This method takes a map of JSON parameters and a prefix, and constructs a QueryFragment that can be - * used to build an SQL query targeting JSON data. The method iterates over the provided parameters, + * used to build an SQL from targeting JSON data. The method iterates over the provided parameters, * converting each into a properly formatted SQL condition using the provided prefix to namespace JSON keys. * * @param params A map where each key represents a JSON path (possibly prefixed) and the value is the @@ -179,15 +179,15 @@ public static QueryFragment queryJson(Map params, String prefix) * and delegates the construction of the final condition part to {@link #buildLastCondition(String[], Object)}. *

      * {@code
-     * // Create a map of JSON-based query parameters
+     * // Create a map of JSON-based from parameters
      * Map jsonParams = new HashMap<>();
      * jsonParams.put("extend.requestBody.nameEq", "Test User"); // EQ stands for Equal
      * jsonParams.put("extend.additionalField1Eq", "value1"); // EQ stands for Equal
      *
-     * // Use the QueryJsonHelper to construct the SQL query for the given JSON parameters
+     * // Use the QueryJsonHelper to construct the SQL from for the given JSON parameters
      * QueryFragment queryFragment = QueryJsonHelper.queryJson(jsonParams, "a");
      *
-     * // Get the SQL query string
+     * // Get the SQL from string
      * String sqlQuery = queryFragment.querySql();
      *
      * // Now you can execute the sqlQuery against your database using a JDBC template or similar
@@ -197,7 +197,7 @@ public static QueryFragment queryJson(Map params, String prefix)
      * @param entry  A map entry where the key is a dot-delimited string indicating a JSON path
      *               (e.g., "extend.usernameLike"), and the value is the target value for the condition.
      * @param prefix A prefix to prepend to the first key of the JSON path to qualify column names
-     *               in the SQL query, ensuring correct scoping or avoiding naming collisions.
+     *               in the SQL from, ensuring correct scoping or avoiding naming collisions.
      * @return A {@link QueryFragment} object representing the constructed SQL condition
      * for querying JSON data, including the SQL fragment, parameters, and the operation detail.
      * @throws RestServerException If the provided JSON path does not meet the minimum requirement of specifying
@@ -206,13 +206,13 @@ public static QueryFragment queryJson(Map params, String prefix)
     private static QueryFragment buildJsonCondition(Map.Entry entry, String prefix) {
         String[] keys = StringUtils.delimitedListToStringArray(entry.getKey(), ".");
         if (keys.length < 2) {
-            throw QueryException.withError("Json query column path [query[" + entry.getKey() + "]] error",
+            throw QueryException.withError("Json from column path [from[" + entry.getKey() + "]] error",
                     new Throwable("Json path example: extend.username," +
-                            "Request query params:" +
-                            "query[extend.usernameLike]=aa," +
-                            "query[extend.age]=23," +
-                            "query[extend.nameIn]=aa,bb,cc," +
-                            "query[extend.codeEq]=123456"
+                            "Request from params:" +
+                            "from[extend.usernameLike]=aa," +
+                            "from[extend.age]=23," +
+                            "from[extend.nameIn]=aa,bb,cc," +
+                            "from[extend.codeEq]=123456"
                     ));
         }
         // 处理第一个键
@@ -236,19 +236,19 @@ private static QueryFragment buildJsonCondition(Map.Entry entry,
     }
 
     /**
-     * Constructs the final part of a query condition based on an array of keys and a value.
+     * Constructs the final part of a from condition based on an array of keys and a value.
      * This method generates SQL fragments for different types of conditions such as equality,
      * between, in, not in, etc., depending on the detected keyword in the last key of the keys array.
      * It handles parameterization to prevent SQL injection and prepares the condition for dynamic
-     * query execution.
+     * from execution.
      *
      * @param keys  An array of strings forming the path to the JSON attribute. The last element
      *              may contain a keyword suffix for special operations.
-     * @param value The value to be compared against in the query condition. For 'In' and 'Between'
+     * @param value The value to be compared against in the from condition. For 'In' and 'Between'
      *              operations, this should be a comma-separated string or an array respectively.
      * @return A QueryCondition object containing:
      * - The 'getWhereSql' field as a string of the SQL fragment representing the condition.
-     * - The 'params' map holding named parameters and their values for the query.
+     * - The 'params' map holding named parameters and their values for the from.
      * - The 'operation' entry describing the operation type and its SQL syntax.
      */
     private static QueryFragment buildLastCondition(String[] keys, Object value) {
@@ -284,14 +284,14 @@ private static QueryFragment buildLastCondition(String[] keys, Object value) {
     }
 
     /**
-     * Constructs a JSON path query string from an array of keys meant to be used in SQL queries
+     * Constructs a JSON path from string from an array of keys meant to be used in SQL queries
      * targeting JSON data. Each key in the array is appended to the path with the appropriate
      * SQL-JSON operator, allowing for traversal of nested JSON objects.
      *
      * @param joinKeys An array of strings representing keys in a JSON object which will be combined
-     *                 to form a JSON path query expression.
+     *                 to form a JSON path from expression.
      * @return StringBuilder A StringBuilder object containing the concatenated JSON path
-     * query expression, suitable for use in SQL queries with JSON columns.
+     * from expression, suitable for use in SQL queries with JSON columns.
      */
     private static StringJoiner buildJsonQueryPath(String[] joinKeys) {
         StringJoiner jsonPath = new StringJoiner("->");

From d39dc8c2ffb772b9d98d4ddcad7e6761c7c32df5 Mon Sep 17 00:00:00 2001
From: AlexBob 
Date: Fri, 27 Dec 2024 15:12:14 +0800
Subject: [PATCH 09/19] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(`SecurityMa?=
 =?UTF-8?q?nager.java`):=20Renamed=20`UserRequest`=20and=20`UserResponse`?=
 =?UTF-8?q?=20to=20`UserReq`=20and=20`UserRes`=20for=20consistency.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../plate/boot/security/SecurityManager.java  | 28 +++++++++----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/boot/platform/src/main/java/com/plate/boot/security/SecurityManager.java b/boot/platform/src/main/java/com/plate/boot/security/SecurityManager.java
index 3bb3407e..e8030837 100644
--- a/boot/platform/src/main/java/com/plate/boot/security/SecurityManager.java
+++ b/boot/platform/src/main/java/com/plate/boot/security/SecurityManager.java
@@ -7,8 +7,8 @@
 import com.plate.boot.security.core.group.member.GroupMemberResp;
 import com.plate.boot.security.core.tenant.member.TenantMemberResponse;
 import com.plate.boot.security.core.user.User;
-import com.plate.boot.security.core.user.UserRequest;
-import com.plate.boot.security.core.user.UserResponse;
+import com.plate.boot.security.core.user.UserReq;
+import com.plate.boot.security.core.user.UserRes;
 import com.plate.boot.security.core.user.UsersService;
 import com.plate.boot.security.core.user.authority.UserAuthority;
 import lombok.RequiredArgsConstructor;
@@ -46,14 +46,14 @@
  * - Manage user registration and modification through integration with UsersService.
  * - Retrieve user information based on OAuth2 bindings for authentication purposes.
  * - Load user details by username, including associated roles and permissions.
- * - Cache query results to minimize direct database hits for frequently accessed data.
+ * - Cache from results to minimize direct database hits for frequently accessed data.
  * - Handle password updates in a secure manner, clearing related caches post-update.
  * - Populate SecurityDetails objects with comprehensive user and authorization data.
  * 

* Dependencies: * - UsersService: For CRUD operations on user entities. * - R2DBC (reactive database access): To execute SQL queries asynchronously. - * - Cache: Utilized for storing query results to improve response times on subsequent requests. + * - Cache: Utilized for storing from results to improve response times on subsequent requests. *

* Note: The class uses reactive types (Mono, Flux) to facilitate non-blocking, asynchronous processing. */ @@ -65,19 +65,19 @@ public class SecurityManager extends AbstractDatabase private final static QueryFragment QUERY_GROUP_MEMBERS_FRAGMENT = QueryFragment.withNew() .columns("a.*", "b.name", "b.extend") - .query("se_group_members a", "join se_groups b on a.group_code=b.code") + .from("se_group_members a", "join se_groups b on a.group_code=b.code") .where("a.user_code like :userCode"); private final static QueryFragment QUERY_TENANT_MEMBERS_FRAGMENT = QueryFragment.withNew() .columns("a.*", "b.name", "b.extend") - .query("se_tenant_members a", "join se_tenants b on a.tenant_code=b.code") + .from("se_tenant_members a", "join se_tenants b on a.tenant_code=b.code") .where("a.user_code like :userCode"); private final static QueryFragment QUERY_USER_AUTHORITY_FRAGMENT = QueryFragment.withNew() .columns("*") - .query("se_authorities") + .from("se_authorities") .where("user_code = :userCode"); private final static QueryFragment QUERY_GROUP_AUTHORITY_FRAGMENT = QueryFragment.withNew() .columns("ga.*") - .query("se_group_authorities ga", + .from("se_group_authorities ga", "join se_group_members gm on ga.group_code = gm.group_code", "join se_users su on gm.user_code = su.code", "join se_groups sg on gm.group_code = sg.code and sg.tenant_code = su.tenant_code") @@ -111,11 +111,11 @@ public Mono updatePassword(UserDetails userDetails, String newPassw /** * Registers a new user or modifies an existing one based on the provided user request. * - * @param request A UserRequest object containing the details necessary to register or modify a user. + * @param request A UserReq object containing the details necessary to register or modify a user. * If the request contains a non-empty 'code', it will be treated as a modification request. * @return A Mono emitting the updated or newly registered User instance upon successful operation. */ - public Mono registerOrModifyUser(UserRequest request) { + public Mono registerOrModifyUser(UserReq request) { if (StringUtils.hasLength(request.getCode())) { return this.usersService.operate(request); } @@ -133,7 +133,7 @@ public Mono registerOrModifyUser(UserRequest request) { * @return A Mono emitting the User if found, or an empty Mono if no user matches the given OAuth2 binding data. */ public Mono loadByOauth2(String bindType, String openid) { - QueryFragment queryFragment = QueryFragment.withNew().columns("*").query("se_users") + QueryFragment queryFragment = QueryFragment.withNew().columns("*").from("se_users") .where("extend->'oauth2'->:bindType->>'openid'::varchar = :openid"); queryFragment.put("bindType", bindType); queryFragment.put("openid", openid); @@ -192,7 +192,7 @@ public Mono findByUsername(String username) { */ private Mono buildUserDetails(User user, Set authorities) { SecurityDetails userDetails = SecurityDetails.of(user.getCode(), authorities, - BeanUtils.beanToMap(UserResponse.withUser(user)), "username").buildUser(user); + BeanUtils.beanToMap(UserRes.withUser(user)), "username").buildUser(user); Mono, List>> groupsAndTenantsMono = Mono.zipDelayError(this.loadGroups(user.getCode()), this.loadTenants(user.getCode())); return groupsAndTenantsMono.doOnNext(tuple2 -> { @@ -204,7 +204,7 @@ private Mono buildUserDetails(User user, Set /** * Loads a list of group members associated with a given user code asynchronously. * Utilizes caching to enhance performance on subsequent calls with the same user code. - * The data is fetched from the database using a predefined SQL query and then serialized + * The data is fetched from the database using a predefined SQL from and then serialized * with user auditor context before being collected and sorted into a list. * * @param userCode The unique code identifying the user whose groups are to be loaded. @@ -219,7 +219,7 @@ private Mono> loadGroups(String userCode) { /** * Loads a list of tenant members associated with a given user code. - * The data is fetched using a cached query with specific SQL and parameters, + * The data is fetched using a cached from with specific SQL and parameters, * then serialized with user auditor context, and finally collected into a sorted list. * * @param userCode The unique code identifying the user whose tenant members are to be loaded. From 7b3d472359a44d3bd231ac3b2efef1a9c0fcb51e Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:12:30 +0800 Subject: [PATCH 10/19] =?UTF-8?q?=E2=9C=A8=20feat(`SessionConfiguration.ja?= =?UTF-8?q?va`):=20=E4=BF=AE=E6=AD=A3=E4=BA=86=E5=85=B3=E4=BA=8EBearer=20t?= =?UTF-8?q?oken=E4=BD=8D=E7=BD=AE=E7=9A=84=E6=8F=8F=E8=BF=B0=EF=BC=8C?= =?UTF-8?q?=E4=BB=8E"query=20parameters"=E6=94=B9=E4=B8=BA"parameters"?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/plate/boot/config/SessionConfiguration.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/config/SessionConfiguration.java b/boot/platform/src/main/java/com/plate/boot/config/SessionConfiguration.java index 33f41e96..34b29104 100644 --- a/boot/platform/src/main/java/com/plate/boot/config/SessionConfiguration.java +++ b/boot/platform/src/main/java/com/plate/boot/config/SessionConfiguration.java @@ -27,12 +27,12 @@ /** * Configures session management for web applications with support for custom session ID resolution, * particularly tailored for handling both AJAX requests and cases where a Bearer token might be - * present either in the request header or query parameters. + * present either in the request header or from parameters. *

* This configuration class enhances the session handling by introducing a custom strategy to read * session IDs from a custom header ({@code X-Auth-Token}) for AJAX requests or falling back to * cookies for non-AJAX requests. It also supports extracting Bearer tokens from the Authorization - * header or access_token query parameter, ensuring secure and flexible session management. + * header or access_token from parameter, ensuring secure and flexible session management. */ @Configuration(proxyBeanMethods = false) @EnableRedisIndexedWebSession @@ -67,7 +67,7 @@ public SpringSessionBackedReactiveSessionRegistry session * Configures and provides a custom strategy for resolving the session ID from web requests. * This resolver extends {@link HeaderWebSessionIdResolver} and conditionally switches * between header-based and cookie-based session ID resolution based on the presence of - * specific request headers or query parameters. + * specific request headers or from parameters. * * @return A configured instance of {@link WebSessionIdResolver} that is capable of * handling session ID resolution with custom logic to support both header and From 44a93d3857ab871e1b8320c8a1050390ceb8e76b Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:12:41 +0800 Subject: [PATCH 11/19] =?UTF-8?q?=F0=9F=94=A7=20refactor(`TenantMembersSer?= =?UTF-8?q?vice.java`):=20Correct=20the=20SQL=20query=20to=20use=20`from`?= =?UTF-8?q?=20instead=20of=20`query`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/security/core/tenant/member/TenantMembersService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/tenant/member/TenantMembersService.java b/boot/platform/src/main/java/com/plate/boot/security/core/tenant/member/TenantMembersService.java index fd5be862..3727110f 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/tenant/member/TenantMembersService.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/tenant/member/TenantMembersService.java @@ -30,7 +30,7 @@ public Flux search(TenantMemberRequest request, Pageable p QueryFragment queryFragment = QueryFragment.of(pageable.getPageSize(), pageable.getOffset(), fragment) .columns("a.*", "b.name as tenant_name", "b.extend as tenant_extend", "c.name as login_name", "c.username") - .query("se_tenant_members a", + .from("se_tenant_members a", "inner join se_tenants b on a.tenant_code = b.code", "inner join se_users c on c.code = a.user_code"); QueryHelper.applySort(queryFragment, pageable.getSort(), "a"); From fe1d883495bfb7de4e531ca16fba42ede55ce1a2 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:19:09 +0800 Subject: [PATCH 12/19] =?UTF-8?q?=F0=9F=9A=9A=20refactor(`UserRequest.java?= =?UTF-8?q?`,=20`User.java`):=20Rename=20`UserRequest`=20to=20`UserReq`=20?= =?UTF-8?q?and=20update=20related=20methods.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/user/{UserRequest.java => UserReq.java} | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) rename boot/platform/src/main/java/com/plate/boot/security/core/user/{UserRequest.java => UserReq.java} (66%) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/user/UserRequest.java b/boot/platform/src/main/java/com/plate/boot/security/core/user/UserReq.java similarity index 66% rename from boot/platform/src/main/java/com/plate/boot/security/core/user/UserRequest.java rename to boot/platform/src/main/java/com/plate/boot/security/core/user/UserReq.java index 816cd446..8313d287 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/user/UserRequest.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/user/UserReq.java @@ -8,31 +8,31 @@ /** * Represents a user request, extending the base User class with additional attributes specific to requests. - * It includes a query map for parameters and a security code, offering fluent method for setting the security code. - * This class also provides utility methods to convert to a plain User instance and to bind request parameters into a SQL query fragment. + * It includes a from map for parameters and a security code, offering fluent method for setting the security code. + * This class also provides utility methods to convert to a plain User instance and to bind request parameters into a SQL from fragment. */ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class UserRequest extends User { +public class UserReq extends User { /** - * Sets the security code for the user request and returns the updated UserRequest instance. + * Sets the security code for the user request and returns the updated UserReq instance. * This method allows for method chaining in a fluent API style. * * @param securityCode The security code to be set for the user request. - * @return The UserRequest instance with the updated security code. + * @return The UserReq instance with the updated security code. */ - public UserRequest securityCode(String securityCode) { + public UserReq securityCode(String securityCode) { this.setSecurityCode(securityCode); return this; } /** - * Converts the UserRequest instance into a User instance by copying all properties. + * Converts the UserReq instance into a User instance by copying all properties. * This is useful when you need to separate concerns between a request object and a domain object. * - * @return A new User instance with properties copied from this UserRequest. + * @return A new User instance with properties copied from this UserReq. */ public User toUser() { return BeanUtils.copyProperties(this, User.class); From d70e297d685718f08a5b0de02945ad1eb10fc01d Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:20:31 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=F0=9F=9A=9A=20refactor(`boot/platform/sr?= =?UTF-8?q?c/main/java/com/plate/boot/security/core/user/UserRes.java`):?= =?UTF-8?q?=20Rename=20`UserResponse`=20to=20`UserRes`=20and=20add=20a=20`?= =?UTF-8?q?rank`=20field.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/user/{UserResponse.java => UserRes.java} | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) rename boot/platform/src/main/java/com/plate/boot/security/core/user/{UserResponse.java => UserRes.java} (79%) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/user/UserResponse.java b/boot/platform/src/main/java/com/plate/boot/security/core/user/UserRes.java similarity index 79% rename from boot/platform/src/main/java/com/plate/boot/security/core/user/UserResponse.java rename to boot/platform/src/main/java/com/plate/boot/security/core/user/UserRes.java index 6992bb99..e0fc4a74 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/user/UserResponse.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/user/UserRes.java @@ -4,6 +4,7 @@ import com.plate.boot.commons.utils.BeanUtils; import lombok.EqualsAndHashCode; import lombok.ToString; +import org.springframework.data.annotation.ReadOnlyProperty; import java.util.Map; @@ -16,10 +17,16 @@ */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class UserResponse extends User { +public class UserRes extends User { - public static UserResponse withUser(User user) { - UserResponse response = new UserResponse(); + /** + * Data full text search entity sort + */ + @ReadOnlyProperty + protected Double rank; + + public static UserRes withUser(User user) { + UserRes response = new UserRes(); BeanUtils.copyProperties(user, response); return response; } From 107510877fd5fa421e5dbf1cdeb0fcab9f393f1b Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:21:31 +0800 Subject: [PATCH 14/19] =?UTF-8?q?=E2=9C=A8=20feat(`UsersController.java`):?= =?UTF-8?q?=20Rename=20`UserRequest`=20to=20`UserReq`=20and=20update=20cor?= =?UTF-8?q?responding=20response=20types.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/core/user/UsersController.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersController.java b/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersController.java index 9028da26..43721038 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersController.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersController.java @@ -36,15 +36,15 @@ public class UsersController { * Ensures that the search operation is performed within the context of the tenant * derived from the security details of the requesting user. * - * @param request A UserRequest object encapsulating the search criteria. It also supports + * @param request A UserReq object encapsulating the search criteria. It also supports * setting a security code through method chaining. * @param pageable Specifies the pagination requirements for the result set, including * page number, size, sorting, etc. - * @return A Flux of UserResponse objects representing the found users matching the + * @return A Flux of UserRes objects representing the found users matching the * search criteria. The results are asynchronously streamed. */ @GetMapping("search") - public Flux search(UserRequest request, Pageable pageable) { + public Flux search(UserReq request, Pageable pageable) { return ContextUtils.securityDetails().flatMapMany(details -> this.usersService.search(request.securityCode(details.getTenantCode()), pageable)); } @@ -53,60 +53,60 @@ public Flux search(UserRequest request, Pageable pageable) { * Retrieves a paginated list of users based on the provided request and pagination details. * Ensures the operation is executed within the context of the authenticated tenant's security code. * - * @param request A UserRequest object encapsulating the user search criteria and additional request-specific fields. + * @param request A UserReq object encapsulating the user search criteria and additional request-specific fields. * @param pageable Specifies the pagination details such as page number, size, sort orders, etc. - * @return A Mono wrapping a PagedModel of UserResponse objects representing the paged user data. + * @return A Mono wrapping a PagedModel of UserRes objects representing the paged user data. */ @GetMapping("page") - public Mono> page(UserRequest request, Pageable pageable) { + public Mono> page(UserReq request, Pageable pageable) { return ContextUtils.securityDetails().flatMap(details -> this.usersService.page(request.securityCode(details.getTenantCode()), pageable)); } /** - * Adds a new user based on the provided UserRequest. + * Adds a new user based on the provided UserReq. * - * @param request A valid UserRequest object containing the details for the user to be added. + * @param request A valid UserReq object containing the details for the user to be added. * The ID within the request must be null, indicating a new user addition. - * @return A Mono emitting the UserResponse representing the newly added user. - * The UserResponse is a JSON-friendly version of the User entity with the password field excluded for security. + * @return A Mono emitting the UserRes representing the newly added user. + * The UserRes is a JSON-friendly version of the User entity with the password field excluded for security. * @throws IllegalArgumentException If the ID within the request is not null, indicating an attempt to add an existing user. */ @PostMapping("add") - public Mono add(@Valid @RequestBody UserRequest request) { + public Mono add(@Valid @RequestBody UserReq request) { Assert.isNull(request.getId(), () -> "When adding a new user, the ID must be null"); - return this.usersService.add(request).map(user -> BeanUtils.copyProperties(user, UserResponse.class)); + return this.usersService.add(request).map(user -> BeanUtils.copyProperties(user, UserRes.class)); } /** - * Modifies an existing user based on the provided {@link UserRequest}. + * Modifies an existing user based on the provided {@link UserReq}. * Validates the request ensuring it is intended for updating (annotated with {@link Update}). * Ensures the request contains a non-null ID before proceeding with modification. - * Upon successful update, maps the modified {@link User} to a {@link UserResponse} for the API response. + * Upon successful update, maps the modified {@link User} to a {@link UserRes} for the API response. * - * @param request A validated {@link UserRequest} containing the details for the user modification, + * @param request A validated {@link UserReq} containing the details for the user modification, * with a non-null ID of the user to be modified. - * @return A {@link Mono} emitting the updated user information as a {@link UserResponse}. + * @return A {@link Mono} emitting the updated user information as a {@link UserRes}. * @throws IllegalArgumentException If the request's ID is null, indicating an attempt to modify a non-existent user. */ @PutMapping("modify") - public Mono modify(@Validated(Update.class) @RequestBody UserRequest request) { + public Mono modify(@Validated(Update.class) @RequestBody UserReq request) { Assert.notNull(request.getId(), () -> "When modifying an existing user, the ID must not be null"); - return this.usersService.modify(request).map(user -> BeanUtils.copyProperties(user, UserResponse.class)); + return this.usersService.modify(request).map(user -> BeanUtils.copyProperties(user, UserRes.class)); } /** - * Deletes a user based on the provided UserRequest. + * Deletes a user based on the provided UserReq. * Ensures that the 'id' within the request is not null before proceeding with deletion. * - * @param request A UserRequest object containing the necessary details to identify the user for deletion. + * @param request A UserReq object containing the necessary details to identify the user for deletion. * Must not be null and must contain a valid 'id'. * @return A Mono indicating the completion of the delete operation. * If the operation completes successfully, the Mono will be completed without any value. * If the 'id' in the request is null, a NullPointerException will be thrown before the operation begins. */ @DeleteMapping("delete") - public Mono delete(@RequestBody UserRequest request) { + public Mono delete(@RequestBody UserReq request) { Assert.notNull(request.getId(), "When deleting a user, the ID must not be null"); return this.usersService.delete(request); } From 182e65ca97139c5008d2cb7ba0ba0cfff57102b3 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:21:56 +0800 Subject: [PATCH 15/19] =?UTF-8?q?=E2=9C=A8=20feat(`UsersService.java`):=20?= =?UTF-8?q?Rename=20UserRequest=20to=20UserReq=20and=20update=20related=20?= =?UTF-8?q?method=20signatures.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/security/core/user/UsersService.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersService.java b/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersService.java index 82884b52..d1869362 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersService.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/user/UsersService.java @@ -33,26 +33,26 @@ public class UsersService extends AbstractDatabase { * * @param request The user request object containing parameters needed for the search. * @param pageable The pagination information specifying the page number and size of each page. - * @return A Flux object containing a stream of UserResponse data. + * @return A Flux object containing a stream of UserRes data. */ - public Flux search(UserRequest request, Pageable pageable) { + public Flux search(UserReq request, Pageable pageable) { QueryFragment queryFragment = QueryHelper.query(request, pageable); String key = BeanUtils.cacheKey(request, pageable); - return super.queryWithCache(key, queryFragment.querySql(), queryFragment, UserResponse.class); + return super.queryWithCache(key, queryFragment.querySql(), queryFragment, UserRes.class); } /** * Retrieves a paged list of users based on the provided request and pagination settings. *

- * This method performs a search query using the given {@link UserRequest} and {@link Pageable} parameters, + * This method performs a search from using the given {@link UserReq} and {@link Pageable} parameters, * and then retrieves the total count of matching records. The results are then combined into a single * {@link Page} object, which includes both the list of users and the total count, allowing for pagination. * - * @param request The {@link UserRequest} object containing the search criteria. + * @param request The {@link UserReq} object containing the search criteria. * @param pageable The {@link Pageable} object defining the pagination settings. * @return A {@link Mono} that emits a single {@link Page} object containing the paged list of users and the total count. */ - public Mono> page(UserRequest request, Pageable pageable) { + public Mono> page(UserReq request, Pageable pageable) { var searchMono = this.search(request, pageable).collectList(); QueryFragment queryFragment = request.querySql(List.of()); var countMono = super.countWithCache(BeanUtils.cacheKey(request), queryFragment.countSql(), queryFragment); @@ -61,10 +61,10 @@ public Mono> page(UserRequest request, Pageable pageable) { } /** - * Loads a user by their unique code using a cached query. + * Loads a user by their unique code using a cached from. *

* This method retrieves a user from the repository based on the provided code. - * It utilizes a cached query to improve performance, reducing the need for repeated database hits + * It utilizes a cached from to improve performance, reducing the need for repeated database hits * for the same code. If a user with the given code is found, it is emitted as a single value in a {@link Mono}. * If no user is found, an empty {@link Mono} is returned. * @@ -78,18 +78,18 @@ public Mono loadByCode(String code) { /** - * Adds a new user based on the provided UserRequest. + * Adds a new user based on the provided UserReq. * *

This method first checks if a user with the same username already exists in the database. * If an existing user is found, a {@link RestServerException} is thrown indicating that the * user already exists. If no existing user is found, the request is processed through the - * {@link #operate(UserRequest)} method to create and save the new user entity.

+ * {@link #operate(UserReq)} method to create and save the new user entity.

* - * @param request A UserRequest object containing the details for the new user, including the username which must be unique. + * @param request A UserReq object containing the details for the new user, including the username which must be unique. * @return A Mono that, when subscribed to, emits the newly created User entity upon successful addition, * or errors with a RestServerException if the user already exists. */ - public Mono add(UserRequest request) { + public Mono add(UserReq request) { return this.usersRepository.existsByUsernameIgnoreCase(request.getUsername()).flatMap(exists -> { if (exists) { return Mono.error(RestServerException.withMsg("User already exists", @@ -100,18 +100,18 @@ public Mono add(UserRequest request) { } /** - * Modifies an existing user based on the provided UserRequest. + * Modifies an existing user based on the provided UserReq. *

* This method first attempts to find a user by their username in the repository. If the user is not found, * a {@link RestServerException} is thrown indicating the absence of the user. Upon finding the user, the * request's ID, code, and username are set to match the found user's details (though these typically would * be redundant operations given the nature of the method). The modified user is then processed through the - * {@link #operate(UserRequest)} method to apply any necessary updates defined in the request. + * {@link #operate(UserReq)} method to apply any necessary updates defined in the request. * - * @param request A UserRequest object containing the updated information for the user, primarily identified by their username. + * @param request A UserReq object containing the updated information for the user, primarily identified by their username. * @return A Mono that, when subscribed to, emits the updated User entity after modification or throws an exception if the user was not found. */ - public Mono modify(UserRequest request) { + public Mono modify(UserReq request) { Mono userFoundMono = Mono.defer(() -> Mono.error(RestServerException .withMsg("User [" + request.getUsername() + "] not found", new UsernameNotFoundException("User by username [" + request.getUsername() + "] not found!")))); @@ -125,19 +125,19 @@ public Mono modify(UserRequest request) { } /** - * Operates on a UserRequest to process and persist user data. + * Operates on a UserReq to process and persist user data. * - *

This method enhances the incoming UserRequest by upgrading the password encoding if necessary. + *

This method enhances the incoming UserReq by upgrading the password encoding if necessary. * It then attempts to find an existing user by code from the repository. If the user does not exist, * the request is converted into a new User entity. Subsequently, the request's data is copied onto * the found or created user, and the user is saved. Finally, the operation triggers a cache clearance * to ensure data consistency.

* - * @param request The UserRequest containing the data to operate on, including the code for user identification + * @param request The UserReq containing the data to operate on, including the code for user identification * and the password that may require encoding upgrade. * @return A Mono emitting the updated or newly created User after the operation is completed. */ - public Mono operate(UserRequest request) { + public Mono operate(UserReq request) { request.setPassword(this.upgradeEncodingIfPassword(request.getPassword())); var userMono = this.usersRepository.findByCode(request.getCode()).defaultIfEmpty(request.toUser()); userMono = userMono.flatMap(user -> { @@ -148,13 +148,13 @@ public Mono operate(UserRequest request) { } /** - * Deletes a user based on the provided UserRequest. + * Deletes a user based on the provided UserReq. * - * @param request A UserRequest object encapsulating the details necessary to identify the user for deletion. + * @param request A UserReq object encapsulating the details necessary to identify the user for deletion. * @return A Mono which upon subscription initiates the deletion process asynchronously. * The Mono will complete empty when the deletion is successful, or error if the operation fails. */ - public Mono delete(UserRequest request) { + public Mono delete(UserReq request) { return this.usersRepository.delete(request.toUser()) .doAfterTerminate(() -> this.cache.clear()); } From 6ade4468d1e6f9f1ca9df27c69eb7c89c3a3586f Mon Sep 17 00:00:00 2001 From: AlexBob Date: Fri, 27 Dec 2024 15:26:55 +0800 Subject: [PATCH 16/19] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(`GroupMembe?= =?UTF-8?q?rsService.java`):=20Remove=20unused=20query=20condition.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/security/core/group/member/GroupMembersService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java b/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java index 8a1d793f..d2b26853 100644 --- a/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java +++ b/boot/platform/src/main/java/com/plate/boot/security/core/group/member/GroupMembersService.java @@ -7,7 +7,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import org.springframework.data.relational.core.query.Criteria; import org.springframework.data.relational.core.query.Query; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; @@ -31,7 +30,6 @@ public Flux search(GroupMemberReq request, Pageable pageable) { "inner join se_users c on c.code = a.user_code") .where(fragment.getWhere().toString()); queryFragment.putAll(fragment); - Query.query(Criteria.where("name").in("a")); return super.queryWithCache(BeanUtils.cacheKey(request, pageable), queryFragment.querySql(), queryFragment, GroupMemberResp.class); } From 4faf4302be9814c26fc49100bb0144c0cc52e1c9 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Tue, 31 Dec 2024 16:35:00 +0800 Subject: [PATCH 17/19] =?UTF-8?q?=F0=9F=94=A7=20refactor(`build.gradle`):?= =?UTF-8?q?=20Remove=20unused=20Spring=20milestone=20and=20snapshot=20repo?= =?UTF-8?q?sitories.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index c1bc049c..f81ce588 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,6 @@ configure(allprojects) { project -> repositories { mavenLocal() - maven { url 'https://repo.spring.io/milestone' } - maven { url 'https://repo.spring.io/snapshot' } mavenCentral() } From c99842a34a60892cc4317970a5af23f7e2353645 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Thu, 2 Jan 2025 11:56:11 +0800 Subject: [PATCH 18/19] =?UTF-8?q?=E2=9C=A8=20feat(`QueryException.java`):?= =?UTF-8?q?=20Add=20detailed=20comments=20and=20Javadoc=20for=20the=20`Que?= =?UTF-8?q?ryException`=20class.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commons/exception/QueryException.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/boot/platform/src/main/java/com/plate/boot/commons/exception/QueryException.java b/boot/platform/src/main/java/com/plate/boot/commons/exception/QueryException.java index fbaedc47..2d997f04 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/exception/QueryException.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/exception/QueryException.java @@ -1,15 +1,44 @@ package com.plate.boot.commons.exception; /** - * @author Alex Bob + * Custom exception class for handling query-related errors. + * Extends the RestServerException to provide additional context for query errors. + * + *

Example usage:

+ *
+ * {@code
+ * try {
+ *     // some query logic
+ * } catch (Exception e) {
+ *     throw QueryException.withError("Error executing query", e);
+ * }
+ * }
+ * 
+ * + *

This class provides a static method to create instances of QueryException with a specific error message and cause.

+ * + *

Author: Alex Bob

*/ public class QueryException extends RestServerException { + /** + * Constructs a new QueryException with the specified detail message and cause. + * + * @param message the detail message (which is saved for later retrieval by the {@link Throwable#getMessage()} method). + * @param throwable the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). + */ public QueryException(String message, Throwable throwable) { super(message, throwable); } + /** + * Creates a new QueryException with the specified detail message and cause. + * + * @param message the detail message. + * @param throwable the cause. + * @return a new instance of QueryException. + */ public static QueryException withError(String message, Throwable throwable) { return new QueryException(message, throwable); } -} +} \ No newline at end of file From bf041d8eedf787548b07657ec905ac69c747a966 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Thu, 2 Jan 2025 12:00:46 +0800 Subject: [PATCH 19/19] =?UTF-8?q?=E2=9C=A8=20feat(`RestServerException.jav?= =?UTF-8?q?a`):=20Add=20detailed=20Javadoc=20comments=20and=20static=20fac?= =?UTF-8?q?tory=20methods=20for=20constructing=20`RestServerException`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/RestServerException.java | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java b/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java index d1608b3e..257e7ade 100644 --- a/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java +++ b/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java @@ -28,19 +28,45 @@ @EqualsAndHashCode(callSuper = true) public class RestServerException extends ServerErrorException { - + /** + * Constructs a new RestServerException with the specified detail message and cause. + * + * @param reason the detail message (which is saved for later retrieval by the {@link Throwable#getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). + */ public RestServerException(String reason, Throwable cause) { super(reason, cause); } + /** + * Constructs a new RestServerException with the specified detail message, handler method, and cause. + * + * @param reason the detail message (which is saved for later retrieval by the {@link Throwable#getMessage()} method). + * @param handlerMethod the method that caused the exception. + * @param cause the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). + */ public RestServerException(String reason, Method handlerMethod, Throwable cause) { super(reason, handlerMethod, cause); } + /** + * Constructs a new RestServerException with the specified detail message, method parameter, and cause. + * + * @param reason the detail message (which is saved for later retrieval by the {@link Throwable#getMessage()} method). + * @param parameter the method parameter that caused the exception. + * @param cause the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). + */ public RestServerException(String reason, MethodParameter parameter, Throwable cause) { super(reason, parameter, cause); } + /** + * Creates a new RestServerException with the specified detail message and cause. + * + * @param reason the detail message. + * @param cause the cause. + * @return a new instance of RestServerException. + */ public static RestServerException withMsg(String reason, Throwable cause) { var ex = new RestServerException(reason, cause); ex.setTitle(reason); @@ -49,10 +75,26 @@ public static RestServerException withMsg(String reason, Throwable cause) { return ex; } + /** + * Creates a new RestServerException with the specified detail message, handler method, and cause. + * + * @param reason the detail message. + * @param handlerMethod the method that caused the exception. + * @param cause the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). + * @return a new instance of RestServerException. + */ public static RestServerException withMsg(String reason, Method handlerMethod, @Nullable Throwable cause) { return new RestServerException(reason, handlerMethod, cause); } + /** + * Creates a new RestServerException with the specified detail message, method parameter, and cause. + * + * @param reason the detail message. + * @param parameter the method parameter that caused the exception. + * @param cause the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). + * @return a new instance of RestServerException. + */ public static RestServerException withMsg(String reason, MethodParameter parameter, Throwable cause) { return new RestServerException(reason, parameter, cause); }