diff --git a/src/main/java/client/command/commands/gm3/UnBanCommand.java b/src/main/java/client/command/commands/gm3/UnBanCommand.java index fecbaaddeb..96f00412fb 100644 --- a/src/main/java/client/command/commands/gm3/UnBanCommand.java +++ b/src/main/java/client/command/commands/gm3/UnBanCommand.java @@ -27,10 +27,6 @@ import client.Character; import client.Client; import client.command.Command; import client.command.CommandContext; -import tools.DatabaseConnection; - -import java.sql.Connection; -import java.sql.PreparedStatement; public class UnBanCommand extends Command { { @@ -45,25 +41,12 @@ public class UnBanCommand extends Command { return; } - try (Connection con = DatabaseConnection.getConnection()) { - int aid = Character.getAccountIdByName(params[0]); - - try (PreparedStatement p = con.prepareStatement("UPDATE accounts SET banned = -1 WHERE id = " + aid)) { - p.executeUpdate(); - } - - try (PreparedStatement p = con.prepareStatement("DELETE FROM ipbans WHERE aid = " + aid)) { - p.executeUpdate(); - } - - try (PreparedStatement p = con.prepareStatement("DELETE FROM macbans WHERE aid = " + aid)) { - p.executeUpdate(); - } - } catch (Exception e) { - e.printStackTrace(); - player.message("Failed to unban " + params[0]); + String chrName = params[0]; + if (!ctx.banService().unban(chrName)) { + player.message("Failed to unban " + chrName); return; } - player.message("Unbanned " + params[0]); + + player.message("Unbanned " + chrName); } } diff --git a/src/main/java/database/account/AccountRepository.java b/src/main/java/database/account/AccountRepository.java index 4d362ca6cf..e4a47d13b5 100644 --- a/src/main/java/database/account/AccountRepository.java +++ b/src/main/java/database/account/AccountRepository.java @@ -157,14 +157,15 @@ public class AccountRepository { } } - public boolean setBanned(int accountId, Instant bannedUntil, byte banReason, String description) { + public boolean setBanned(int accountId, boolean banned, Instant bannedUntil, Byte banReason, String description) { String sql = """ UPDATE account - SET banned = true, banned_until = :bannedUntil, ban_reason = :banReason, ban_description = :banDescription + SET banned = :banned, banned_until = :bannedUntil, ban_reason = :banReason, ban_description = :banDescription WHERE id = :id"""; try (Handle handle = connection.getHandle()) { return handle.createUpdate(sql) .bind("id", accountId) + .bind("banned", banned) .bind("bannedUntil", bannedUntil) .bind("banReason", banReason) .bind("banDescription", description) diff --git a/src/main/java/database/ban/IpBanRepository.java b/src/main/java/database/ban/IpBanRepository.java index f95cb459ec..7a0a126d84 100644 --- a/src/main/java/database/ban/IpBanRepository.java +++ b/src/main/java/database/ban/IpBanRepository.java @@ -28,7 +28,7 @@ public class IpBanRepository { } } - public boolean saveIpBan(int accountId, String ip) { + public boolean saveIpBan(String ip, int accountId) { String sql = """ INSERT INTO ip_ban (account_id, ip) VALUES (:accountId, :ip)"""; @@ -42,4 +42,15 @@ public class IpBanRepository { return false; } } + + public void deleteIpBan(String ip) { + String sql = """ + DELETE FROM ip_ban + WHERE ip = :ip"""; + try (Handle handle = connection.getHandle()) { + handle.createUpdate(sql) + .bind("ip", ip) + .execute(); + } + } } diff --git a/src/main/java/server/ban/IpBanManager.java b/src/main/java/server/ban/IpBanManager.java index 281b93b50c..55e8be988d 100644 --- a/src/main/java/server/ban/IpBanManager.java +++ b/src/main/java/server/ban/IpBanManager.java @@ -5,8 +5,10 @@ import database.ban.IpBanRepository; import lombok.extern.slf4j.Slf4j; import net.jcip.annotations.ThreadSafe; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -16,7 +18,7 @@ import java.util.Set; @Slf4j public class IpBanManager { private final IpBanRepository ipBanRepository; - private final Set bannedIps = new HashSet<>(); + private final Map bannedIps = new HashMap<>(); public IpBanManager(IpBanRepository ipBanRepository) { this.ipBanRepository = ipBanRepository; @@ -25,11 +27,11 @@ public class IpBanManager { public synchronized void loadIpBans() { List ipBans = ipBanRepository.getAllIpBans(); log.debug("Loaded {} ip bans", ipBans.size()); - bannedIps.addAll(ipBans.stream().map(IpBan::ip).toList()); + ipBans.forEach(ipBan -> bannedIps.put(ipBan.ip(), ipBan.accountId())); } public synchronized boolean isBanned(String ip) { - return bannedIps.contains(ip); + return bannedIps.containsKey(ip); } public synchronized void banIp(String ip, int accountId) { @@ -38,8 +40,24 @@ public class IpBanManager { } // TODO: validate ip format. Or create "Ip" model class. - bannedIps.add(ip); - ipBanRepository.saveIpBan(accountId, ip); + bannedIps.put(ip, accountId); + ipBanRepository.saveIpBan(ip, accountId); + } + + public synchronized void unbanAccountIps(int accountId) { + Set ipsToUnban = new HashSet<>(); + for (Map.Entry bannedIp : bannedIps.entrySet()) { + if (bannedIp.getValue() == accountId) { + ipsToUnban.add(bannedIp.getKey()); + } + } + + ipsToUnban.forEach(this::unbanIp); + } + + private void unbanIp(String ip) { + bannedIps.remove(ip); + ipBanRepository.deleteIpBan(ip); } } diff --git a/src/main/java/service/AccountService.java b/src/main/java/service/AccountService.java index 818d77c597..41015c5ad8 100644 --- a/src/main/java/service/AccountService.java +++ b/src/main/java/service/AccountService.java @@ -317,7 +317,11 @@ public class AccountService { } public boolean ban(int accountId, Instant bannedUntil, byte banReason, String description) { - return accountRepository.setBanned(accountId, bannedUntil, banReason, description); + return accountRepository.setBanned(accountId, true, bannedUntil, banReason, description); + } + + public boolean unban(int accountId) { + return accountRepository.setBanned(accountId, false, null, null, null); } } diff --git a/src/main/java/service/BanService.java b/src/main/java/service/BanService.java index f529d4f54e..8ca49ae68d 100644 --- a/src/main/java/service/BanService.java +++ b/src/main/java/service/BanService.java @@ -173,6 +173,20 @@ public class BanService { hwidBanManager.banHwid(hwid, accountId); } + public boolean unban(String chrName) { + Optional foundAccount = accountService.getAccountIdByChrName(chrName); + if (foundAccount.isEmpty()) { + return false; + } + + int accountId = foundAccount.get().id(); + accountService.unban(accountId); + ipBanManager.unbanAccountIps(accountId); +// macBanManager.unbanAccountMacs(accountId); +// hwidBanManager.unbanAccountHwids(accountId); + return true; + } + public boolean isBanned(Client c) { return isIpBanned(c) || isHwidBanned(c) || isMacBanned(c); } diff --git a/src/main/resources/db/migration/postgresql/V0.10__ban.sql b/src/main/resources/db/migration/postgresql/V0.10__ban.sql index b5fefc4b34..d4f698f1d8 100644 --- a/src/main/resources/db/migration/postgresql/V0.10__ban.sql +++ b/src/main/resources/db/migration/postgresql/V0.10__ban.sql @@ -5,7 +5,7 @@ CREATE TABLE ip_ban created_at timestamp DEFAULT now() NOT NULL, PRIMARY KEY (ip) ); -GRANT SELECT, INSERT ON TABLE ip_ban TO ${server-username}; +GRANT SELECT, INSERT, DELETE ON TABLE ip_ban TO ${server-username}; CREATE TABLE hwid_ban ( @@ -14,7 +14,7 @@ CREATE TABLE hwid_ban created_at timestamp DEFAULT now() NOT NULL, PRIMARY KEY (hwid) ); -GRANT SELECT, INSERT ON TABLE hwid_ban TO ${server-username}; +GRANT SELECT, INSERT, DELETE ON TABLE hwid_ban TO ${server-username}; CREATE TABLE mac_ban ( @@ -23,4 +23,4 @@ account_id integer, created_at timestamp DEFAULT now() NOT NULL, PRIMARY KEY (mac) ); -GRANT SELECT, INSERT ON TABLE mac_ban TO ${server-username}; +GRANT SELECT, INSERT, DELETE ON TABLE mac_ban TO ${server-username}; diff --git a/src/test/java/server/ban/IpBanManagerTest.java b/src/test/java/server/ban/IpBanManagerTest.java index 2e22c3e093..8a941812b9 100644 --- a/src/test/java/server/ban/IpBanManagerTest.java +++ b/src/test/java/server/ban/IpBanManagerTest.java @@ -37,7 +37,7 @@ class IpBanManagerTest extends DatabaseTest { ipBanManager.loadIpBans(); assertFalse(ipBanManager.isBanned(ip)); - ipBanRepository.saveIpBan(AnyValues.integer(), ip); + ipBanRepository.saveIpBan(ip, AnyValues.integer()); ipBanManager.loadIpBans(); assertTrue(ipBanManager.isBanned(ip));