Save accepted ToS to PG

This commit is contained in:
P0nk
2024-09-26 21:13:40 +02:00
parent c7f835da0d
commit 0f2ef341ce
8 changed files with 136 additions and 49 deletions

View File

@@ -54,14 +54,10 @@ import server.TimerManager;
import server.life.Monster; import server.life.Monster;
import tools.BCrypt; import tools.BCrypt;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.HexTool;
import tools.PacketCreator; import tools.PacketCreator;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -894,35 +890,6 @@ public class Client extends ChannelInboundHandlerAdapter {
return QuestScriptManager.getInstance().getQM(this); return QuestScriptManager.getInstance().getQM(this);
} }
public boolean acceptToS() {
if (accountName == null) {
return true;
}
boolean disconnect = false;
try (Connection con = DatabaseConnection.getConnection()) {
try (PreparedStatement ps = con.prepareStatement("SELECT `tos` FROM accounts WHERE id = ?")) {
ps.setInt(1, accId);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
if (rs.getByte("tos") == 1) {
disconnect = true;
}
}
}
}
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET tos = 1 WHERE id = ?")) {
ps.setInt(1, accId);
ps.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
return disconnect;
}
public void lockClient() { public void lockClient() {
lock.lock(); lock.lock();
} }
@@ -945,16 +912,6 @@ public class Client extends ChannelInboundHandlerAdapter {
actionsSemaphore.release(); actionsSemaphore.release();
} }
private static boolean checkHash(String hash, String type, String password) {
try {
MessageDigest digester = MessageDigest.getInstance(type);
digester.update(password.getBytes(StandardCharsets.UTF_8), 0, password.length());
return HexTool.toHexString(digester.digest()).replace(" ", "").toLowerCase().equals(hash);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Encoding the string failed", e);
}
}
public short getAvailableCharacterSlots() { public short getAvailableCharacterSlots() {
return (short) Math.max(0, characterSlots - Server.getInstance().getAccountCharacterCount(accId)); return (short) Math.max(0, characterSlots - Server.getInstance().getAccountCharacterCount(accId));
} }

View File

@@ -1,5 +1,6 @@
package database; package database;
import database.account.AccountRowMapper;
import database.drop.GlobalMonsterDropRowMapper; import database.drop.GlobalMonsterDropRowMapper;
import database.drop.MonsterDropRowMapper; import database.drop.MonsterDropRowMapper;
import database.maker.MakerIngredientRowMapper; import database.maker.MakerIngredientRowMapper;
@@ -26,6 +27,7 @@ public final class JdbiConfig {
private static List<RowMapper<?>> rowMappers() { private static List<RowMapper<?>> rowMappers() {
return List.of( return List.of(
new AccountRowMapper(),
new NoteRowMapper(), new NoteRowMapper(),
new MakerReagentRowMapper(), new MakerReagentRowMapper(),
new MakerRecipeRowMapper(), new MakerRecipeRowMapper(),

View File

@@ -3,8 +3,12 @@ package database.account;
import lombok.Builder; import lombok.Builder;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* @author Ponk
*/
@Builder @Builder
public record Account(String name, String password, boolean acceptedTos, LocalDate birthdate, String pin, String pic, public record Account(int id, String name, String password, boolean acceptedTos, byte gender, LocalDate birthdate,
int loggedIn) { String pin, String pic, int chrSlots, int loggedIn, LocalDateTime lastLogin, boolean banned) {
} }

View File

@@ -3,6 +3,11 @@ package database.account;
import database.PgDatabaseConnection; import database.PgDatabaseConnection;
import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.Handle;
import java.util.Optional;
/**
* @author Ponk
*/
public class AccountRepository { public class AccountRepository {
private final PgDatabaseConnection connection; private final PgDatabaseConnection connection;
@@ -10,8 +15,17 @@ public class AccountRepository {
this.connection = connection; this.connection = connection;
} }
public Account getByName(String name) { public Optional<Account> findById(int accountId) {
return null; // TODO String sql = """
SELECT id, name, password, pin, pic, logged_in, last_login, birthdate, banned, gender, tos_accepted
FROM account
WHERE id = :id""";
try (Handle handle = connection.getHandle()) {
return handle.createQuery(sql)
.bind("id", accountId)
.mapTo(Account.class)
.findOne();
}
} }
public Integer insert(Account account) { public Integer insert(Account account) {
@@ -28,4 +42,17 @@ public class AccountRepository {
.one(); .one();
} }
} }
public void setTos(int accountId, boolean acceptedTos) {
String sql = """
UPDATE account
SET tos_accepted = :acceptedTos
WHERE id = :id""";
try (Handle handle = connection.getHandle()) {
handle.createUpdate(sql)
.bind("id", accountId)
.bind("acceptedTos", acceptedTos)
.execute();
}
}
} }

View File

@@ -0,0 +1,34 @@
package database.account;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.core.statement.StatementContext;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Optional;
/**
* @author Ponk
*/
public class AccountRowMapper implements RowMapper<Account> {
@Override
public Account map(ResultSet rs, StatementContext ctx) throws SQLException {
return Account.builder()
.id(rs.getInt("id"))
.name(rs.getString("name"))
.password(rs.getString("password"))
.pin(rs.getString("pin"))
.pic(rs.getString("pic"))
.loggedIn(rs.getInt("logged_in"))
.lastLogin(Optional.ofNullable(rs.getTimestamp("last_login"))
.map(Timestamp::toLocalDateTime)
.orElse(null))
.birthdate(rs.getDate("birthdate").toLocalDate())
.banned(rs.getBoolean("banned"))
.gender(rs.getByte("gender"))
.acceptedTos(rs.getBoolean("tos_accepted"))
.build();
}
}

View File

@@ -276,7 +276,7 @@ public final class PacketProcessor {
} }
private void registerLoginHandlers() { private void registerLoginHandlers() {
registerHandler(RecvOpcode.ACCEPT_TOS, new AcceptToSHandler()); registerHandler(RecvOpcode.ACCEPT_TOS, new AcceptToSHandler(channelDeps.accountService()));
registerHandler(RecvOpcode.AFTER_LOGIN, new AfterLoginHandler()); registerHandler(RecvOpcode.AFTER_LOGIN, new AfterLoginHandler());
registerHandler(RecvOpcode.SERVERLIST_REREQUEST, new ServerlistRequestHandler()); registerHandler(RecvOpcode.SERVERLIST_REREQUEST, new ServerlistRequestHandler());
registerHandler(RecvOpcode.CHARLIST_REQUEST, new CharlistRequestHandler()); registerHandler(RecvOpcode.CHARLIST_REQUEST, new CharlistRequestHandler());

View File

@@ -4,12 +4,19 @@ import client.Client;
import net.AbstractPacketHandler; import net.AbstractPacketHandler;
import net.netty.GameViolationException; import net.netty.GameViolationException;
import net.packet.InPacket; import net.packet.InPacket;
import service.AccountService;
import tools.PacketCreator; import tools.PacketCreator;
/** /**
* @author kevintjuh93 * @author kevintjuh93
* @author Ponk
*/ */
public final class AcceptToSHandler extends AbstractPacketHandler { public final class AcceptToSHandler extends AbstractPacketHandler {
private final AccountService accountService;
public AcceptToSHandler(final AccountService accountService) {
this.accountService = accountService;
}
@Override @Override
public boolean validateState(Client c) { public boolean validateState(Client c) {
@@ -18,7 +25,7 @@ public final class AcceptToSHandler extends AbstractPacketHandler {
@Override @Override
public void handlePacket(InPacket p, Client c) { public void handlePacket(InPacket p, Client c) {
if (p.available() == 0 || p.readByte() != 1 || c.acceptToS()) { if (p.available() == 0 || p.readByte() != 1 || !accountService.acceptTos(c.getAccID())) {
throw new GameViolationException("ToS not accepted"); throw new GameViolationException("ToS not accepted");
} }

View File

@@ -4,10 +4,18 @@ import database.account.Account;
import database.account.AccountRepository; import database.account.AccountRepository;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import tools.BCrypt; import tools.BCrypt;
import tools.DatabaseConnection;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Optional; import java.util.Optional;
/**
* @author Ponk
*/
@Slf4j @Slf4j
public class AccountService { public class AccountService {
private static final int PASSWORD_HASH_SALT_LOG_ROUNDS = 12; private static final int PASSWORD_HASH_SALT_LOG_ROUNDS = 12;
@@ -41,4 +49,52 @@ public class AccountService {
private String hashPassword(String password) { private String hashPassword(String password) {
return BCrypt.hashpw(password, BCrypt.gensalt(PASSWORD_HASH_SALT_LOG_ROUNDS)); return BCrypt.hashpw(password, BCrypt.gensalt(PASSWORD_HASH_SALT_LOG_ROUNDS));
} }
public Optional<Account> getAccount(int accountId) {
return accountRepository.findById(accountId);
}
public boolean acceptTos(int accountId) {
acceptTosMysql(accountId);
acceptTosPostgres(accountId);
return true;
}
private boolean acceptTosMysql(int accountId) {
try (Connection con = DatabaseConnection.getConnection()) {
try (PreparedStatement ps = con.prepareStatement("SELECT `tos` FROM accounts WHERE id = ?")) {
ps.setInt(1, accountId);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
if (rs.getByte("tos") == 1) {
return false;
}
}
}
}
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET tos = 1 WHERE id = ?")) {
ps.setInt(1, accountId);
ps.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}
private boolean acceptTosPostgres(int accountId) {
Optional<Account> account = getAccount(accountId);
if (account.isEmpty()) {
return false;
}
if (account.get().acceptedTos()) {
return false;
}
accountRepository.setTos(accountId, true);
return true;
}
} }