Handle ban solely through BanService

This commit is contained in:
P0nk
2024-09-29 20:22:27 +02:00
parent c0ee1f8ffe
commit e35060da2a
9 changed files with 78 additions and 113 deletions

View File

@@ -736,18 +736,6 @@ public class Character extends AbstractCharacterObject {
visibleMapObjects.add(mo); visibleMapObjects.add(mo);
} }
public void ban(String reason) {
setBanned();
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE accounts SET banned = 1, banreason = ? WHERE id = ?")) {
ps.setString(1, reason);
ps.setInt(2, accountid);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static boolean ban(String id, String reason, boolean accountId) { public static boolean ban(String id, String reason, boolean accountId) {
try (Connection con = DatabaseConnection.getConnection()) { try (Connection con = DatabaseConnection.getConnection()) {
if (id.matches("/[0-9]{1,3}\\..*")) { if (id.matches("/[0-9]{1,3}\\..*")) {

View File

@@ -3,15 +3,17 @@ package client.command;
import database.character.CharacterSaver; import database.character.CharacterSaver;
import database.drop.DropProvider; import database.drop.DropProvider;
import server.shop.ShopFactory; import server.shop.ShopFactory;
import service.BanService;
import service.TransitionService; import service.TransitionService;
/** /**
* @author Ponk * @author Ponk
*/ */
public record CommandContext(CommandsExecutor commandsExecutor, DropProvider dropProvider, ShopFactory shopFactory, public record CommandContext(CommandsExecutor commandsExecutor, DropProvider dropProvider, ShopFactory shopFactory,
CharacterSaver characterSaver, TransitionService transitionService) { CharacterSaver characterSaver, TransitionService transitionService, BanService banService
) {
public CommandContext with(CommandsExecutor ce) { public CommandContext with(CommandsExecutor ce) {
return new CommandContext(ce, this.dropProvider, this.shopFactory, this.characterSaver, this.transitionService); return new CommandContext(ce, dropProvider, shopFactory, characterSaver, transitionService, banService);
} }
} }

View File

@@ -27,15 +27,6 @@ import client.Character;
import client.Client; import client.Client;
import client.command.Command; import client.command.Command;
import client.command.CommandContext; import client.command.CommandContext;
import net.server.Server;
import server.TimerManager;
import tools.DatabaseConnection;
import tools.PacketCreator;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
public class BanCommand extends Command { public class BanCommand extends Command {
{ {
@@ -51,42 +42,6 @@ public class BanCommand extends Command {
} }
String ign = params[0]; String ign = params[0];
String reason = joinStringFrom(params, 1); String reason = joinStringFrom(params, 1);
Character target = c.getChannelServer().getPlayerStorage().getCharacterByName(ign); ctx.banService().permaBan(c, ign, (byte) 0, reason);
if (target != null) {
String readableTargetName = Character.makeMapleReadable(target.getName());
String ip = target.getClient().getRemoteAddress();
//Ban ip
try (Connection con = DatabaseConnection.getConnection()) {
if (ip.matches("/[0-9]{1,3}\\..*")) {
try (PreparedStatement ps = con.prepareStatement("INSERT INTO ipbans VALUES (DEFAULT, ?, ?)")) {
ps.setString(1, ip);
ps.setString(2, String.valueOf(target.getClient().getAccID()));
ps.executeUpdate();
}
}
} catch (SQLException ex) {
ex.printStackTrace();
c.getPlayer().message("Error occured while banning IP address");
c.getPlayer().message(target.getName() + "'s IP was not banned: " + ip);
}
target.getClient().banMacs();
reason = c.getPlayer().getName() + " banned " + readableTargetName + " for " + reason + " (IP: " + ip + ") " + "(MAC: " + c.getMacs() + ")";
target.ban(reason);
target.yellowMessage("You have been banned by #b" + c.getPlayer().getName() + " #k.");
target.yellowMessage("Reason: " + reason);
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
final Character rip = target;
TimerManager.getInstance().schedule(
() -> ctx.transitionService().disconnect(rip.getClient(), false),
TimeUnit.SECONDS.toMillis(5)
);
Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned."));
} else if (Character.ban(ign, reason, false)) {
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned."));
} else {
c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1));
}
} }
} }

View File

@@ -45,7 +45,7 @@ public class AccountRepository {
} }
} }
public Optional<Account> findIdByChrNameIgnoreCase(String name) { public Optional<Integer> findIdByChrNameIgnoreCase(String name) {
String sql = """ String sql = """
SELECT id SELECT id
FROM account AS a FROM account AS a
@@ -54,7 +54,7 @@ public class AccountRepository {
try (Handle handle = connection.getHandle()) { try (Handle handle = connection.getHandle()) {
return handle.createQuery(sql) return handle.createQuery(sql)
.bind("name", name) .bind("name", name)
.mapTo(Account.class) .mapTo(Integer.class)
.findOne(); .findOne();
} }
} }

View File

@@ -417,8 +417,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.SCRIPTED_ITEM, new ScriptedItemHandler()); registerHandler(RecvOpcode.SCRIPTED_ITEM, new ScriptedItemHandler());
registerHandler(RecvOpcode.TOUCHING_REACTOR, new TouchReactorHandler()); registerHandler(RecvOpcode.TOUCHING_REACTOR, new TouchReactorHandler());
registerHandler(RecvOpcode.BEHOLDER, new BeholderHandler()); registerHandler(RecvOpcode.BEHOLDER, new BeholderHandler());
registerHandler(RecvOpcode.ADMIN_COMMAND, new AdminCommandHandler(channelDeps.accountService(), registerHandler(RecvOpcode.ADMIN_COMMAND, new AdminCommandHandler(channelDeps.banService()));
channelDeps.transitionService()));
registerHandler(RecvOpcode.ADMIN_LOG, new AdminLogHandler()); registerHandler(RecvOpcode.ADMIN_LOG, new AdminLogHandler());
registerHandler(RecvOpcode.ALLIANCE_OPERATION, new AllianceOperationHandler()); registerHandler(RecvOpcode.ALLIANCE_OPERATION, new AllianceOperationHandler());
registerHandler(RecvOpcode.DENY_ALLIANCE_REQUEST, new DenyAllianceRequestHandler()); registerHandler(RecvOpcode.DENY_ALLIANCE_REQUEST, new DenyAllianceRequestHandler());

View File

@@ -829,6 +829,7 @@ public class Server {
NoteService noteService = new NoteService(new NoteDao(connection)); NoteService noteService = new NoteService(new NoteDao(connection));
DropProvider dropProvider = new DropProvider(new DropRepository(connection)); DropProvider dropProvider = new DropProvider(new DropRepository(connection));
ShopFactory shopFactory = new ShopFactory(new ShopDao(connection)); ShopFactory shopFactory = new ShopFactory(new ShopDao(connection));
BanService banService = new BanService(accountService, transitionService);
ChannelDependencies channelDependencies = ChannelDependencies.builder() ChannelDependencies channelDependencies = ChannelDependencies.builder()
.accountService(accountService) .accountService(accountService)
.characterCreator(new CharacterCreator(connection, characterRepository)) .characterCreator(new CharacterCreator(connection, characterRepository))
@@ -839,10 +840,10 @@ public class Server {
.makerProcessor(new MakerProcessor(new MakerInfoProvider(new MakerRepository(connection)))) .makerProcessor(new MakerProcessor(new MakerInfoProvider(new MakerRepository(connection))))
.dropProvider(dropProvider) .dropProvider(dropProvider)
.commandsExecutor(new CommandsExecutor(new CommandContext(null, dropProvider, shopFactory, .commandsExecutor(new CommandsExecutor(new CommandContext(null, dropProvider, shopFactory,
characterSaver, transitionService))) characterSaver, transitionService, banService)))
.shopFactory(shopFactory) .shopFactory(shopFactory)
.transitionService(transitionService) .transitionService(transitionService)
.banService(new BanService(transitionService)) .banService(banService)
.build(); .build();
PacketProcessor.registerGameHandlerDependencies(channelDependencies); PacketProcessor.registerGameHandlerDependencies(channelDependencies);

View File

@@ -30,31 +30,26 @@ import lombok.extern.slf4j.Slf4j;
import net.AbstractPacketHandler; import net.AbstractPacketHandler;
import net.packet.InPacket; import net.packet.InPacket;
import server.ItemInformationProvider; import server.ItemInformationProvider;
import server.TimerManager;
import server.life.LifeFactory; import server.life.LifeFactory;
import server.life.Monster; import server.life.Monster;
import server.maps.MapObject; import server.maps.MapObject;
import server.maps.MapObjectType; import server.maps.MapObjectType;
import server.quest.Quest; import server.quest.Quest;
import service.AccountService; import service.BanService;
import service.TransitionService;
import tools.PacketCreator; import tools.PacketCreator;
import tools.Randomizer; import tools.Randomizer;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
public final class AdminCommandHandler extends AbstractPacketHandler { public final class AdminCommandHandler extends AbstractPacketHandler {
private final AccountService accountService; private final BanService banService;
private final TransitionService transitionService;
public AdminCommandHandler(AccountService accountService, TransitionService transitionService) { public AdminCommandHandler(BanService banService) {
this.accountService = accountService; this.banService = banService;
this.transitionService = transitionService;
} }
@Override @Override
@@ -178,34 +173,13 @@ public final class AdminCommandHandler extends AbstractPacketHandler {
private void handleBlock(InPacket p, Client c) { private void handleBlock(InPacket p, Client c) {
String victimName = p.readString(); String victimName = p.readString();
byte reason = p.readByte(); byte reason = p.readByte();
int duration = p.readInt(); int durationDays = p.readInt();
String description = p.readString(); String description = p.readString();
Character victim = c.getChannelServer().getPlayerStorage().getCharacterByName(victimName);
if (victim != null) {
banOnlineChr(c, victim, reason, duration, description);
} else if (Character.ban(victimName, c.getPlayer().getName() + " used /ban to ban", false)) { // TODO: find account id from chr name and ban
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
} else {
c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1));
}
}
private void banOnlineChr(Client c, Character victim, byte reason, int durationDays, String description) {
victim.setBanned();
String readableTargetName = Character.makeMapleReadable(victim.getName());
String ip = victim.getClient().getRemoteAddress();
description += readableTargetName + " (IP: " + ip + ")";
int accountId = victim.getAccountID();
if (durationDays == -1) { if (durationDays == -1) {
accountService.permaBan(accountId, reason, description); banService.permaBan(c, victimName, reason, description);
} else { } else {
Duration duration = Duration.ofDays(durationDays); Duration duration = Duration.ofDays(durationDays);
accountService.tempBan(accountId, duration, reason, description); banService.tempBan(c, victimName, duration, reason, description);
} }
victim.setBanned();
victim.sendPacket(PacketCreator.sendPolice(String.format("You have been blocked by the#b %s Police.#k", "Cosmic")));
TimerManager.getInstance().schedule(() -> transitionService.disconnect(c, false),
TimeUnit.SECONDS.toMillis(6));
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
} }
} }

View File

@@ -17,7 +17,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Optional; import java.util.Optional;
@@ -90,7 +89,7 @@ public class AccountService {
return accountRepository.findById(accountId); return accountRepository.findById(accountId);
} }
public Optional<Account> getAccountIdByChrName(String chrName) { public Optional<Integer> getAccountIdByChrName(String chrName) {
return accountRepository.findIdByChrNameIgnoreCase(chrName); return accountRepository.findIdByChrNameIgnoreCase(chrName);
} }
@@ -302,13 +301,8 @@ public class AccountService {
} }
} }
public void permaBan(int accountId, byte banReason, String description) { public boolean ban(int accountId, Instant bannedUntil, byte banReason, String description) {
accountRepository.setBanned(accountId, null, banReason, description); return accountRepository.setBanned(accountId, bannedUntil, banReason, description);
}
public void tempBan(int accountId, Duration duration, byte banReason, String description) {
Instant bannedUntil = Instant.now().plus(duration);
accountRepository.setBanned(accountId, bannedUntil, banReason, description);
} }
} }

View File

@@ -1,22 +1,27 @@
package service; package service;
import client.Character; import client.Character;
import client.Client;
import client.autoban.AutobanFactory; import client.autoban.AutobanFactory;
import config.YamlConfig; import config.YamlConfig;
import lombok.extern.slf4j.Slf4j;
import net.packet.Packet; import net.packet.Packet;
import net.server.Server; import net.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import server.TimerManager; import server.TimerManager;
import tools.PacketCreator; import tools.PacketCreator;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Slf4j
public class BanService { public class BanService {
private static final Logger log = LoggerFactory.getLogger(BanService.class); private final AccountService accountService;
private final TransitionService transitionService; private final TransitionService transitionService;
public BanService(TransitionService transitionService) { public BanService(AccountService accountService, TransitionService transitionService) {
this.accountService = accountService;
this.transitionService = transitionService; this.transitionService = transitionService;
} }
@@ -29,7 +34,8 @@ public class BanService {
return; return;
} }
chr.ban(reason); chr.setBanned();
accountService.ban(chr.getAccountID(), null, (byte) 0, reason);
chr.sendPacket(PacketCreator.sendPolice("You have been blocked by the#b %s Police for HACK reason.#k".formatted("Cosmic"))); chr.sendPacket(PacketCreator.sendPolice("You have been blocked by the#b %s Police for HACK reason.#k".formatted("Cosmic")));
TimerManager.getInstance().schedule(() -> transitionService.disconnect(chr.getClient(), false), TimerManager.getInstance().schedule(() -> transitionService.disconnect(chr.getClient(), false),
@@ -59,4 +65,50 @@ public class BanService {
private boolean isExempt(Character chr) { private boolean isExempt(Character chr) {
return !YamlConfig.config.server.USE_AUTOBAN || chr.isGM() || chr.isBanned(); return !YamlConfig.config.server.USE_AUTOBAN || chr.isGM() || chr.isBanned();
} }
public void permaBan(Client c, String victimName, byte reason, String description) {
ban(c, victimName, null, reason, description);
}
public void tempBan(Client c, String victimName, Duration duration, byte reason, String description) {
ban(c, victimName, duration, reason, description);
}
// TODO: also ban ip and macs. Table "ipbans" and "macbans" (while taking "macfilters" into consideration).
// That's how it was done previously, anyway.
private void ban(Client c, String victimName, Duration duration, byte reason, String description) {
Character victim = c.getChannelServer().getPlayerStorage().getCharacterByName(victimName);
if (victim == null) {
Optional<Integer> foundAccountId = accountService.getAccountIdByChrName(victimName);
if (foundAccountId.isEmpty()) {
c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1));
return;
}
saveBan(foundAccountId.get(), duration, reason, description);
} else {
victim.setBanned();
String readableName = Character.makeMapleReadable(victimName);
String ip = victim.getClient().getRemoteAddress();
String enrichedDescription = "[%s] %s (IP: %s)".formatted(description, readableName, ip);
saveBan(victim.getAccountID(), duration, reason, enrichedDescription);
victim.sendPacket(PacketCreator.sendPolice("You have been banned by %s.".formatted(c.getPlayer().getName())));
TimerManager.getInstance().schedule(() -> transitionService.disconnect(c, false),
TimeUnit.SECONDS.toMillis(5));
}
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "%s has been banned.".formatted(victimName)));
}
private void saveBan(int accountId, Duration duration, byte reason, String description) {
final Instant bannedUntil;
if (duration != null) {
bannedUntil = Instant.now().plus(duration);
} else {
bannedUntil = null;
}
accountService.ban(accountId, bannedUntil, reason, description);
}
} }