Add punishment details and history retrieval functionality

This commit introduces a new `DetailsComponent` for displaying detailed punishment data and establishes a route to view punishment history by ID and type. It also updates the API to support fetching individual punishment records and refines database mappings for improved data handling.
This commit is contained in:
2025-04-19 04:02:51 +02:00
parent a1912b96d8
commit 3babde5513
22 changed files with 547 additions and 165 deletions
@@ -5,6 +5,7 @@ import lombok.Data;
@Data
public class HistoryRecord {
private String uuid;
private int id;
private String punishedName;
private String reason;
private String bannedByUuid;
@@ -0,0 +1,54 @@
package com.alttd.altitudeweb.database.litebans;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
public interface IdHistoryMapper {
@Results({
@Result(property = "id", column = "id"),
@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.id,
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 *
FROM ${table_name} AS punishment
WHERE punishment.id = #{id})
AS punishment
INNER JOIN user_lookup
ON user_lookup.uuid = punishment.uuid
""")
HistoryRecord getHistoryForId(@Param("table_name") String tableName,
@Param("type") String type,
@Param("id") int id);
default HistoryRecord getRecentHistory(HistoryType historyType, int id) {
HistoryRecord historyRecord = switch (historyType) {
case ALL -> throw new IllegalArgumentException("HistoryType.ALL is not supported");
case BAN -> getHistoryForId("litebans_bans", "ban", id);
case MUTE -> getHistoryForId("litebans_mutes", "mute", id);
case KICK -> getHistoryForId("litebans_kicks", "kick", id);
case WARN -> getHistoryForId("litebans_warnings", "warn", id);
};
historyRecord.setType(historyType.name().toLowerCase());
return historyRecord;
}
}
@@ -4,6 +4,7 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -24,6 +25,7 @@ public interface NameHistoryMapper {
* order
*/
@Results({
@Result(property = "id", column = "id"),
@Result(property = "uuid", column = "uuid"),
@Result(property = "punishedName", column = "punished_name"),
@Result(property = "reason", column = "reason"),
@@ -36,7 +38,8 @@ public interface NameHistoryMapper {
@Result(property = "type", column = "type")
})
@Select("""
SELECT all_punishments.uuid,
SELECT id,
all_punishments.uuid,
user_lookup.name AS punished_name,
reason,
banned_by_uuid,
@@ -62,7 +65,6 @@ public interface NameHistoryMapper {
* 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
*
@@ -70,6 +72,7 @@ public interface NameHistoryMapper {
* order
*/
@Results({
@Result(property = "id", column = "id"),
@Result(property = "uuid", column = "uuid"),
@Result(property = "punishedName", column = "punished_name"),
@Result(property = "reason", column = "reason"),
@@ -82,17 +85,19 @@ public interface NameHistoryMapper {
@Result(property = "type", column = "type")
})
@Select("""
SELECT punishments.uuid,
SELECT punishment.id,
punishment.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
punishment.reason,
punishment.banned_by_uuid,
punishment.banned_by_name,
punishment.removed_by_name,
punishment.time,
punishment.until,
punishment.removed_by_reason,
punishment.type
FROM (SELECT uuid,
id,
reason,
banned_by_uuid,
banned_by_name,
@@ -103,9 +108,9 @@ public interface NameHistoryMapper {
type
FROM all_punishments
ORDER BY time DESC
LIMIT #{limit} OFFSET #{offset}) AS punishments
LIMIT #{limit} OFFSET #{offset}) AS punishment
INNER JOIN user_lookup
ON user_lookup.uuid = punishments.uuid;
ON user_lookup.uuid = punishment.uuid;
""")
List<HistoryRecord> getRecentAllHistory(@Param("limit") int limit,
@Param("offset") int offset);
@@ -124,6 +129,7 @@ public interface NameHistoryMapper {
* order
*/
@Results({
@Result(property = "id", column = "id"),
@Result(property = "uuid", column = "uuid"),
@Result(property = "punishedName", column = "punished_name"),
@Result(property = "reason", column = "reason"),
@@ -135,7 +141,8 @@ public interface NameHistoryMapper {
@Result(property = "removedByReason", column = "removed_by_reason")
})
@Select("""
SELECT punishment.uuid,
SELECT punishment.id,
punishment.uuid,
user_lookup.name AS punished_name,
punishment.reason,
punishment.banned_by_uuid,
@@ -162,8 +169,6 @@ public interface NameHistoryMapper {
* 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
*
@@ -171,6 +176,7 @@ public interface NameHistoryMapper {
* order
*/
@Results({
@Result(property = "id", column = "id"),
@Result(property = "uuid", column = "uuid"),
@Result(property = "punishedName", column = "punished_name"),
@Result(property = "reason", column = "reason"),
@@ -182,7 +188,8 @@ public interface NameHistoryMapper {
@Result(property = "removedByReason", column = "removed_by_reason")
})
@Select("""
SELECT punishment.uuid,
SELECT punishment.id,
punishment.uuid,
user_lookup.name AS punished_name,
punishment.reason,
punishment.banned_by_uuid,
@@ -192,7 +199,8 @@ public interface NameHistoryMapper {
punishment.until,
punishment.removed_by_reason
FROM (
SELECT uuid,
SELECT id,
uuid,
reason,
banned_by_uuid,
banned_by_name,
@@ -254,23 +262,23 @@ public interface NameHistoryMapper {
}
}
private List<HistoryRecord> getRecentBans(UserType userType, String partialName, int page) {
private @NotNull List<HistoryRecord> getRecentBans(UserType userType, String partialName, int page) {
return addType(getRecent("litebans_bans", userType, partialName, page), "ban");
}
private List<HistoryRecord> getRecentKicks(UserType userType, String partialName, int page) {
private @NotNull List<HistoryRecord> getRecentKicks(UserType userType, String partialName, int page) {
return addType(getRecent("litebans_kicks", userType, partialName, page), "kick");
}
private List<HistoryRecord> getRecentMutes(UserType userType, String partialName, int page) {
private @NotNull List<HistoryRecord> getRecentMutes(UserType userType, String partialName, int page) {
return addType(getRecent("litebans_mutes", userType, partialName, page), "mute");
}
private List<HistoryRecord> getRecentWarns(UserType userType, String partialName, int page) {
private @NotNull List<HistoryRecord> getRecentWarns(UserType userType, String partialName, int page) {
return addType(getRecent("litebans_warnings", userType, partialName, page), "warn");
}
private List<HistoryRecord> addType(List<HistoryRecord> historyRecords, String type) {
private @NotNull List<HistoryRecord> addType(@NotNull List<HistoryRecord> historyRecords, String type) {
historyRecords.forEach(historyRecord -> historyRecord.setType(type));
return historyRecords;
}
@@ -1,10 +1,11 @@
package com.alttd.altitudeweb.database.litebans;
import com.alttd.altitudeweb.type_handler.UUIDTypeHandler;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.UUID;
@@ -14,10 +15,11 @@ public interface UUIDHistoryMapper {
int PAGE_SIZE = 10;
@Results({
@Result(property = "uuid", column = "uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class),
@Result(property = "id", column = "id"),
@Result(property = "uuid", column = "uuid"),
@Result(property = "punishedName", column = "punished_name"),
@Result(property = "reason", column = "reason"),
@Result(property = "bannedByUuid", column = "banned_by_uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class),
@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"),
@@ -26,7 +28,7 @@ public interface UUIDHistoryMapper {
@Result(property = "type", column = "type")
})
@Select("""
SELECT all_punishments.uuid, user_lookup.name AS punished_name, reason, banned_by_uuid, banned_by_name,
SELECT id, 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
@@ -41,10 +43,11 @@ public interface UUIDHistoryMapper {
@Param("offset") int offset);
@Results({
@Result(property = "uuid", column = "uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class),
@Result(property = "id", column = "id"),
@Result(property = "uuid", column = "uuid"),
@Result(property = "punishedName", column = "punished_name"),
@Result(property = "reason", column = "reason"),
@Result(property = "bannedByUuid", column = "banned_by_uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class),
@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"),
@@ -52,7 +55,7 @@ public interface UUIDHistoryMapper {
@Result(property = "removedByReason", column = "removed_by_reason")
})
@Select("""
SELECT punishment.uuid, user_lookup.name AS punished_name, reason, banned_by_uuid, banned_by_name,
SELECT punishment.id, 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
@@ -66,7 +69,8 @@ public interface UUIDHistoryMapper {
@Param("limit") int limit,
@Param("offset") int offset);
default List<HistoryRecord> getRecent(HistoryType historyType, UserType userType, UUID uuid, int page) {
default List<HistoryRecord> getRecent(@NotNull HistoryType historyType, @NotNull UserType userType,
@NotNull UUID uuid, int page) {
return switch (historyType) {
case ALL -> getRecentAll(userType, uuid, page);
case BAN -> getRecentBans(userType, uuid, page);
@@ -76,7 +80,8 @@ public interface UUIDHistoryMapper {
};
}
private List<HistoryRecord> getRecent(String tableName, UserType userType, UUID uuid, int page) {
private List<HistoryRecord> getRecent(@NotNull String tableName, @NotNull UserType userType,
@NotNull UUID uuid, int page) {
int offset = page * PAGE_SIZE;
int limit = PAGE_SIZE;
return switch (userType) {
@@ -85,7 +90,7 @@ public interface UUIDHistoryMapper {
};
}
private List<HistoryRecord> getRecentAll(UserType userType, UUID uuid, int page) {
private List<HistoryRecord> getRecentAll(@NotNull UserType userType, @NotNull UUID uuid, int page) {
int offset = page * PAGE_SIZE;
int limit = PAGE_SIZE;
return switch (userType) {
@@ -96,23 +101,24 @@ public interface UUIDHistoryMapper {
};
}
private List<HistoryRecord> getRecentBans(UserType userType, UUID uuid, int page) {
private @NotNull List<HistoryRecord> getRecentBans(@NotNull UserType userType, @NotNull UUID uuid, int page) {
return addType(getRecent("litebans_bans", userType, uuid, page), "ban");
}
private List<HistoryRecord> getRecentKicks(UserType userType, UUID uuid, int page) {
private @NotNull List<HistoryRecord> getRecentKicks(@NotNull UserType userType, @NotNull UUID uuid, int page) {
return addType(getRecent("litebans_kicks", userType, uuid, page), "kick");
}
private List<HistoryRecord> getRecentMutes(UserType userType, UUID uuid, int page) {
private @NotNull List<HistoryRecord> getRecentMutes(@NotNull UserType userType, @NotNull UUID uuid, int page) {
return addType(getRecent("litebans_mutes", userType, uuid, page), "mute");
}
private List<HistoryRecord> getRecentWarns(UserType userType, UUID uuid, int page) {
private @NotNull List<HistoryRecord> getRecentWarns(@NotNull UserType userType, @NotNull UUID uuid, int page) {
return addType(getRecent("litebans_warnings", userType, uuid, page), "warn");
}
private List<HistoryRecord> addType(List<HistoryRecord> historyRecords, String type) {
@Contract("_, _ -> param1")
private @NotNull List<HistoryRecord> addType(@NotNull List<HistoryRecord> historyRecords, @NotNull String type) {
historyRecords.forEach(historyRecord -> historyRecord.setType(type));
return historyRecords;
}
@@ -18,6 +18,7 @@ public class InitializeLiteBans {
configuration.addMapper(NameHistoryMapper.class);
configuration.addMapper(UUIDHistoryMapper.class);
configuration.addMapper(HistoryCountMapper.class);
configuration.addMapper(IdHistoryMapper.class);
}).join()
.runQuery(sqlSession -> {
createAllPunishmentsView(sqlSession);
@@ -29,15 +30,15 @@ public class InitializeLiteBans {
private static void createAllPunishmentsView(SqlSession sqlSession) {
String query = """
CREATE VIEW IF NOT EXISTS all_punishments AS
SELECT uuid, reason, banned_by_uuid, banned_by_name, removed_by_name, time, until, removed_by_reason,
SELECT id, uuid, reason, banned_by_uuid, banned_by_name, removed_by_name, time, until, removed_by_reason,
'ban' as type
FROM litebans_bans
UNION ALL
SELECT uuid, reason, banned_by_uuid, banned_by_name, removed_by_name, time, until, removed_by_reason,
SELECT id, uuid, reason, banned_by_uuid, banned_by_name, removed_by_name, time, until, removed_by_reason,
'mute' as type
FROM litebans_mutes
UNION ALL
SELECT uuid, reason, banned_by_uuid, banned_by_name, removed_by_name, time, until, removed_by_reason,
SELECT id, uuid, reason, banned_by_uuid, banned_by_name, removed_by_name, time, until, removed_by_reason,
'warn' as type
FROM litebans_warnings
ORDER BY time DESC;