diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/limits/RateLimitAspect.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/limits/RateLimitAspect.java index 0f80248..c7de9f6 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/limits/RateLimitAspect.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/limits/RateLimitAspect.java @@ -71,13 +71,6 @@ public class RateLimitAspect { Duration nextResetTime = rateLimiterService.getNextResetTime(key, duration); - if (response != null) { - response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); - response.setHeader("X-Rate-Limit-Limit", String.valueOf(limit)); - response.setHeader("X-Rate-Limit-Remaining", "0"); - response.setHeader("Retry-After", String.valueOf(nextResetTime.getSeconds())); - } - return ResponseEntity .status(HttpStatus.TOO_MANY_REQUESTS) .header("X-Rate-Limit-Limit", String.valueOf(limit)) diff --git a/database/src/main/java/com/alttd/altitudeweb/database/litebans/NameHistoryMapper.java b/database/src/main/java/com/alttd/altitudeweb/database/litebans/NameHistoryMapper.java index e399895..8e3f471 100644 --- a/database/src/main/java/com/alttd/altitudeweb/database/litebans/NameHistoryMapper.java +++ b/database/src/main/java/com/alttd/altitudeweb/database/litebans/NameHistoryMapper.java @@ -36,18 +36,78 @@ public interface NameHistoryMapper { @Result(property = "type", column = "type") }) @Select(""" - SELECT all_punishments.uuid, user_lookup.name AS punished_name, reason, banned_by_uuid, banned_by_name, - removed_by_name, time, until, removed_by_reason, type + SELECT all_punishments.uuid, + user_lookup.name AS punished_name, + reason, + banned_by_uuid, + banned_by_name, + removed_by_name, + time, + until, + removed_by_reason, + type FROM all_punishments - INNER JOIN user_lookup - ON user_lookup.uuid = all_punishments.uuid + INNER JOIN user_lookup + ON user_lookup.uuid = all_punishments.uuid WHERE ${name_column} LIKE #{partialName} ORDER BY time DESC LIMIT #{limit} OFFSET #{offset} """) - List getRecentAllHistory(@Param("partialName") String partialName, - @Param("name_column") String nameColumn, - @Param("limit") int limit, + List getRecentAllHistoryForName(@Param("partialName") String partialName, + @Param("name_column") String nameColumn, + @Param("limit") int limit, + @Param("offset") int offset); + + /** + * Retrieves a list of all types of recent punishment history records sorted + * in descending time order. This result does NOT contain kicks history + * + * @param nameColumn the column name in the database indicating the name to use for filtering + * @param limit the maximum number of records to fetch + * @param offset the starting offset position of the result set + * + * @return a list of {@link HistoryRecord} objects that match the specified filters, ordered by time in descending + * order + */ + @Results({ + @Result(property = "uuid", column = "uuid"), + @Result(property = "punishedName", column = "punished_name"), + @Result(property = "reason", column = "reason"), + @Result(property = "bannedByUuid", column = "banned_by_uuid"), + @Result(property = "bannedByName", column = "banned_by_name"), + @Result(property = "removedByName", column = "removed_by_name"), + @Result(property = "time", column = "time"), + @Result(property = "until", column = "until"), + @Result(property = "removedByReason", column = "removed_by_reason"), + @Result(property = "type", column = "type") + }) + @Select(""" + SELECT punishments.uuid, + user_lookup.name AS punished_name, + punishments.reason, + punishments.banned_by_uuid, + punishments.banned_by_name, + punishments.removed_by_name, + punishments.time, + punishments.until, + punishments.removed_by_reason, + punishments.type + FROM (SELECT uuid, + reason, + banned_by_uuid, + banned_by_name, + removed_by_name, + time, + until, + removed_by_reason, + type + FROM all_punishments + ORDER BY time DESC + LIMIT #{limit} OFFSET #{offset}) AS punishments + INNER JOIN user_lookup + ON user_lookup.uuid = punishments.uuid; + """) + List getRecentAllHistory(@Param("limit") int limit, @Param("offset") int offset); /** @@ -75,19 +135,80 @@ public interface NameHistoryMapper { @Result(property = "removedByReason", column = "removed_by_reason") }) @Select(""" - SELECT punishment.uuid, user_lookup.name AS punished_name, reason, banned_by_uuid, banned_by_name, - removed_by_name, time, until, removed_by_reason + SELECT punishment.uuid, + user_lookup.name AS punished_name, + reason, + banned_by_uuid, + banned_by_name, + removed_by_name, + time, + until, + removed_by_reason FROM ${tableName} AS punishment - INNER JOIN user_lookup ON user_lookup.uuid = punishment.uuid + INNER JOIN user_lookup ON user_lookup.uuid = punishment.uuid WHERE ${name_column} LIKE #{partialName} ORDER BY time DESC LIMIT #{limit} OFFSET #{offset} """) + List getRecentHistoryForName(@Param("tableName") String tableName, + @Param("partialName") String partialName, + @Param("name_column") String nameColumn, + @Param("limit") int limit, + @Param("offset") int offset); + + /** + * Retrieves a list of a specific type of recent punishment history records filtered based on the provided + * parameters. The records are sorted in descending order by time and limited to a specified range. + * + * @param tableName the name of the database table to query the history records from + * @param partialName a partial or complete name of the user to filter the records, case-insensitive + * @param nameColumn the column name in the database indicating the name to use for filtering + * @param limit the maximum number of records to fetch + * @param offset the starting offset position of the result set + * + * @return a list of {@link HistoryRecord} objects that match the specified filters, sorted by time in descending + * order + */ + @Results({ + @Result(property = "uuid", column = "uuid"), + @Result(property = "punishedName", column = "punished_name"), + @Result(property = "reason", column = "reason"), + @Result(property = "bannedByUuid", column = "banned_by_uuid"), + @Result(property = "bannedByName", column = "banned_by_name"), + @Result(property = "removedByName", column = "removed_by_name"), + @Result(property = "time", column = "time"), + @Result(property = "until", column = "until"), + @Result(property = "removedByReason", column = "removed_by_reason") + }) + @Select(""" + SELECT punishment.uuid, + user_lookup.name AS punished_name, + punishment.reason, + punishment.banned_by_uuid, + punishment.banned_by_name, + punishment.removed_by_name, + punishment.time, + punishment.until, + punishment.removed_by_reason + FROM ( + SELECT uuid, + reason, + banned_by_uuid, + banned_by_name, + removed_by_name, + time, + until, + removed_by_reason + FROM ${tableName} AS punishment + WHERE ${name_column} LIKE #{partialName} + ORDER BY time DESC + LIMIT #{limit} OFFSET #{offset} + ) AS punishment + INNER JOIN user_lookup ON user_lookup.uuid = punishment.uuid + """) List getRecentHistory(@Param("tableName") String tableName, - @Param("partialName") String partialName, - @Param("name_column") String nameColumn, - @Param("limit") int limit, - @Param("offset") int offset); + @Param("limit") int limit, + @Param("offset") int offset); default List getRecent(HistoryType historyType, UserType userType, String partialName, int page) { @@ -104,23 +225,33 @@ public interface NameHistoryMapper { int page) { int offset = page * PAGE_SIZE; int limit = PAGE_SIZE; - return switch (userType) { - case PLAYER -> getRecentHistory(tableName, partialName.toLowerCase() + "%", "name", - limit, offset); - case STAFF -> getRecentHistory(tableName, partialName.toLowerCase() + "%", "banned_by_name", - limit, offset); - }; + if (partialName.isEmpty()) { + return getRecentHistory(tableName, limit, offset); + } else { + final String searchName = partialName.toLowerCase().replace("_", "\\_") + "%"; + return switch (userType) { + case PLAYER -> getRecentHistoryForName(tableName, searchName, "name", + limit, offset); + case STAFF -> getRecentHistoryForName(tableName, searchName, "banned_by_name", + limit, offset); + }; + } } private List getRecentAll(UserType userType, String partialName, int page) { int offset = page * PAGE_SIZE; int limit = PAGE_SIZE; - return switch (userType) { - case PLAYER -> getRecentAllHistory(partialName.toLowerCase() + "%", "name", - limit, offset); - case STAFF -> getRecentAllHistory(partialName.toLowerCase() + "%", "banned_by_name", - limit, offset); - }; + if (partialName.isEmpty()) { + return getRecentAllHistory(limit, offset); + } else { + final String searchName = partialName.toLowerCase().replace("_", "\\_") + "%"; + return switch (userType) { + case PLAYER -> getRecentAllHistoryForName(searchName, "name", + limit, offset); + case STAFF -> getRecentAllHistoryForName(searchName, "banned_by_name", + limit, offset); + }; + } } private List getRecentBans(UserType userType, String partialName, int page) {