From edd255e29db8ae36f646591f1a92a9c166fd2dc1 Mon Sep 17 00:00:00 2001 From: Dawson Date: Thu, 5 Jun 2025 11:35:15 -0400 Subject: [PATCH] Added mongodb and option to remove spoiled cached responses --- .../brighten/antivpn/bukkit/BukkitPlugin.java | 4 +- .../brighten/antivpn/bungee/BungeePlugin.java | 4 +- Common/pom.xml | 10 +- .../java/dev/brighten/antivpn/AntiVPN.java | 10 +- .../brighten/antivpn/database/Database.java | 39 +++ .../antivpn/database/VPNDatabase.java | 88 ------- .../database/mongodb/MongoDatabase.java | 229 ++++++++++++++++++ .../database/mongodb/records/AlertsUser.java | 6 + .../mongodb/records/CidrWhitelist.java | 6 + .../mongodb/records/UserIpResponse.java | 13 + .../mongodb/records/UserWhitelist.java | 6 + .../database/sqllite/LiteDatabase.java | 58 ++++- .../database/sqllite/version/Version.java | 4 +- .../database/sqllite/version/impl/First.java | 18 +- .../antivpn/velocity/VelocityPlugin.java | 4 +- 15 files changed, 390 insertions(+), 109 deletions(-) create mode 100644 Common/src/main/java/dev/brighten/antivpn/database/Database.java delete mode 100644 Common/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java create mode 100644 Common/src/main/java/dev/brighten/antivpn/database/mongodb/MongoDatabase.java create mode 100644 Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/AlertsUser.java create mode 100644 Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/CidrWhitelist.java create mode 100644 Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserIpResponse.java create mode 100644 Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserWhitelist.java diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java b/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java index 72e9852..dfce1b9 100644 --- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java +++ b/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java @@ -3,7 +3,7 @@ package dev.brighten.antivpn.bukkit; import dev.brighten.antivpn.AntiVPN; import dev.brighten.antivpn.bukkit.command.BukkitCommand; import dev.brighten.antivpn.command.Command; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.Database; import dev.brighten.antivpn.database.sqllite.LiteDatabase; import lombok.Getter; import org.bstats.bukkit.Metrics; @@ -114,7 +114,7 @@ public class BukkitPlugin extends JavaPlugin { } private String getDatabaseType() { - VPNDatabase database = AntiVPN.getInstance().getDatabase(); + Database database = AntiVPN.getInstance().getDatabase(); if(database instanceof LiteDatabase) { return "SQLLite"; diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java index c435bfd..c8672b7 100644 --- a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java +++ b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java @@ -3,7 +3,7 @@ package dev.brighten.antivpn.bungee; import dev.brighten.antivpn.AntiVPN; import dev.brighten.antivpn.bungee.command.BungeeCommand; import dev.brighten.antivpn.command.Command; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.Database; import dev.brighten.antivpn.database.sqllite.LiteDatabase; import net.md_5.bungee.api.plugin.Plugin; import org.bstats.bungeecord.Metrics; @@ -47,7 +47,7 @@ public class BungeePlugin extends Plugin { } private String getDatabaseType() { - VPNDatabase database = AntiVPN.getInstance().getDatabase(); + Database database = AntiVPN.getInstance().getDatabase(); if(database instanceof LiteDatabase) { return "SQLLite"; diff --git a/Common/pom.xml b/Common/pom.xml index 618aebb..cca88e4 100644 --- a/Common/pom.xml +++ b/Common/pom.xml @@ -80,8 +80,8 @@ - com.mongodb - dev.brighten.antivpn.shaded.com.mongodb + com.mongodb.client + dev.brighten.antivpn.shaded.com.mongodb.client dev.brighten.antivpn.depends.Relocate @@ -154,6 +154,12 @@ annotations 24.0.1 + + org.mongodb + mongodb-driver-sync + 5.5.0 + provided + org.postgresql postgresql diff --git a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java b/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java index b663865..fca642e 100644 --- a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java +++ b/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java @@ -5,7 +5,8 @@ import dev.brighten.antivpn.api.VPNConfig; import dev.brighten.antivpn.api.VPNExecutor; import dev.brighten.antivpn.command.Command; import dev.brighten.antivpn.command.impl.AntiVPNCommand; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.Database; +import dev.brighten.antivpn.database.mongodb.MongoDatabase; import dev.brighten.antivpn.database.postgres.PostgresDatabase; import dev.brighten.antivpn.database.sqllite.LiteDatabase; import dev.brighten.antivpn.database.sqllite.version.Version; @@ -42,13 +43,17 @@ import java.util.List; relocations = { @Relocate(from = "org\\.postgresql", to = "dev.brighten.antivpn.shaded.org.postgresql") }) +@MavenLibrary(groupId = "com\\.mongodb", artifactId = "driver-sync", version = "5.5.0", + relocations = { + @Relocate(from = "com\\.mongodb.client", to = "dev.brighten.antivpn.shaded.com.mongodb.client") + }) public class AntiVPN { private static AntiVPN INSTANCE; private VPNConfig vpnConfig; private VPNExecutor executor; private PlayerExecutor playerExecutor; - private VPNDatabase database; + private Database database; private MessageHandler messageHandler; private Configuration config; private List commands = new ArrayList<>(); @@ -94,6 +99,7 @@ public class AntiVPN { INSTANCE.database = switch (INSTANCE.vpnConfig.getDatabaseType().toLowerCase()) { case "sqlite", "sqllite" -> new LiteDatabase(); case "postgresql", "postgres" -> new PostgresDatabase(); + case "mongo", "mongodb" -> new MongoDatabase(); default -> throw new IllegalStateException("Unexpected database type set at config.yml 'database.type': \"" + INSTANCE.vpnConfig.getDatabaseType().toLowerCase() + "\"!" + diff --git a/Common/src/main/java/dev/brighten/antivpn/database/Database.java b/Common/src/main/java/dev/brighten/antivpn/database/Database.java new file mode 100644 index 0000000..3d5514a --- /dev/null +++ b/Common/src/main/java/dev/brighten/antivpn/database/Database.java @@ -0,0 +1,39 @@ +package dev.brighten.antivpn.database; + +import dev.brighten.antivpn.web.objects.VPNResponse; + +import java.util.Optional; +import java.util.UUID; + +@SuppressWarnings({"unused"}) +public interface Database { + Optional getStoredResponse(String ip); + + void cacheResponse(VPNResponse toCache); + + void deleteResponse(String ip); + + void clearResponses(); + + void clearOutdatedResponses(); + + boolean isWhitelisted(UUID uuid); + + boolean isWhitelisted(String ip); + + void addWhitelist(UUID uuid); + + void addWhitelist(String cidr); + + void removeWhitelist(UUID uuid); + + void removeWhitelist(String cidr); + + boolean getAlertsState(UUID uuid); + + void updateAlertsState(UUID uuid, boolean state); + + void init(); + + void shutdown(); +} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java b/Common/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java deleted file mode 100644 index b2378d6..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java +++ /dev/null @@ -1,88 +0,0 @@ -package dev.brighten.antivpn.database; - -import dev.brighten.antivpn.AntiVPN; -import dev.brighten.antivpn.database.sqllite.version.Version; -import dev.brighten.antivpn.web.objects.VPNResponse; -import org.intellij.lang.annotations.Language; - -import java.sql.*; -import java.util.Optional; -import java.util.UUID; - -@SuppressWarnings({"unused", "SqlSourceToSinkFlow"}) -public interface VPNDatabase { - Optional getStoredResponse(String ip); - - void cacheResponse(VPNResponse toCache); - - void deleteResponse(String ip); - - void clearResponses(); - - boolean isWhitelisted(UUID uuid); - - boolean isWhitelisted(String ip); - - void addWhitelist(UUID uuid); - - void addWhitelist(String cidr); - - void removeWhitelist(UUID uuid); - - void removeWhitelist(String cidr); - - boolean getAlertsState(UUID uuid); - - void updateAlertsState(UUID uuid, boolean state); - - void init(); - - default void setupTable() throws SQLException { - try(Connection connection = connection()) { - Statement statement = connection.createStatement(); - statement.execute("CREATE TABLE IF NOT EXISTS vpn_responses (ip TEXT, response TEXT)"); - statement.execute("CREATE TABLE IF NOT EXISTS whitelist (uuid TEXT, minimum NUMERIC, maximum NUMERIC)"); - statement.execute("CREATE TABLE IF NOT EXISTS alerts (uuid TEXT)"); - statement.execute("CREATE TABLE IF NOT EXISTS version (version INTEGER PRIMARY KEY, updated BOOLEAN)"); - - // Run through updates - for (Version version : Version.versions) { - try(ResultSet result = query("SELECT * FROM version WHERE version = ?", - version.versionNumber())) { - if(!result.next()) { - version.update(this); - statement("INSERT INTO version (version, updated) VALUES (?, ?)", - version.versionNumber(), true); - } - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - } - } - - default ResultSet query(@Language("SQL") String query, Object... args) throws SQLException { - try(Connection connection = connection()) { - PreparedStatement pstmt = connection.prepareStatement(query); - for (int i = 0; i < args.length; i++) { - pstmt.setObject(i + 1, args[i]); - } - - return pstmt.executeQuery(); - } - } - - default void statement(@Language("SQL") String query, Object... args) throws SQLException { - try(Connection connection = connection()) { - PreparedStatement pstmt = connection.prepareStatement(query); - for (int i = 0; i < args.length; i++) { - pstmt.setObject(i + 1, args[i]); - } - - pstmt.execute(); - } - } - Connection connection(); - - void shutdown(); -} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/MongoDatabase.java b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/MongoDatabase.java new file mode 100644 index 0000000..0cdf156 --- /dev/null +++ b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/MongoDatabase.java @@ -0,0 +1,229 @@ +package dev.brighten.antivpn.database.mongodb; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.UpdateOptions; +import dev.brighten.antivpn.AntiVPN; +import dev.brighten.antivpn.database.Database; +import dev.brighten.antivpn.database.mongodb.records.AlertsUser; +import dev.brighten.antivpn.database.mongodb.records.CidrWhitelist; +import dev.brighten.antivpn.database.mongodb.records.UserIpResponse; +import dev.brighten.antivpn.database.mongodb.records.UserWhitelist; +import dev.brighten.antivpn.utils.CIDRUtils; +import dev.brighten.antivpn.utils.IpUtils; +import dev.brighten.antivpn.utils.json.JSONException; +import dev.brighten.antivpn.web.objects.VPNResponse; +import org.bson.Document; + +import java.math.BigDecimal; +import java.net.UnknownHostException; +import java.util.Date; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +public class MongoDatabase implements Database { + + private MongoCollection alertsCollection; + private MongoCollection cidrWhitelistCollection; + private MongoCollection userWhitelistCollection; + private MongoCollection vpnResponseCollection; + + @Override + public Optional getStoredResponse(String ip) { + UserIpResponse response = vpnResponseCollection.find(Filters.eq("ip", ip)).first(); + + if(response == null) { + return Optional.empty(); + } + + try { + return Optional.of(response.getVpnResponse()); + } catch (JSONException e) { + AntiVPN.getInstance().getExecutor().logException("Could not convert vpn response from JSON String to DTO " + + "for address: " + ip, e); + return Optional.empty(); + } + } + + @Override + public void cacheResponse(VPNResponse toCache) { + try { + UserIpResponse response = new UserIpResponse(toCache.getIp(), new Date(), toCache.toJson().toString()); + + vpnResponseCollection.updateOne(Filters.eq("ip", toCache.getIp()), + new Document("$set", response), + new UpdateOptions().upsert(true)); + } catch (JSONException e) { + AntiVPN.getInstance().getExecutor().log(Level.SEVERE, "An error occurred while caching response", e); + } + } + + @Override + public void deleteResponse(String ip) { + vpnResponseCollection.deleteOne(Filters.eq("ip", ip)); + } + + @Override + public void clearResponses() { + //Clears all documents within the collection + var result = vpnResponseCollection.deleteMany(new Document()); + + AntiVPN.getInstance().getExecutor().log(Level.INFO, "VPN responses have been cleared (count=%s)", result.getDeletedCount()); + } + + @Override + public void clearOutdatedResponses() { + var result = vpnResponseCollection.deleteMany(Filters.lte("date", + new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMicros(7)))); + + AntiVPN.getInstance().getExecutor().log(Level.INFO, "Cleared outdated responses (count=%s)", + result.getDeletedCount()); + } + + @Override + public boolean isWhitelisted(UUID uuid) { + UserWhitelist whitelist = userWhitelistCollection.find(Filters.eq("uuid", uuid)).first(); + + return whitelist != null; + } + + @Override + public boolean isWhitelisted(String ip) { + Optional ipDec = IpUtils.getIpDecimal(ip); + + if(ipDec.isEmpty()) { + AntiVPN.getInstance().getExecutor().log(Level.WARNING, "Could not check for whitelist on IP %s since" + + " it cannot be converted to decimal!", ip); + return false; + } + + BigDecimal decimal = ipDec.get(); + + CidrWhitelist whitelist = cidrWhitelistCollection.find(Filters.and( + Filters.lte("start", decimal), + Filters.gte("end", decimal) + + )).first(); + + return whitelist != null; + } + + @Override + public void addWhitelist(UUID uuid) { + UserWhitelist whitelist = new UserWhitelist(uuid); + + userWhitelistCollection.insertOne(whitelist); + } + + @Override + public void addWhitelist(String cidr) { + try { + var cidrObj = new CIDRUtils(cidr); + + Optional start = IpUtils.getIpDecimal(cidrObj.getStartAddress().getHostAddress()), + end = IpUtils.getIpDecimal(cidrObj.getEndAddress().getHostAddress()); + + if(start.isEmpty() || end.isEmpty()) { + AntiVPN.getInstance().getExecutor().log(Level.WARNING, "Could not whitelist cidr %s since " + + "it is missing either a start or end address", cidr); + return; + } + + CidrWhitelist whitelist = new CidrWhitelist(start.get(), end.get()); + + cidrWhitelistCollection.insertOne(whitelist); + } catch (UnknownHostException e) { + AntiVPN.getInstance().getExecutor().logException("Could not whitelist cidr: " + cidr, e); + } + } + + @Override + public void removeWhitelist(UUID uuid) { + var result = userWhitelistCollection.deleteMany(Filters.eq("uuid", uuid.toString())); + + AntiVPN.getInstance().getExecutor().log(Level.INFO, "Removed whitelist for uuid %s (count=%s)", + uuid, result.getDeletedCount()); + } + + @Override + public void removeWhitelist(String cidr) { + try { + var cidrObj = new CIDRUtils(cidr); + + Optional start = IpUtils.getIpDecimal(cidrObj.getStartAddress().getHostAddress()); + Optional end = IpUtils.getIpDecimal(cidrObj.getEndAddress().getHostAddress()); + + if(start.isEmpty() || end.isEmpty()) { + AntiVPN.getInstance().getExecutor().log(Level.WARNING, "Could not remove cidr %s from whitelist" + + " since it is missing either a start or end address.", cidr); + return; + } + + var result = cidrWhitelistCollection.deleteMany(Filters.and(Filters.eq("start", start.get()), + Filters.eq("end", end.get()))); + + AntiVPN.getInstance().getExecutor().log(Level.INFO, "Removed cidr %s from whitelist (count=%s).", + cidr, result.getDeletedCount()); + } catch (UnknownHostException e) { + AntiVPN.getInstance().getExecutor().logException("Could not remove whitelist for CIDR: " + cidr, e); + } + } + + @Override + public boolean getAlertsState(UUID uuid) { + AlertsUser alertsUser = alertsCollection.find(Filters.eq("uuid", uuid)).first(); + + if(alertsUser == null) { + return false; + } + + return alertsUser.state(); + } + + @Override + public void updateAlertsState(UUID uuid, boolean state) { + alertsCollection.updateOne(Filters.eq("uuid", uuid), + new Document("$set", new AlertsUser(uuid, state)), + new UpdateOptions().upsert(true)); + } + + @Override + public void init() { + String connectionUrl; + if(AntiVPN.getInstance().getVpnConfig().getMongoURL().isEmpty()) { + String databaseName = AntiVPN.getInstance().getVpnConfig().getDatabaseName(); + String username = AntiVPN.getInstance().getVpnConfig().getUsername(); + String password = AntiVPN.getInstance().getVpnConfig().getPassword(); + String ip = AntiVPN.getInstance().getVpnConfig().getIp(); + int port = AntiVPN.getInstance().getVpnConfig().getPort(); + + connectionUrl = String.format("mongodb+srv://" + + "%s:%s>@%s:%s/%s?connectTimeoutMS=2000", + username, password, ip, port, databaseName); + } else { + connectionUrl = AntiVPN.getInstance() + .getVpnConfig().getMongoURL(); + } + + try(MongoClient mongoClient = MongoClients.create(connectionUrl)) { + var database = mongoClient.getDatabase(AntiVPN.getInstance().getVpnConfig().getDatabaseName()); + + userWhitelistCollection = database.getCollection("whitelist", UserWhitelist.class); + cidrWhitelistCollection = database.getCollection("cidrWhitelist", CidrWhitelist.class); + alertsCollection = database.getCollection("alerts", AlertsUser.class); + vpnResponseCollection = database.getCollection("responses", UserIpResponse.class); + } + } + + @Override + public void shutdown() { + userWhitelistCollection = null; + cidrWhitelistCollection = null; + alertsCollection = null; + vpnResponseCollection = null; + } +} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/AlertsUser.java b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/AlertsUser.java new file mode 100644 index 0000000..7fe29f8 --- /dev/null +++ b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/AlertsUser.java @@ -0,0 +1,6 @@ +package dev.brighten.antivpn.database.mongodb.records; + +import java.util.UUID; + +public record AlertsUser(UUID uuid, boolean state) { +} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/CidrWhitelist.java b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/CidrWhitelist.java new file mode 100644 index 0000000..eb24bb5 --- /dev/null +++ b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/CidrWhitelist.java @@ -0,0 +1,6 @@ +package dev.brighten.antivpn.database.mongodb.records; + +import java.math.BigDecimal; + +public record CidrWhitelist(BigDecimal start, BigDecimal end) { +} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserIpResponse.java b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserIpResponse.java new file mode 100644 index 0000000..cc81709 --- /dev/null +++ b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserIpResponse.java @@ -0,0 +1,13 @@ +package dev.brighten.antivpn.database.mongodb.records; + +import dev.brighten.antivpn.utils.json.JSONException; +import dev.brighten.antivpn.web.objects.VPNResponse; + +import java.util.Date; + +public record UserIpResponse(String ip, Date queried, String response) { + + public VPNResponse getVpnResponse() throws JSONException { + return VPNResponse.fromJson(response); + } +} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserWhitelist.java b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserWhitelist.java new file mode 100644 index 0000000..e2e01c4 --- /dev/null +++ b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserWhitelist.java @@ -0,0 +1,6 @@ +package dev.brighten.antivpn.database.mongodb.records; + +import java.util.UUID; + +public record UserWhitelist(UUID uuid) { +} diff --git a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/LiteDatabase.java b/Common/src/main/java/dev/brighten/antivpn/database/sqllite/LiteDatabase.java index 148b5ca..da2e8e7 100644 --- a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/LiteDatabase.java +++ b/Common/src/main/java/dev/brighten/antivpn/database/sqllite/LiteDatabase.java @@ -1,20 +1,23 @@ package dev.brighten.antivpn.database.sqllite; import dev.brighten.antivpn.AntiVPN; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.sqllite.version.Version; import dev.brighten.antivpn.utils.CIDRUtils; import dev.brighten.antivpn.utils.IpUtils; import dev.brighten.antivpn.utils.StringUtil; import dev.brighten.antivpn.utils.json.JSONException; import dev.brighten.antivpn.web.objects.VPNResponse; +import org.intellij.lang.annotations.Language; import java.math.BigDecimal; import java.net.UnknownHostException; import java.sql.*; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.TimeUnit; -public class LiteDatabase implements VPNDatabase { +@SuppressWarnings("SqlSourceToSinkFlow") +public class LiteDatabase implements dev.brighten.antivpn.database.Database { protected Connection connection; @@ -36,7 +39,7 @@ public class LiteDatabase implements VPNDatabase { String hashedIp = StringUtil.getHash(toCache.getIp()); try { - statement("INSERT INTO vpn_responses (ip, response) VALUES (?, ?)", hashedIp, jsonResponse); + statement("INSERT INTO vpn_responses (ip, date, response) VALUES (?, ?, ?)", hashedIp, System.currentTimeMillis(), jsonResponse); } catch (SQLException e) { AntiVPN.getInstance().getExecutor().logException(e); } @@ -63,6 +66,17 @@ public class LiteDatabase implements VPNDatabase { } } + @Override + public void clearOutdatedResponses() { + long cutoffTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7); + + try { + statement("DELETE FROM vpn_responses WHERE date < ?", cutoffTime); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + @Override public boolean isWhitelisted(UUID uuid) { try(ResultSet result = query("SELECT * FROM whitelist WHERE uuid = ?", uuid.toString())) { @@ -194,12 +208,44 @@ public class LiteDatabase implements VPNDatabase { } } - @Override public void setupTable() throws SQLException { - VPNDatabase.super.setupTable(); + // Run through updates + for (Version version : Version.versions) { + try(ResultSet result = query("SELECT * FROM version WHERE version = ?", + version.versionNumber())) { + if(!result.next()) { + version.update(this); + statement("INSERT INTO version (version, updated) VALUES (?, ?)", + version.versionNumber(), true); + } + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor().logException(e); + } + } + } + + protected ResultSet query(@Language("SQL") String query, Object... args) throws SQLException { + try(Connection connection = connection()) { + PreparedStatement pstmt = connection.prepareStatement(query); + for (int i = 0; i < args.length; i++) { + pstmt.setObject(i + 1, args[i]); + } + + return pstmt.executeQuery(); + } + } + + protected void statement(@Language("SQL") String query, Object... args) throws SQLException { + try(Connection connection = connection()) { + PreparedStatement pstmt = connection.prepareStatement(query); + for (int i = 0; i < args.length; i++) { + pstmt.setObject(i + 1, args[i]); + } + + pstmt.execute(); + } } - @Override public Connection connection() { return connection; } diff --git a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/Version.java b/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/Version.java index f01202c..eb0b561 100644 --- a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/Version.java +++ b/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/Version.java @@ -1,6 +1,6 @@ package dev.brighten.antivpn.database.sqllite.version; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.sqllite.LiteDatabase; import dev.brighten.antivpn.database.sqllite.version.impl.First; import java.sql.SQLException; @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; public interface Version { - void update(VPNDatabase database) throws SQLException; + void update(LiteDatabase database) throws SQLException; int versionNumber(); List versions = new ArrayList<>(); diff --git a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/impl/First.java b/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/impl/First.java index fd95bf1..508ad62 100644 --- a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/impl/First.java +++ b/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/impl/First.java @@ -1,13 +1,25 @@ package dev.brighten.antivpn.database.sqllite.version.impl; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.sqllite.LiteDatabase; import dev.brighten.antivpn.database.sqllite.version.Version; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + public class First implements Version { @Override - public void update(VPNDatabase database) { - + public void update(LiteDatabase database) { + try(Connection connection = database.connection()) { + Statement statement = connection.createStatement(); + statement.execute("CREATE TABLE IF NOT EXISTS vpn_responses (ip TEXT, date INTEGER, response TEXT)"); + statement.execute("CREATE TABLE IF NOT EXISTS whitelist (uuid TEXT, minimum NUMERIC, maximum NUMERIC)"); + statement.execute("CREATE TABLE IF NOT EXISTS alerts (uuid TEXT)"); + statement.execute("CREATE TABLE IF NOT EXISTS version (version INTEGER PRIMARY KEY, updated BOOLEAN)"); + } catch (SQLException e) { + throw new RuntimeException(e); + } } @Override diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java index 2252ee9..926b35d 100644 --- a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java +++ b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java @@ -9,7 +9,7 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.ProxyServer; import dev.brighten.antivpn.AntiVPN; import dev.brighten.antivpn.command.Command; -import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.Database; import dev.brighten.antivpn.database.sqllite.LiteDatabase; import dev.brighten.antivpn.velocity.command.VelocityCommand; import lombok.Getter; @@ -84,7 +84,7 @@ public class VelocityPlugin { } private String getDatabaseType() { - VPNDatabase database = AntiVPN.getInstance().getDatabase(); + Database database = AntiVPN.getInstance().getDatabase(); if(database instanceof LiteDatabase) { return "SQLLite";