diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..3c1cd40 --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,67 @@ +name: create-release.yml +on: + workflow_dispatch: +jobs: + build-and-release: + name: Build and Release + runs-on: ubuntu-latest + steps: + - name: Cache local Maven repository + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - uses: actions/checkout@v5 + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'zulu' + - name: Set up Maven + uses: stCarolas/setup-maven@v5 + with: + maven-version: 3.9.6 + - name: Compile + run: mvn -B package --file pom.xml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Get Version Number from Pom + id: get_version + run: echo "VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV + - name: Extract latest CHANGELOG entry + id: changelog + run: | + CHANGELOG_CONTENT=$(awk 'BEGIN {print_section=0;} /^## \[/ {if (print_section == 0) {print_section=1;} else {exit;}} print_section {print;}' CHANGELOG.md) + CHANGELOG_ESCAPED=$(echo "$CHANGELOG_CONTENT" | sed ':a;N;$!ba;s/\n/%0A/g') + echo "Extracted latest release notes from CHANGELOG.md:" + echo -e "$CHANGELOG_CONTENT" + echo "::set-output name=content::$CHANGELOG_ESCAPED" + - name: Create Release + uses: actions/create-release@v1 + id: create_release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ env.VERSION }} + release_name: Release v${{ env.VERSION }} + draft: false + prerelease: false + body: ${{ steps.changelog.outputs.content }} + - uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./Universal/target/AntiVPN-${{ env.VERSION }}-universal.jar + asset_name: AntiVPN-Universal-v${{ env.VERSION }}.jar + asset_content_type: application/java-archive + - uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./Sponge/target/Sponge-${{ env.VERSION }}.jar + asset_name: AntiVPN-Sponge-v${{ env.VERSION }}.jar + asset_content_type: application/java-archive diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 073bbfa..550b098 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -12,15 +12,15 @@ jobs: steps: - name: Cache local Maven repository - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: '21' distribution: 'zulu' diff --git a/Bukkit/Loader/pom.xml b/Bukkit/Loader/pom.xml new file mode 100644 index 0000000..b4dff27 --- /dev/null +++ b/Bukkit/Loader/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + dev.brighten.antivpn + Bukkit + 1.9.4 + + dev.brighten.antivpn.bukkit + Loader + + + 17 + 17 + UTF-8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + antivpn-bukkit.jarinjar + ${project.parent.basedir}/Plugin/target/Plugin-${project.version}.jar + + + + + + + + + + src/main/resources + true + + + + + + + org.spigotmc + spigot-api + 1.20.2-R0.1-SNAPSHOT + provided + + + dev.brighten.antivpn + Plugin + ${project.version} + provided + + + dev.brighten.antivpn + loader-utils + 1.9.4 + compile + + + + \ No newline at end of file diff --git a/Bukkit/Loader/src/main/java/dev/brighten/antivpn/bukkit/loader/BukkitLoaderPlugin.java b/Bukkit/Loader/src/main/java/dev/brighten/antivpn/bukkit/loader/BukkitLoaderPlugin.java new file mode 100644 index 0000000..f8ea3c8 --- /dev/null +++ b/Bukkit/Loader/src/main/java/dev/brighten/antivpn/bukkit/loader/BukkitLoaderPlugin.java @@ -0,0 +1,36 @@ +package dev.brighten.antivpn.bukkit.loader; + +import dev.brighten.antivpn.loader.JarInJarClassLoader; +import dev.brighten.antivpn.loader.LoaderBootstrap; +import org.bukkit.plugin.java.JavaPlugin; + +public class BukkitLoaderPlugin extends JavaPlugin { + + private static final String JAR_NAME = "antivpn-bukkit.jarinjar"; + private static final String SOURCE_NAME = "antivpn-source.jarinjar"; + private static final String BOOTSTRAP_CLASS = "dev.brighten.antivpn.bukkit.BukkitPlugin"; + + private final LoaderBootstrap plugin; + + public BukkitLoaderPlugin() { + JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME, SOURCE_NAME); + this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, JavaPlugin.class, this); + } + + @Override + public void onLoad() { + this.plugin.onLoad(getDataFolder()); + } + + @Override + public void onEnable() { + this.plugin.onEnable(); + } + + @Override + public void onDisable() { + this.plugin.onDisable(); + } + + +} diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/Loader/src/main/resources/plugin.yml similarity index 57% rename from Bukkit/src/main/resources/plugin.yml rename to Bukkit/Loader/src/main/resources/plugin.yml index 1c9241d..e625e91 100644 --- a/Bukkit/src/main/resources/plugin.yml +++ b/Bukkit/Loader/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: KauriVPN -main: dev.brighten.antivpn.bukkit.BukkitPlugin +main: dev.brighten.antivpn.bukkit.loader.BukkitLoaderPlugin version: ${project.version} author: funkemunky api-version: 1.13 diff --git a/Bukkit/Plugin/pom.xml b/Bukkit/Plugin/pom.xml new file mode 100644 index 0000000..0a35b0c --- /dev/null +++ b/Bukkit/Plugin/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + + dev.brighten.antivpn + Bukkit + 1.9.4 + + + Plugin + + + 17 + 17 + UTF-8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + org.bstats + + dev.brighten.antivpn.bukkit.org.bstats + + + org.yaml.snakeyaml + dev.brighten.antivpn.shaded.org.yaml.snakeyaml + + + + + + + + + + src/main/resources + true + + + + + + + org.spigotmc + spigot-api + 1.20.2-R0.1-SNAPSHOT + provided + + + dev.brighten.antivpn + Source + 1.9.4 + provided + + + org.bstats + bstats-bukkit + 2.2.1 + compile + + + dev.brighten.antivpn + loader-utils + 1.9.4 + provided + + + + \ No newline at end of file diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitCommandExecutor.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitCommandExecutor.java similarity index 100% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitCommandExecutor.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitCommandExecutor.java diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java similarity index 96% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java index a4686aa..176e63a 100644 --- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java +++ b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java @@ -25,8 +25,8 @@ public class BukkitListener extends VPNExecutor implements Listener { @Override public void registerListeners() { - BukkitPlugin.pluginInstance.getServer().getPluginManager() - .registerEvents(this, BukkitPlugin.pluginInstance); + Bukkit.getPluginManager() + .registerEvents(this, BukkitPlugin.pluginInstance.getPlugin()); } @Override @@ -53,7 +53,7 @@ public class BukkitListener extends VPNExecutor implements Listener { @Override public void disablePlugin() { HandlerList.unregisterAll(this); - BukkitPlugin.pluginInstance.getServer().getPluginManager().disablePlugin(BukkitPlugin.pluginInstance); + Bukkit.getPluginManager().disablePlugin(BukkitPlugin.pluginInstance.getPlugin()); } @EventHandler(priority = EventPriority.HIGH) diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayer.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayer.java similarity index 94% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayer.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayer.java index 660094b..5f8e6ac 100644 --- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayer.java +++ b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayer.java @@ -27,7 +27,7 @@ public class BukkitPlayer extends APIPlayer { public void run() { player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason)); } - }.runTask(BukkitPlugin.pluginInstance); + }.runTask(BukkitPlugin.pluginInstance.getPlugin()); } else player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason)); } diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayerExecutor.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayerExecutor.java similarity index 100% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayerExecutor.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlayerExecutor.java diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java similarity index 74% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java index dfce1b9..540780c 100644 --- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java +++ b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java @@ -3,8 +3,11 @@ 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.Database; -import dev.brighten.antivpn.database.sqllite.LiteDatabase; +import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.local.H2VPN; +import dev.brighten.antivpn.database.mongo.MongoVPN; +import dev.brighten.antivpn.database.sql.MySqlVPN; +import dev.brighten.antivpn.loader.LoaderBootstrap; import lombok.Getter; import org.bstats.bukkit.Metrics; import org.bstats.charts.SimplePie; @@ -15,20 +18,34 @@ import org.bukkit.plugin.SimplePluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; +import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map; -public class BukkitPlugin extends JavaPlugin { +public class BukkitPlugin implements LoaderBootstrap { public static BukkitPlugin pluginInstance; private SimpleCommandMap commandMap; + @Getter + private File dataFolder; private final List registeredCommands = new ArrayList<>(); + @Getter + private final JavaPlugin plugin; + + public BukkitPlugin(JavaPlugin plugin) { + this.plugin = plugin; + } @Getter private PlayerCommandRunner playerCommandRunner; + @Override + public void onLoad(File dataFolder) { + this.dataFolder = dataFolder; + } + public void onEnable() { pluginInstance = this; @@ -39,20 +56,20 @@ public class BukkitPlugin extends JavaPlugin { playerCommandRunner.start(); // Loading our bStats metrics to be pushed to https://bstats.org - if(AntiVPN.getInstance().getVpnConfig().isMetrics()) { + if(AntiVPN.getInstance().getVpnConfig().metrics()) { Bukkit.getLogger().info("Starting bStats metrics..."); - Metrics metrics = new Metrics(this, 12615); + Metrics metrics = new Metrics(plugin, 12615); metrics.addCustomChart(new SimplePie("database_used", this::getDatabaseType)); new BukkitRunnable() { public void run() { AntiVPN.getInstance().checked = AntiVPN.getInstance().detections = 0; } - }.runTaskTimerAsynchronously(this, 12000, 12000); + }.runTaskTimerAsynchronously(plugin, 12000, 12000); } Bukkit.getLogger().info("Setting up and registering commands..."); // We need access to the commandMap to register our commands without using the "proper" method - if (pluginInstance.getServer().getPluginManager() instanceof SimplePluginManager manager) { + if (Bukkit.getServer().getPluginManager() instanceof SimplePluginManager manager) { try { Field field = SimplePluginManager.class.getDeclaredField("commandMap"); field.setAccessible(true); @@ -71,7 +88,7 @@ public class BukkitPlugin extends JavaPlugin { registeredCommands.add(newCommand); // This tells Bukkit to register our command for use. - commandMap.register(pluginInstance.getName(), newCommand); + commandMap.register(plugin.getName(), newCommand); } //TODO Finish system before implementing on startup @@ -81,7 +98,7 @@ public class BukkitPlugin extends JavaPlugin { .get()); AntiVPN.getInstance().getMessageHandler().reloadStrings();*/ - reloadConfig(); + plugin.reloadConfig(); } @Override @@ -107,17 +124,23 @@ public class BukkitPlugin extends JavaPlugin { } Bukkit.getLogger().info("Unregistering listeners..."); - HandlerList.unregisterAll(this); + HandlerList.unregisterAll(plugin); Bukkit.getLogger().info("Cancelling any running tasks..."); - Bukkit.getScheduler().cancelTasks(this); + Bukkit.getScheduler().cancelTasks(plugin); } private String getDatabaseType() { - Database database = AntiVPN.getInstance().getDatabase(); + VPNDatabase database = AntiVPN.getInstance().getDatabase(); - if(database instanceof LiteDatabase) { - return "SQLLite"; - } return "No-Database"; + if(database instanceof H2VPN) { + return "H2"; + } else if(database instanceof MySqlVPN) { + return "MySQL"; + } else if(database instanceof MongoVPN) { + return "MongoDB"; + } else { + return "No-Database"; + } } } diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/PlayerCommandRunner.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/PlayerCommandRunner.java similarity index 96% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/PlayerCommandRunner.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/PlayerCommandRunner.java index 3a285a8..8ac64a7 100644 --- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/PlayerCommandRunner.java +++ b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/PlayerCommandRunner.java @@ -35,7 +35,7 @@ public class PlayerCommandRunner { public void run() { action.getAction().run(); } - }.runTask(BukkitPlugin.pluginInstance); + }.runTask(BukkitPlugin.pluginInstance.getPlugin()); playerActions.poll(); } diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/command/BukkitCommand.java b/Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/command/BukkitCommand.java similarity index 100% rename from Bukkit/src/main/java/dev/brighten/antivpn/bukkit/command/BukkitCommand.java rename to Bukkit/Plugin/src/main/java/dev/brighten/antivpn/bukkit/command/BukkitCommand.java diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 3cd4cb3..e44a743 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -5,91 +5,21 @@ AntiVPN dev.brighten.antivpn - 2.0.0-SNAPSHOT + 1.9.4 + pom + + Plugin + Loader + + 4.0.0 Bukkit - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - 17 - 17 - -XDignore.symbol.file - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - package - - shade - - - true - - - org.bstats - - dev.brighten.antivpn.bukkit.org.bstats - - - org.yaml.snakeyaml - dev.brighten.antivpn.shaded.org.yaml.snakeyaml - - - - - - - - - - src/main/resources - true - - - - 17 17 - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - - - - - org.spigotmc - spigot-api - 1.20.2-R0.1-SNAPSHOT - provided - - - dev.brighten.antivpn - Common - 2.0.0-SNAPSHOT - provided - - - org.bstats - bstats-bukkit - 2.2.1 - compile - - - \ No newline at end of file diff --git a/Bungee/BungeeLoader/pom.xml b/Bungee/BungeeLoader/pom.xml new file mode 100644 index 0000000..0aea182 --- /dev/null +++ b/Bungee/BungeeLoader/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + + dev.brighten.antivpn + Bungee + 1.9.4 + ../pom.xml + + + dev.brighten.antivpn.bungee + BungeeLoader + + + 17 + 17 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + antivpn-bungee.jarinjar + ${project.parent.basedir}/BungeePlugin/target/BungeePlugin-${project.version}.jar + + + + + + + + + + src/main/resources + true + + + + + + + net.md-5 + bungeecord-api + 1.21-R0.2 + jar + provided + + + dev.brighten.antivpn + Plugin + ${project.version} + provided + + + dev.brighten.antivpn + loader-utils + 1.9.4 + compile + + + + \ No newline at end of file diff --git a/Bungee/BungeeLoader/src/main/java/dev/brighten/antivpn/bungee/BungeeLoaderPlugin.java b/Bungee/BungeeLoader/src/main/java/dev/brighten/antivpn/bungee/BungeeLoaderPlugin.java new file mode 100644 index 0000000..353be25 --- /dev/null +++ b/Bungee/BungeeLoader/src/main/java/dev/brighten/antivpn/bungee/BungeeLoaderPlugin.java @@ -0,0 +1,36 @@ +package dev.brighten.antivpn.bungee; + +import dev.brighten.antivpn.loader.JarInJarClassLoader; +import dev.brighten.antivpn.loader.LoaderBootstrap; +import net.md_5.bungee.api.plugin.Plugin; + +public class BungeeLoaderPlugin extends Plugin { + + private static final String JAR_NAME = "antivpn-bungee.jarinjar"; + private static final String SOURCE_NAME = "antivpn-source.jarinjar"; + private static final String BOOTSTRAP_CLASS = "dev.brighten.antivpn.bungee.BungeePlugin"; + + private final LoaderBootstrap plugin; + + public BungeeLoaderPlugin() { + JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME, SOURCE_NAME); + this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, Plugin.class, this); + } + + @Override + public void onLoad() { + this.plugin.onLoad(getDataFolder()); + } + + @Override + public void onEnable() { + this.plugin.onEnable(); + } + + @Override + public void onDisable() { + this.plugin.onDisable(); + } + + +} diff --git a/Bungee/src/main/resources/bungee.yml b/Bungee/BungeeLoader/src/main/resources/bungee.yml similarity index 67% rename from Bungee/src/main/resources/bungee.yml rename to Bungee/BungeeLoader/src/main/resources/bungee.yml index b045000..afa76f7 100644 --- a/Bungee/src/main/resources/bungee.yml +++ b/Bungee/BungeeLoader/src/main/resources/bungee.yml @@ -1,5 +1,5 @@ name: KauriVPN -main: dev.brighten.antivpn.bungee.BungeePlugin +main: dev.brighten.antivpn.bungee.BungeeLoaderPlugin description: A simple and fast antivpn plugin. version: ${project.version} author: funkemunky \ No newline at end of file diff --git a/Bungee/BungeePlugin/pom.xml b/Bungee/BungeePlugin/pom.xml new file mode 100644 index 0000000..1727eb0 --- /dev/null +++ b/Bungee/BungeePlugin/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + dev.brighten.antivpn + Bungee + 1.9.4 + ../pom.xml + + + BungeePlugin + + + 17 + 17 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + + org.bstats + + dev.brighten.antivpn.bungee.org.bstats + + + org.yaml.snakeyaml + dev.brighten.antivpn.shaded.org.yaml.snakeyaml + + + + + + package + + shade + + + + + + + + src/main/resources + true + + + + + + + dev.brighten.antivpn + Source + 1.9.4 + provided + + + net.md-5 + bungeecord-api + 1.21-R0.2 + jar + provided + + + org.bstats + bstats-bungeecord + 2.2.1 + compile + + + dev.brighten.antivpn + loader-utils + 1.9.4 + provided + + + + \ No newline at end of file diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java similarity index 95% rename from Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java rename to Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java index 7f3aad0..116322c 100644 --- a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java +++ b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java @@ -25,7 +25,7 @@ public class BungeeListener extends VPNExecutor implements Listener { @Override public void registerListeners() { BungeePlugin.pluginInstance.getProxy().getPluginManager() - .registerListener(BungeePlugin.pluginInstance, this); + .registerListener(BungeePlugin.pluginInstance.getPlugin(), this); } @Override @@ -61,12 +61,12 @@ public class BungeeListener extends VPNExecutor implements Listener { @Override public void disablePlugin() { - BungeePlugin.pluginInstance.getProxy().getPluginManager().unregisterListeners(BungeePlugin.pluginInstance); + BungeePlugin.pluginInstance.getProxy().getPluginManager().unregisterListeners(BungeePlugin.pluginInstance.getPlugin()); if (cacheResetTask != null) { cacheResetTask.cancel(); cacheResetTask = null; } - BungeePlugin.pluginInstance.getProxy().getPluginManager().unregisterCommands(BungeePlugin.pluginInstance); + BungeePlugin.pluginInstance.getProxy().getPluginManager().unregisterCommands(BungeePlugin.pluginInstance.getPlugin()); BungeePlugin.pluginInstance.onDisable(); } diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlayer.java b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlayer.java similarity index 100% rename from Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlayer.java rename to Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlayer.java diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlayerExecutor.java b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlayerExecutor.java similarity index 100% rename from Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlayerExecutor.java rename to Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlayerExecutor.java diff --git a/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java new file mode 100644 index 0000000..f8361fd --- /dev/null +++ b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java @@ -0,0 +1,87 @@ +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.local.H2VPN; +import dev.brighten.antivpn.database.mongo.MongoVPN; +import dev.brighten.antivpn.database.sql.MySqlVPN; +import dev.brighten.antivpn.loader.LoaderBootstrap; +import lombok.Getter; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.plugin.Plugin; +import org.bstats.bungeecord.Metrics; +import org.bstats.charts.SimplePie; + +import java.io.File; +import java.util.concurrent.TimeUnit; + +public class BungeePlugin implements LoaderBootstrap { + + public static BungeePlugin pluginInstance; + + @Getter + private File dataFolder; + + @Getter + private final Plugin plugin; + + public BungeePlugin(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public void onLoad(File dataFolder) { + this.dataFolder = dataFolder; + } + + @Override + public void onEnable() { + pluginInstance = this; + + //Setting up config + ProxyServer.getInstance().getLogger().info("Loading config..."); + + + //Loading plugin + ProxyServer.getInstance().getLogger().info("Starting AntiVPN services..."); + AntiVPN.start(new BungeeListener(), new BungeePlayerExecutor(), getDataFolder()); + + if(AntiVPN.getInstance().getVpnConfig().metrics()) { + ProxyServer.getInstance().getLogger().info("Starting bStats metrics..."); + Metrics metrics = new Metrics(getPlugin(), 12616); + metrics.addCustomChart(new SimplePie("database_used", this::getDatabaseType)); + ProxyServer.getInstance().getScheduler().schedule(getPlugin(), + () -> AntiVPN.getInstance().checked = AntiVPN.getInstance().detections = 0, + 10, 10, TimeUnit.MINUTES); + } + + for (Command command : AntiVPN.getInstance().getCommands()) { + ProxyServer.getInstance().getPluginManager().registerCommand(getPlugin(), new BungeeCommand(command)); + } + } + + @Override + public void onDisable() { + AntiVPN.getInstance().stop(); + } + + private String getDatabaseType() { + VPNDatabase database = AntiVPN.getInstance().getDatabase(); + + if(database instanceof H2VPN) { + return "H2"; + } else if(database instanceof MySqlVPN) { + return "MySQL"; + } else if(database instanceof MongoVPN) { + return "MongoDB"; + } else { + return "No-Database"; + } + } + + public ProxyServer getProxy() { + return ProxyServer.getInstance(); + } +} diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommand.java b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommand.java similarity index 100% rename from Bungee/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommand.java rename to Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommand.java diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommandExecutor.java b/Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommandExecutor.java similarity index 100% rename from Bungee/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommandExecutor.java rename to Bungee/BungeePlugin/src/main/java/dev/brighten/antivpn/bungee/command/BungeeCommandExecutor.java diff --git a/Bungee/pom.xml b/Bungee/pom.xml index cf03290..83aee15 100644 --- a/Bungee/pom.xml +++ b/Bungee/pom.xml @@ -5,79 +5,11 @@ AntiVPN dev.brighten.antivpn - 2.0.0-SNAPSHOT + 1.9.4 + pom 4.0.0 Bungee - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - 17 - 17 - -XDignore.symbol.file - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - - org.bstats - dev.brighten.antivpn.bungee.org.bstats - - - - - - package - - shade - - - - - - - - src/main/resources - true - - - - - - 17 - 17 - - - - - dev.brighten.antivpn - Common - 2.0.0-SNAPSHOT - provided - - - net.md-5 - bungeecord-api - 1.21-R0.2 - jar - provided - - - org.bstats - bstats-bungeecord - 2.2.1 - compile - - - \ No newline at end of file diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java deleted file mode 100644 index c8672b7..0000000 --- a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java +++ /dev/null @@ -1,56 +0,0 @@ -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.Database; -import dev.brighten.antivpn.database.sqllite.LiteDatabase; -import net.md_5.bungee.api.plugin.Plugin; -import org.bstats.bungeecord.Metrics; -import org.bstats.charts.SimplePie; - -import java.util.concurrent.TimeUnit; - -public class BungeePlugin extends Plugin { - - public static BungeePlugin pluginInstance; - - @Override - public void onEnable() { - pluginInstance = this; - - //Setting up config - getProxy().getLogger().info("Loading config..."); - - - //Loading plugin - getProxy().getLogger().info("Starting AntiVPN services..."); - AntiVPN.start(new BungeeListener(), new BungeePlayerExecutor(), getDataFolder()); - - if(AntiVPN.getInstance().getVpnConfig().isMetrics()) { - getProxy().getLogger().info("Starting bStats metrics..."); - Metrics metrics = new Metrics(this, 12616); - metrics.addCustomChart(new SimplePie("database_used", this::getDatabaseType)); - getProxy().getScheduler().schedule(this, - () -> AntiVPN.getInstance().checked = AntiVPN.getInstance().detections = 0, - 10, 10, TimeUnit.MINUTES); - } - - for (Command command : AntiVPN.getInstance().getCommands()) { - getProxy().getPluginManager().registerCommand(pluginInstance, new BungeeCommand(command)); - } - } - - @Override - public void onDisable() { - AntiVPN.getInstance().stop(); - } - - private String getDatabaseType() { - Database database = AntiVPN.getInstance().getDatabase(); - - if(database instanceof LiteDatabase) { - return "SQLLite"; - } return "No-Database"; - } -} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9706111 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.9.4] - 2025-09-30 + +### Added +- New dependency management system with automatic library loading and relocation +- Caffeine cache implementation to replace Guava +- Sponge platform support with full event handling and command system +- UUID lookup functionality for player validation +- Enhanced kick checking system with scheduled task execution +- Support for Java 17 and Java 21 runtime environments +- New database metrics tracking for bStats + +### Changed +- **BREAKING**: Minimum Java version upgraded from 8 to 17 +- Replaced Guava cache with Caffeine cache for better performance +- Modernized player checking system with asynchronous processing +- Improved database connection handling with proper resource management +- Enhanced VPN/Proxy detection with new `CheckResult` and `ResultType` system +- Updated Maven dependencies and build process +- Reorganized project structure (Assembly → Universal module) +- Improved error handling and exception logging throughout codebase + +### Fixed +- H2 database compatibility issues with automatic backup and recovery +- Memory leaks in database result set handling with try-with-resources +- Thread safety issues in player cache management +- Command registration and unregistration during plugin lifecycle +- Proper cleanup of database drivers on shutdown +- Resource management in SQL connections and prepared statements + +### Removed +- Guava dependency (replaced with Caffeine and built-in utilities) +- Legacy cached response handling system +- Old table format compatibility code \ No newline at end of file diff --git a/Common/Source/pom.xml b/Common/Source/pom.xml new file mode 100644 index 0000000..44fe127 --- /dev/null +++ b/Common/Source/pom.xml @@ -0,0 +1,178 @@ + + + 4.0.0 + + dev.brighten.antivpn + Common + 1.9.4 + + + Source + + + 17 + 17 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + org.projectlombok + lombok + 1.18.30 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + true + + + org.yaml.snakeyaml + dev.brighten.antivpn.shaded.org.yaml.snakeyaml + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + com.github.benmanes.caffeine + dev.brighten.antivpn.shaded.com.github.benmanes.caffeine + + + org.h2 + dev.brighten.antivpn.shaded.org.h2 + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + org.bson + dev.brighten.antivpn.shaded.org.bson + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + com.mongodb + dev.brighten.antivpn.shaded.com.mongodb + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + com.mysql.cj + dev.brighten.antivpn.shaded.com.mysql.cj + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + com.mysql.jdbc + dev.brighten.antivpn.shaded.com.mysql.jdbc + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + + + + + + + + src/main/resources + true + + + + + + + funkemunky-releases + https://nexus.funkemunky.cc/content/repositories/releases/ + + + + + + com.mysql + mysql-connector-j + 9.1.0 + jar + provided + + + com.h2database + h2 + 2.2.220 + provided + + + org.ow2.asm + asm + 9.8 + compile + + + org.ow2.asm + asm-commons + 9.8 + compile + + + org.yaml + snakeyaml + 2.2 + compile + + + com.github.ben-manes.caffeine + caffeine + 3.1.8 + provided + + + + org.mongodb + mongo-java-driver + 3.12.14 + provided + + + + \ No newline at end of file diff --git a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java b/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/AntiVPN.java rename to Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/APIPlayer.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/APIPlayer.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/APIPlayer.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/APIPlayer.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/CheckResult.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/CheckResult.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/CheckResult.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/CheckResult.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/OfflinePlayer.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/OfflinePlayer.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/OfflinePlayer.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/OfflinePlayer.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/PlayerExecutor.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/PlayerExecutor.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/PlayerExecutor.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/PlayerExecutor.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/ResultType.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/ResultType.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/ResultType.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/ResultType.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/VPNConfig.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNConfig.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/VPNConfig.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/VPNConfig.java diff --git a/Common/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java rename to Common/Source/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/Command.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/Command.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/Command.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/Command.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/CommandExecutor.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/CommandExecutor.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/CommandExecutor.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/CommandExecutor.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/AlertsCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/AlertsCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/AlertsCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/AlertsCommand.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/AllowlistCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/AllowlistCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/AllowlistCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/AllowlistCommand.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/AntiVPNCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/AntiVPNCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/AntiVPNCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/AntiVPNCommand.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/ClearCacheCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/ClearCacheCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/ClearCacheCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/ClearCacheCommand.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/LookupCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/LookupCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/LookupCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/LookupCommand.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/PlanCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/PlanCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/PlanCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/PlanCommand.java diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java b/Common/Source/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java rename to Common/Source/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java new file mode 100644 index 0000000..2289197 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java @@ -0,0 +1,44 @@ +package dev.brighten.antivpn.database; + +import dev.brighten.antivpn.web.objects.VPNResponse; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Consumer; + +public interface VPNDatabase { + Optional getStoredResponse(String ip); + + void cacheResponse(VPNResponse toCache); + + void deleteResponse(String ip); + + boolean isWhitelisted(UUID uuid); + + boolean isWhitelisted(String ip); + + void setWhitelisted(UUID uuid, boolean whitelisted); + + void setWhitelisted(String ip, boolean whitelisted); + + List getAllWhitelisted(); + + List getAllWhitelistedIps(); + + void getStoredResponseAsync(String ip, Consumer> result); + + void isWhitelistedAsync(UUID uuid, Consumer result); + + void isWhitelistedAsync(String ip, Consumer result); + + void alertsState(UUID uuid, Consumer result); + + void updateAlertsState(UUID uuid, boolean state); + + void clearResponses(); + + void init(); + + void shutdown(); +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java new file mode 100644 index 0000000..4dfcdf9 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java @@ -0,0 +1,283 @@ +package dev.brighten.antivpn.database.local; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import dev.brighten.antivpn.AntiVPN; +import dev.brighten.antivpn.api.VPNExecutor; +import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.sql.utils.MySQL; +import dev.brighten.antivpn.database.sql.utils.Query; +import dev.brighten.antivpn.web.objects.VPNResponse; +import lombok.SneakyThrows; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class H2VPN implements VPNDatabase { + + private final Cache cachedResponses = Caffeine.newBuilder() + .expireAfterWrite(20, TimeUnit.MINUTES) + .maximumSize(4000) + .build(); + + + public H2VPN() { + VPNExecutor.threadExecutor.scheduleAtFixedRate(() -> { + if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) return; + + //Refreshing whitelisted players + AntiVPN.getInstance().getExecutor().getWhitelisted().clear(); + AntiVPN.getInstance().getExecutor().getWhitelisted() + .addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted()); + + //Refreshing whitlisted IPs + AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear(); + AntiVPN.getInstance().getExecutor().getWhitelistedIps() + .addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps()); + }, 2, 30, TimeUnit.SECONDS); + } + + @Override + public Optional getStoredResponse(String ip) { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()|| MySQL.isClosed()) + return Optional.empty(); + + VPNResponse response = cachedResponses.get(ip, ip2 -> { + try(ResultSet rs = Query.prepare("select * from `responses` where `ip` = ? limit 1").append(ip). + executeQuery()) { + if (rs != null && rs.next()) { + return new VPNResponse(rs.getString("asn"), rs.getString("ip"), + rs.getString("countryName"), rs.getString("countryCode"), + rs.getString("city"), rs.getString("timeZone"), + rs.getString("method"), rs.getString("isp"), "N/A", + rs.getBoolean("proxy"), rs.getBoolean("cached"), true, + rs.getDouble("latitude"), rs.getDouble("longitude"), + rs.getTimestamp("inserted").getTime(), -1); + } + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor().logException("There was a problem getting a response for " + + ip, e); + } + return null; + }); + + return Optional.ofNullable(response); + } + + /* + * Query. + * prepare("create table if not exists `responses` (`ip` varchar(45) not null, " + * + + * "`countryName` varchar(64), `countryCode` varchar(10), `city` varchar(64), `timeZone` varchar(64), " + * + + * "`method` varchar(32), `isp` varchar(32), `proxy` boolean, `cached` boolean " + * + "`latitude` double, `longitude` double)"); + */ + @Override + public void cacheResponse(VPNResponse toCache) { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) + return; + + cachedResponses.put(toCache.getIp(), toCache); + + Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`," + + "`method`,`isp`,`proxy`,`cached`,`inserted`,`latitude`,`longitude`) values (?,?,?,?,?,?,?,?,?,?,?,?,?)") + .append(toCache.getIp()).append(toCache.getAsn()).append(toCache.getCountryName()) + .append(toCache.getCountryCode()).append(toCache.getCity()).append(toCache.getTimeZone()) + .append(toCache.getMethod()).append(toCache.getIsp()).append(toCache.isProxy()) + .append(toCache.isCached()).append(new Timestamp(System.currentTimeMillis())) + .append(toCache.getLatitude()).append(toCache.getLongitude()).execute(); + } + + @Override + public void deleteResponse(String ip) { + if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) + return; + + Query.prepare("delete from `responses` where `ip` = ?").append(ip).execute(); + } + + @SneakyThrows + @Override + public boolean isWhitelisted(UUID uuid) { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) + return false; + ResultSet set = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1") + .append(uuid.toString()).executeQuery(); + + return set != null && set.next() && set.getString("uuid") != null; + } + + @SneakyThrows + @Override + public boolean isWhitelisted(String ip) { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) + return false; + ResultSet set = Query.prepare("select `ip` from `whitelisted-ips` where `ip` = ? limit 1") + .append(ip).executeQuery(); + + + return set != null && set.next() && set.getString("ip") != null; + } + + @Override + public void setWhitelisted(UUID uuid, boolean whitelisted) { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) + return; + + if (whitelisted) { + if (!isWhitelisted(uuid)) { + Query.prepare("insert into `whitelisted` (`uuid`) values (?)").append(uuid.toString()).execute(); + } + AntiVPN.getInstance().getExecutor().getWhitelisted().add(uuid); + } else { + Query.prepare("delete from `whitelisted` where `uuid` = ?").append(uuid.toString()).execute(); + AntiVPN.getInstance().getExecutor().getWhitelisted().remove(uuid); + } + } + + @Override + public void setWhitelisted(String ip, boolean whitelisted) { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) + return; + + if(whitelisted) { + if(!isWhitelisted(ip)) { + Query.prepare("insert into `whitelisted-ips` (`ip`) values (?)").append(ip).execute(); + } + AntiVPN.getInstance().getExecutor().getWhitelistedIps().add(ip); + } else { + Query.prepare("delete from `whitelisted-ips` where `ip` = ?").append(ip).execute(); + AntiVPN.getInstance().getExecutor().getWhitelistedIps().remove(ip); + } + } + + @Override + public List getAllWhitelisted() { + List uuids = new ArrayList<>(); + + if(!MySQL.isClosed()) Query.prepare("select uuid from `whitelisted`") + .execute(set -> uuids.add(UUID.fromString(set.getString("uuid")))); + + return uuids; + } + + @Override + public List getAllWhitelistedIps() { + List ips = new ArrayList<>(); + + if(!MySQL.isClosed()) Query.prepare("select `ip` from `whitelisted-ips`") + .execute(set -> ips.add(set.getString("ip"))); + + return ips; + } + + @Override + public void getStoredResponseAsync(String ip, Consumer> result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> result.accept(getStoredResponse(ip))); + } + + @Override + public void isWhitelistedAsync(UUID uuid, Consumer result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(uuid))); + } + + @Override + public void isWhitelistedAsync(String ip, Consumer result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(ip))); + } + + @Override + public void alertsState(UUID uuid, Consumer result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> { + + try(ResultSet set = Query.prepare("select * from `alerts` where `uuid` = ? limit 1") + .append(uuid.toString()).executeQuery()) { + result.accept(set != null && set.next() && set.getString("uuid") != null); + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor().logException("There was a problem getting alerts state for " + uuid, e); + result.accept(false); + } + }); + } + + @Override + public void updateAlertsState(UUID uuid, boolean enabled) { + if(MySQL.isClosed()) return; + + if(enabled) { + //We want to make sure there isn't already a uuid inserted to prevent double insertions + alertsState(uuid, alreadyEnabled -> { //No need to make another thread execute, already async + if(!alreadyEnabled) { + Query.prepare("insert into `alerts` (`uuid`) values (?)").append(uuid.toString()) + .execute(); + } //No need to insert again of already enabled + }); + //Removing any uuid from the alerts table will disable alerts globally. + } else VPNExecutor.threadExecutor.execute(() -> + Query.prepare("delete from `alerts` where `uuid` = ?") + .append(uuid.toString()) + .execute()); + } + + @Override + public void clearResponses() { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> Query.prepare("delete from `responses`").execute()); + } + + @Override + public void init() { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) + return; + AntiVPN.getInstance().getExecutor().log("Initializing H2..."); + MySQL.initH2(); + + AntiVPN.getInstance().getExecutor().log("Creating tables..."); + + //Running check for old table types to update + + Query.prepare("create table if not exists `whitelisted` (`uuid` varchar(36) not null)").execute(); + Query.prepare("create table if not exists `whitelisted-ips` (`ip` varchar(45) not null)").execute(); + Query.prepare("create table if not exists `responses` (`ip` varchar(45) not null, `asn` varchar(12)," + + "`countryName` text, `countryCode` varchar(10), `city` text, `timeZone` varchar(64), " + + "`method` varchar(32), `isp` text, `proxy` boolean, `cached` boolean, `inserted` timestamp," + + "`latitude` double, `longitude` double)").execute(); + Query.prepare("create table if not exists `alerts` (`uuid` varchar(36) not null)").execute(); + + AntiVPN.getInstance().getExecutor().log("Creating indexes..."); + try { + Query.prepare("create index if not exists `uuid_1` on `whitelisted` (`uuid`)").execute(); + Query.prepare("create index if not exists `ip_1` on `responses` (`ip`)").execute(); + Query.prepare("create index if not exists `proxy_1` on `responses` (`proxy`)").execute(); + Query.prepare("create index if not exists `inserted_1` on `responses` (`inserted`)").execute(); + Query.prepare("create index if not exists `ip_1` on `whitelisted-ips` (`ip`)").execute(); + } catch (Exception e) { + System.err.println("MySQL Excepton created" + e.getMessage()); + } + } + + @Override + public void shutdown() { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) + return; + + MySQL.shutdown(); + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/mongo/MongoVPN.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/mongo/MongoVPN.java new file mode 100644 index 0000000..2e7c4eb --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/mongo/MongoVPN.java @@ -0,0 +1,260 @@ +package dev.brighten.antivpn.database.mongo; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.mongodb.*; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Indexes; +import com.mongodb.client.model.UpdateOptions; +import dev.brighten.antivpn.AntiVPN; +import dev.brighten.antivpn.api.VPNExecutor; +import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.web.objects.VPNResponse; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class MongoVPN implements VPNDatabase { + + private MongoCollection settingsDocument, cacheDocument; + private MongoClient client; + + private final Cache cachedResponses = Caffeine.newBuilder() + .expireAfterWrite(20, TimeUnit.MINUTES) + .maximumSize(4000) + .build(); + + public MongoVPN() { + VPNExecutor.threadExecutor.scheduleAtFixedRate(() -> { + if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) return; + + //Refreshing whitelisted players + AntiVPN.getInstance().getExecutor().getWhitelisted().clear(); + AntiVPN.getInstance().getExecutor().getWhitelisted() + .addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted()); + + //Refreshing whitlisted IPs + AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear(); + AntiVPN.getInstance().getExecutor().getWhitelistedIps() + .addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps()); + }, 2, 30, TimeUnit.SECONDS); + } + @Override + public Optional getStoredResponse(String ip) { + VPNResponse response = cachedResponses.get(ip, ip2 -> { + Document rdoc = cacheDocument.find(Filters.eq("ip", ip)).first(); + + if(rdoc != null) { + long lastUpdate = rdoc.get("lastAccess", 0L); + + if(System.currentTimeMillis() - lastUpdate > TimeUnit.HOURS.toMillis(1)) { + VPNExecutor.threadExecutor.execute(() -> deleteResponse(ip)); + return null; + } + + return VPNResponse.builder().asn(rdoc.getString("asn")).ip(ip) + .countryName(rdoc.getString("countryName")) + .countryCode(rdoc.getString("countryCode")) + .city(rdoc.getString("city")) + .isp(rdoc.getString("isp")) + .method(rdoc.getString("method")) + .timeZone(rdoc.getString("timeZone")) + .proxy(rdoc.getBoolean("proxy")) + .cached(rdoc.getBoolean("cached")) + .success(true) + .latitude(rdoc.getDouble("latitude")) + .longitude(rdoc.getDouble("longitude")) + .lastAccess(rdoc.get("lastAccess", 0L)) + .build(); + } + return null; + }); + + + return Optional.ofNullable(response); + } + + @Override + public void cacheResponse(VPNResponse toCache) { + Document rdoc = new Document("ip", toCache.getIp()); + + rdoc.put("asn", toCache.getAsn()); + rdoc.put("countryName", toCache.getCountryName()); + rdoc.put("countryCode", toCache.getCountryCode()); + rdoc.put("city", toCache.getCity()); + rdoc.put("isp", toCache.getIsp()); + rdoc.put("method", toCache.getMethod()); + rdoc.put("timeZone", toCache.getTimeZone()); + rdoc.put("proxy", toCache.isProxy()); + rdoc.put("cached", toCache.isCached()); + rdoc.put("success", toCache.isSuccess()); + rdoc.put("latitude", toCache.getLatitude()); + rdoc.put("longitude", toCache.getLongitude()); + rdoc.put("lastAccess", System.currentTimeMillis()); + + cachedResponses.put(toCache.getIp(), toCache); + + VPNExecutor.threadExecutor.execute(() -> { + Bson update = new Document("$set", rdoc); + cacheDocument.updateOne(Filters.eq("ip", toCache.getIp()), update, + new UpdateOptions().upsert(true)); + }); + } + + @Override + public void deleteResponse(String ip) { + cacheDocument.deleteMany(Filters.eq("ip", ip)); + } + + @Override + public boolean isWhitelisted(UUID uuid) { + return settingsDocument + .find(Filters.and(Filters.eq("setting", "whitelist"), + Filters.eq("uuid", uuid.toString()))).first() != null; + } + + @Override + public boolean isWhitelisted(String ip) { + return settingsDocument + .find(Filters.and(Filters.eq("setting", "whitelist"), + Filters.eq("ip", ip))).first() != null; + } + + @Override + public void setWhitelisted(UUID uuid, boolean whitelisted) { + if(whitelisted) { + Document wdoc = new Document("setting", "whitelist"); + wdoc.put("uuid", uuid.toString()); + AntiVPN.getInstance().getExecutor().getWhitelisted().add(uuid); + VPNExecutor.threadExecutor.execute(() -> settingsDocument.insertOne(wdoc)); + } else { + AntiVPN.getInstance().getExecutor().getWhitelisted().remove(uuid); + VPNExecutor.threadExecutor.execute(() -> settingsDocument.deleteMany(Filters + .and( + Filters.eq("setting", "whitelist"), + Filters.eq("uuid", uuid.toString())))); + } + } + + @Override + public void setWhitelisted(String ip, boolean whitelisted) { + if(whitelisted) { + Document wdoc = new Document("setting", "whitelist").append("ip", ip); + + AntiVPN.getInstance().getExecutor().getWhitelistedIps().add(ip); + VPNExecutor.threadExecutor.execute(() -> settingsDocument.insertOne(wdoc)); + } else { + AntiVPN.getInstance().getExecutor().getWhitelistedIps().remove(ip); + VPNExecutor.threadExecutor.execute(() -> settingsDocument.deleteMany(Filters + .and( + Filters.eq("setting", "whitelist"), + Filters.eq("ip", ip)))); + } + } + + @Override + public List getAllWhitelisted() { + List uuids = new ArrayList<>(); + settingsDocument.find(Filters.and(Filters.eq("setting", "whitelist"), + Filters.exists("uuid"))) + .forEach((Consumer) doc -> uuids.add(UUID.fromString(doc.getString("uuid")))); + return uuids; + } + + @Override + public List getAllWhitelistedIps() { + List ips = new ArrayList<>(); + settingsDocument.find(Filters.and(Filters.eq("setting", "whitelist"), + Filters.exists("ip"))) + .forEach((Consumer) doc -> ips.add(doc.getString("ip"))); + return ips; + } + + @Override + public void getStoredResponseAsync(String ip, Consumer> result) { + VPNExecutor.threadExecutor.execute(() -> result.accept(getStoredResponse(ip))); + } + + @Override + public void isWhitelistedAsync(UUID uuid, Consumer result) { + VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(uuid))); + } + + @Override + public void isWhitelistedAsync(String ip, Consumer result) { + VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(ip))); + } + + @Override + public void alertsState(UUID uuid, Consumer result) { + VPNExecutor.threadExecutor.execute(() -> result.accept(settingsDocument + .find(Filters.and(Filters.eq("setting", "alerts"), + Filters.eq("uuid", uuid.toString()))).first() != null)); + } + + @Override + public void updateAlertsState(UUID uuid, boolean state) { + VPNExecutor.threadExecutor.execute(() -> { + settingsDocument.deleteMany(Filters.and(Filters.eq("setting", "alerts"), + Filters.eq("uuid", uuid.toString()))); + if(state) { + Document adoc = new Document("setting", "alerts"); + + adoc.put("uuid", uuid.toString()); + settingsDocument.insertOne(adoc); + } + }); + } + + @Override + public void clearResponses() { + cacheDocument.deleteMany(Filters.exists("ip")); + } + + @Override + public void init() { + if(!AntiVPN.getInstance().getVpnConfig().mongoDatabaseURL().isEmpty()) { //URL + ConnectionString cs = new ConnectionString(AntiVPN.getInstance().getVpnConfig().mongoDatabaseURL()); + MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); + client = MongoClients.create(settings); + } else { + MongoClientSettings.Builder settingsBld = MongoClientSettings.builder().readPreference(ReadPreference.nearest()) + .applyToClusterSettings(builder -> builder. + hosts(Collections.singletonList( + new ServerAddress( + AntiVPN.getInstance().getVpnConfig().getIp(), + AntiVPN.getInstance().getVpnConfig().getPort()) + ))); + if(AntiVPN.getInstance().getVpnConfig().useDatabaseCreds()) { + settingsBld.credential(MongoCredential + .createCredential(AntiVPN.getInstance().getVpnConfig().getUsername(), + AntiVPN.getInstance().getVpnConfig().getDatabaseName(), + AntiVPN.getInstance().getVpnConfig().getPassword().toCharArray())); + } + + client = MongoClients.create(settingsBld.build()); + } + MongoDatabase antivpnDatabase = client.getDatabase(AntiVPN.getInstance().getVpnConfig().getDatabaseName()); + + settingsDocument = antivpnDatabase.getCollection("settings"); + if(settingsDocument.listIndexes().first() == null) { + AntiVPN.getInstance().getExecutor().log("Created index for settings collection!"); + settingsDocument.createIndex(Indexes.ascending("ip")); + } + cacheDocument = antivpnDatabase.getCollection("cache"); + } + + @Override + public void shutdown() { + settingsDocument = null; + cacheDocument = null; + client.close(); + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/MySqlVPN.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/MySqlVPN.java new file mode 100644 index 0000000..148f0c8 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/MySqlVPN.java @@ -0,0 +1,362 @@ +package dev.brighten.antivpn.database.sql; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import dev.brighten.antivpn.AntiVPN; +import dev.brighten.antivpn.api.VPNExecutor; +import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.sql.utils.MySQL; +import dev.brighten.antivpn.database.sql.utils.Query; +import dev.brighten.antivpn.web.objects.VPNResponse; +import lombok.SneakyThrows; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class MySqlVPN implements VPNDatabase { + + private final Cache cachedResponses = Caffeine.newBuilder() + .expireAfterWrite(20, TimeUnit.MINUTES) + .maximumSize(4000) + .build(); + + + public MySqlVPN() { + VPNExecutor.threadExecutor.scheduleAtFixedRate(() -> { + if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) return; + + //Refreshing whitelisted players + AntiVPN.getInstance().getExecutor().getWhitelisted().clear(); + AntiVPN.getInstance().getExecutor().getWhitelisted() + .addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted()); + + //Refreshing whitlisted IPs + AntiVPN.getInstance().getExecutor().getWhitelistedIps().clear(); + AntiVPN.getInstance().getExecutor().getWhitelistedIps() + .addAll(AntiVPN.getInstance().getDatabase().getAllWhitelistedIps()); + }, 2, 30, TimeUnit.SECONDS); + } + + @Override + public Optional getStoredResponse(String ip) { + if (isDisabled()) + return Optional.empty(); + + VPNResponse response = cachedResponses.get(ip, ip2 -> { + try(ResultSet rs = Query.prepare("select * from `responses` where `ip` = ? limit 1").append(ip) + .executeQuery()) { + if (rs != null && rs.next()) { + VPNResponse responseFromDoc = new VPNResponse(rs.getString("asn"), + rs.getString("ip"), + rs.getString("countryName"), rs.getString("countryCode"), + rs.getString("city"), rs.getString("timeZone"), + rs.getString("method"), rs.getString("isp"), "N/A", + rs.getBoolean("proxy"), rs.getBoolean("cached"), true, + rs.getDouble("latitude"), rs.getDouble("longitude"), + rs.getTimestamp("inserted").getTime(), -1); + + if(System.currentTimeMillis() - responseFromDoc.getLastAccess() > TimeUnit.HOURS.toMillis(1)) { + VPNExecutor.threadExecutor.execute(() -> deleteResponse(ip)); + return null; + } + + return responseFromDoc; + } + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor() + .logException("Failed to get response from cache due to SQL error for: " + ip, e); + } + return null; + }); + + return Optional.ofNullable(response); + } + + /* + * Query. + * prepare("create table if not exists `responses` (`ip` varchar(45) not null, " + * + + * "`countryName` varchar(64), `countryCode` varchar(10), `city` varchar(64), `timeZone` varchar(64), " + * + + * "`method` varchar(32), `isp` varchar(32), `proxy` boolean, `cached` boolean " + * + "`latitude` double, `longitude` double)"); + */ + @Override + public void cacheResponse(VPNResponse toCache) { + if (isDisabled()) + return; + + cachedResponses.put(toCache.getIp(), toCache); + + Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`," + + "`method`,`isp`,`proxy`,`cached`,`inserted`,`latitude`,`longitude`) values (?,?,?,?,?,?,?,?,?,?,?,?,?)") + .append(toCache.getIp()).append(toCache.getAsn()).append(toCache.getCountryName()) + .append(toCache.getCountryCode()).append(toCache.getCity()).append(toCache.getTimeZone()) + .append(toCache.getMethod()).append(toCache.getIsp()).append(toCache.isProxy()) + .append(toCache.isCached()).append(new Timestamp(System.currentTimeMillis())) + .append(toCache.getLatitude()).append(toCache.getLongitude()).execute(); + } + + @Override + public void deleteResponse(String ip) { + if(!isDisabled()) + return; + + Query.prepare("delete from `responses` where `ip` = ?").append(ip).execute(); + } + + @SneakyThrows + @Override + public boolean isWhitelisted(UUID uuid) { + if (isDisabled()) + return false; + try(ResultSet set = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1") + .append(uuid.toString()).executeQuery()) { + return set != null && set.next() && set.getString("uuid") != null; + } + } + + @SneakyThrows + @Override + public boolean isWhitelisted(String ip) { + if (isDisabled()) + return false; + try(ResultSet set = Query.prepare("select `ip` from `whitelisted-ips` where `ip` = ? limit 1") + .append(ip).executeQuery()) { + return set != null && set.next() && set.getString("ip") != null; + } + } + + @Override + public void setWhitelisted(UUID uuid, boolean whitelisted) { + if (isDisabled()) + return; + + if (whitelisted) { + if (!isWhitelisted(uuid)) { + Query.prepare("insert into `whitelisted` (`uuid`) values (?)").append(uuid.toString()).execute(); + } + AntiVPN.getInstance().getExecutor().getWhitelisted().add(uuid); + } else { + Query.prepare("delete from `whitelisted` where `uuid` = ?").append(uuid.toString()).execute(); + AntiVPN.getInstance().getExecutor().getWhitelisted().remove(uuid); + } + } + + @Override + public void setWhitelisted(String ip, boolean whitelisted) { + if (isDisabled()) + return; + + if(whitelisted) { + if(!isWhitelisted(ip)) { + Query.prepare("insert into `whitelisted-ips` (`ip`) values (?)").append(ip).execute(); + } + AntiVPN.getInstance().getExecutor().getWhitelistedIps().add(ip); + } else { + Query.prepare("delete from `whitelisted-ips` where `ip` = ?").append(ip).execute(); + AntiVPN.getInstance().getExecutor().getWhitelistedIps().remove(ip); + } + } + + @Override + public List getAllWhitelisted() { + List uuids = new ArrayList<>(); + + if(!MySQL.isClosed()) Query.prepare("select uuid from `whitelisted`") + .execute(set -> uuids.add(UUID.fromString(set.getString("uuid")))); + + return uuids; + } + + @Override + public List getAllWhitelistedIps() { + List ips = new ArrayList<>(); + + if(!MySQL.isClosed()) Query.prepare("select `ip` from `whitelisted-ips`") + .execute(set -> ips.add(set.getString("ip"))); + + return ips; + } + + @Override + public void getStoredResponseAsync(String ip, Consumer> result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> result.accept(getStoredResponse(ip))); + } + + @Override + public void isWhitelistedAsync(UUID uuid, Consumer result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(uuid))); + } + + @Override + public void isWhitelistedAsync(String ip, Consumer result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(ip))); + } + + @Override + public void alertsState(UUID uuid, Consumer result) { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> { + + try(ResultSet set = Query.prepare("select * from `alerts` where `uuid` = ? limit 1") + .append(uuid.toString()).executeQuery()) { + result.accept(set != null && set.next() && set.getString("uuid") != null); + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor() + .logException("Failed to get alerts state from database for: " + uuid, e); + result.accept(false); + } + }); + } + + @Override + public void updateAlertsState(UUID uuid, boolean enabled) { + if(MySQL.isClosed()) return; + + if(enabled) { + //We want to make sure there isn't already a uuid inserted to prevent double insertions + alertsState(uuid, alreadyEnabled -> { //No need to make another thread execute, already async + if(!alreadyEnabled) { + Query.prepare("insert into `alerts` (`uuid`) values (?)").append(uuid.toString()) + .execute(); + } //No need to insert again of already enabled + }); + //Removing any uuid from the alerts table will disable alerts globally. + } else VPNExecutor.threadExecutor.execute(() -> + Query.prepare("delete from `alerts` where `uuid` = ?") + .append(uuid.toString()) + .execute()); + } + + @Override + public void clearResponses() { + if(MySQL.isClosed()) return; + + VPNExecutor.threadExecutor.execute(() -> Query.prepare("delete from `responses`").execute()); + } + + @Override + public void init() { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) + return; + AntiVPN.getInstance().getExecutor().log("Initializing MySQL..."); + MySQL.init(); + + AntiVPN.getInstance().getExecutor().log("Creating tables..."); + + //Running check for old table types to update + Query.prepare("select `DATA_TYPE` from INFORMATION_SCHEMA.COLUMNS " + + "WHERE table_name = 'responses' AND COLUMN_NAME = 'isp';").execute(set -> { + if(set.getObject("DATA_TYPE").toString().contains("varchar")) { + AntiVPN.getInstance().getExecutor().log("Using old database format for storing responses! " + + "Dropping table and creating a new one..."); + if(Query.prepare("drop table `responses`").execute() > 0) { + AntiVPN.getInstance().getExecutor().log("Successfully dropped table!"); + } + } + }); + + Query.prepare("create table if not exists `whitelisted` (`uuid` varchar(36) not null)").execute(); + Query.prepare("create table if not exists `whitelisted-ips` (`ip` varchar(45) not null)").execute(); + Query.prepare("create table if not exists `responses` (`ip` varchar(45) not null, `asn` varchar(12)," + + "`countryName` text, `countryCode` varchar(10), `city` text, `timeZone` varchar(64), " + + "`method` varchar(32), `isp` text, `proxy` boolean, `cached` boolean, `inserted` timestamp," + + "`latitude` double, `longitude` double)").execute(); + Query.prepare("create table if not exists `alerts` (`uuid` varchar(36) not null)").execute(); + + AntiVPN.getInstance().getExecutor().log("Creating indexes..."); + try { + // Ref: + // https://dba.stackexchange.com/questions/24531/mysql-create-index-if-not-exists + + String query = "SELECT COUNT(1) IndexExists FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema=DATABASE()" + + " AND table_name='whitelisted' AND index_name='uuid_1';"; + int id = 0; + try(ResultSet rs = Query.prepare(query).executeQuery()) { + while (rs.next()) { + id = rs.getInt("IndexExists"); + } + if (id == 0) { + Query.prepare("create index `uuid_1` on `whitelisted` (`uuid`)").execute(); + } + } + id = 0; + + // Responses index + query = "SELECT COUNT(1) IndexExists FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema=DATABASE() " + + "AND table_name='responses' AND index_name='ip_1';"; + try(ResultSet rs = Query.prepare(query).executeQuery()) { + while (rs.next()) { + id = rs.getInt("IndexExists"); + } + if (id == 0) { + Query.prepare("create index `ip_1` on `responses` (`ip`)").execute(); + } + id = 0; + } + + query = "SELECT COUNT(1) IndexExists FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema=DATABASE() " + + "AND table_name='responses' AND index_name='proxy_1';"; + try(ResultSet rs = Query.prepare(query).executeQuery()) { + while (rs.next()) { + id = rs.getInt("IndexExists"); + } + if (id == 0) { + Query.prepare("create index `proxy_1` on `responses` (`proxy`)").execute(); + } + id = 0; + } + query = "SELECT COUNT(1) IndexExists FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema=DATABASE()" + + " AND table_name='responses' AND index_name='inserted_1';"; + try(ResultSet rs = Query.prepare(query).executeQuery()) { + while (rs.next()) { + id = rs.getInt("IndexExists"); + } + if (id == 0) { + Query.prepare("create index `inserted_1` on `responses` (`inserted`)").execute(); + } + id = 0; + } + + //Whitelisted IPs index + query = "SELECT COUNT(1) IndexExists FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema=DATABASE()" + + " AND table_name='whitelisted-ips' AND index_name='ip_1';"; + try(ResultSet rs = Query.prepare(query).executeQuery()) { + while (rs.next()) { + id = rs.getInt("IndexExists"); + } + if (id == 0) { + Query.prepare("create index `ip_1` on `whitelisted-ips` (`ip`)").execute(); + } + } + } catch (Exception e) { + System.err.println("MySQL Excepton created" + e.getMessage()); + } + } + + private boolean isDisabled() { + return !AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()|| MySQL.isClosed(); + } + + @Override + public void shutdown() { + if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled()) + return; + MySQL.shutdown(); + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/ExecutableStatement.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/ExecutableStatement.java new file mode 100644 index 0000000..f226fd0 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/ExecutableStatement.java @@ -0,0 +1,138 @@ +package dev.brighten.antivpn.database.sql.utils; + +import dev.brighten.antivpn.utils.MiscUtils; +import lombok.SneakyThrows; + +import java.sql.*; +import java.util.UUID; + +public class ExecutableStatement { + private PreparedStatement statement; + private int pos = 1; + + public ExecutableStatement(PreparedStatement statement) { + this.statement = statement; + } + + @SneakyThrows + public Integer execute() { + try { + return statement.executeUpdate(); + } finally { + MiscUtils.close(statement); + } + } + + @SneakyThrows + public void execute(ResultSetIterator iterator) { + ResultSet rs = null; + try { + rs = statement.executeQuery(); + while (rs.next()) iterator.next(rs); + } finally { + MiscUtils.close(statement, rs); + } + } + + @SneakyThrows + public void executeSingle(ResultSetIterator iterator) { + ResultSet rs = null; + try { + rs = statement.executeQuery(); + if (rs.next()) iterator.next(rs); + else iterator.next(null); + } finally { + MiscUtils.close(statement, rs); + } + } + + @SneakyThrows + public ResultSet executeQuery() { + return statement.executeQuery(); + } + + @SneakyThrows + public ExecutableStatement append(Object obj) { + statement.setObject(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(String obj) { + statement.setString(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(UUID uuid) { + if (uuid != null) statement.setString(pos++, uuid.toString().replace("-", "")); + else statement.setString(pos++, null); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Array obj) { + statement.setArray(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Integer obj) { + statement.setInt(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Short obj) { + statement.setShort(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Long obj) { + statement.setLong(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Float obj) { + statement.setFloat(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Double obj) { + statement.setDouble(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Date obj) { + statement.setDate(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Timestamp obj) { + statement.setTimestamp(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Time obj) { + statement.setTime(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(Blob obj) { + statement.setBlob(pos++, obj); + return this; + } + + @SneakyThrows + public ExecutableStatement append(byte[] obj) { + statement.setBytes(pos++, obj); + return this; + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java new file mode 100644 index 0000000..e8a1530 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java @@ -0,0 +1,143 @@ +package dev.brighten.antivpn.database.sql.utils; + +import com.mysql.cj.jdbc.Driver; +import dev.brighten.antivpn.AntiVPN; +import org.h2.jdbc.JdbcSQLFeatureNotSupportedException; +import org.h2.jdbc.JdbcSQLNonTransientConnectionException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import java.util.logging.Level; + +public class MySQL { + private static Connection conn; + + public static void init() { + try { + if (conn == null || conn.isClosed()) { + DriverManager.registerDriver(new Driver()); + conn = DriverManager.getConnection("jdbc:mysql://" + AntiVPN.getInstance().getVpnConfig().getIp() + + ":" + AntiVPN.getInstance().getVpnConfig().getPort() + + "/?useSSL=true&autoReconnect=true", + AntiVPN.getInstance().getVpnConfig().getUsername(), + AntiVPN.getInstance().getVpnConfig().getPassword()); + conn.setAutoCommit(true); + Query.use(conn); + Query.prepare("CREATE DATABASE IF NOT EXISTS `" + + AntiVPN.getInstance().getVpnConfig().getDatabaseName() + "`").execute(); + Query.prepare("USE `" + AntiVPN.getInstance().getVpnConfig().getDatabaseName() + "`").execute(); + AntiVPN.getInstance().getExecutor().log("Connection to MySQL has been established."); + } + } catch (Exception e) { + AntiVPN.getInstance().getExecutor().logException("Failed to load mysql: " + e.getMessage(), e); + } + } + + private static boolean didRetry = false; + + public static void initH2() { + if(didRetry) { + AntiVPN.getInstance().getExecutor().log(Level.WARNING, + "Already attempted to retry H2 connection, skipping."); + return; + } + File dataFolder = new File(AntiVPN.getInstance().getPluginFolder(), "databases"); + if (!dataFolder.exists() && dataFolder.mkdirs()) { + AntiVPN.getInstance().getExecutor().log("Created database directory"); + } + + File dbFile = new File(dataFolder, "database.mv.db"); + + File databaseFile = new File(dataFolder, "database"); + try { + conn = new NonClosableConnection(new org.h2.jdbc.JdbcConnection("jdbc:h2:file:" + + databaseFile.getAbsolutePath(), + new Properties(), AntiVPN.getInstance().getVpnConfig().getUsername(), + AntiVPN.getInstance().getVpnConfig().getPassword(), false)); + conn.setAutoCommit(true); + Query.use(conn); + AntiVPN.getInstance().getExecutor().log("Connection to H2 has been established."); + } catch (SQLException ex) { + AntiVPN.getInstance().getExecutor().logException("H2 exception on initialize", ex); + if(ex instanceof JdbcSQLFeatureNotSupportedException + || ex instanceof JdbcSQLNonTransientConnectionException) { + AntiVPN.getInstance().getExecutor() + .log("H2 database file is incompatible with this version of AntiVPN. " + + "Backing up old database file..."); + backupOldDB(dbFile, dataFolder); + initH2(); + didRetry = true; + } else { + AntiVPN.getInstance().getExecutor().logException("Failed to load H2 database: " + ex.getCause().toString(), ex); + } + } catch (Exception e) { + AntiVPN.getInstance().getExecutor().logException("Failed to load H2 database: " + e.getMessage(), e); + AntiVPN.getInstance().getExecutor().log(Level.INFO, "TIP: Try deleting the plugin folder and restarting your server!"); + } + } + + private static void backupOldDB(File dbFile, File dataFolder) { + if (dbFile.exists()) { + try { + // Optional: Make backup first + File backupDir = new File(dataFolder, "backups"); + if(backupDir.mkdirs()) { + AntiVPN.getInstance().getExecutor().log("Created backup directory"); + } else { + AntiVPN.getInstance().getExecutor().log("Backup directory already exists"); + } + File backupFile = new File(backupDir, "database.mv.db.backup_" + System.currentTimeMillis()); + Files.copy(dbFile.toPath(), backupFile.toPath()); + + // Actually delete the file + if (!dbFile.delete()) { + // If normal delete fails, try force delete on JVM exit + dbFile.deleteOnExit(); + AntiVPN.getInstance().getExecutor().log("Could not delete database file - will try again on shutdown"); + } else { + AntiVPN.getInstance().getExecutor().log("Successfully deleted incompatible database file"); + } + } catch (IOException ex) { + AntiVPN.getInstance().getExecutor().logException("Failed to handle database file", ex); + } + } + } + + public static void use() { + try { + init(); + } catch (Exception e) { + AntiVPN.getInstance().getExecutor().logException(e); + } + } + + public static void shutdown() { + try { + if(conn != null && !conn.isClosed()) { + if(conn instanceof NonClosableConnection) { + ((NonClosableConnection)conn).shutdown(); + } else conn.close(); + conn = null; + } + } catch (Exception e) { + AntiVPN.getInstance().getExecutor().logException(e); + } + } + + public static boolean isClosed() { + if(conn == null) + return true; + + try { + return conn.isClosed(); + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor().logException(e); + return true; + } + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/NonClosableConnection.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/NonClosableConnection.java new file mode 100644 index 0000000..38668af --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/NonClosableConnection.java @@ -0,0 +1,122 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.brighten.antivpn.database.sql.utils; + +import java.sql.*; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +/** + * A wrapper around a {@link Connection} which blocks usage of the default {@link #close()} method. + */ +public class NonClosableConnection implements Connection { + private final Connection delegate; + + public NonClosableConnection(Connection delegate) { + this.delegate = delegate; + } + + /** + * Actually {@link #close() closes} the underlying connection. + */ + public final void shutdown() throws SQLException { + this.delegate.close(); + } + + @Override + public final void close() throws SQLException { + // do nothing + } + + @Override + public final boolean isWrapperFor(Class iface) throws SQLException { + return iface.isInstance(this.delegate) || this.delegate.isWrapperFor(iface); + } + + @SuppressWarnings("unchecked") + @Override + public final T unwrap(Class iface) throws SQLException { + if (iface.isInstance(this.delegate)) { + return (T) this.delegate; + } + return this.delegate.unwrap(iface); + } + + // Forward to the delegate connection + @Override public Statement createStatement() throws SQLException { return this.delegate.createStatement(); } + @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return this.delegate.prepareStatement(sql); } + @Override public CallableStatement prepareCall(String sql) throws SQLException { return this.delegate.prepareCall(sql); } + @Override public String nativeSQL(String sql) throws SQLException { return this.delegate.nativeSQL(sql); } + @Override public void setAutoCommit(boolean autoCommit) throws SQLException { this.delegate.setAutoCommit(autoCommit); } + @Override public boolean getAutoCommit() throws SQLException { return this.delegate.getAutoCommit(); } + @Override public void commit() throws SQLException { this.delegate.commit(); } + @Override public void rollback() throws SQLException { this.delegate.rollback(); } + @Override public boolean isClosed() throws SQLException { return this.delegate.isClosed(); } + @Override public DatabaseMetaData getMetaData() throws SQLException { return this.delegate.getMetaData(); } + @Override public void setReadOnly(boolean readOnly) throws SQLException { this.delegate.setReadOnly(readOnly); } + @Override public boolean isReadOnly() throws SQLException { return this.delegate.isReadOnly(); } + @Override public void setCatalog(String catalog) throws SQLException { this.delegate.setCatalog(catalog); } + @Override public String getCatalog() throws SQLException { return this.delegate.getCatalog(); } + @Override public void setTransactionIsolation(int level) throws SQLException { this.delegate.setTransactionIsolation(level); } + @Override public int getTransactionIsolation() throws SQLException { return this.delegate.getTransactionIsolation(); } + @Override public SQLWarning getWarnings() throws SQLException { return this.delegate.getWarnings(); } + @Override public void clearWarnings() throws SQLException { this.delegate.clearWarnings(); } + @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return this.delegate.createStatement(resultSetType, resultSetConcurrency); } + @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return this.delegate.prepareStatement(sql, resultSetType, resultSetConcurrency); } + @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return this.delegate.prepareCall(sql, resultSetType, resultSetConcurrency); } + @Override public Map> getTypeMap() throws SQLException { return this.delegate.getTypeMap(); } + @Override public void setTypeMap(Map> map) throws SQLException { this.delegate.setTypeMap(map); } + @Override public void setHoldability(int holdability) throws SQLException { this.delegate.setHoldability(holdability); } + @Override public int getHoldability() throws SQLException { return this.delegate.getHoldability(); } + @Override public Savepoint setSavepoint() throws SQLException { return this.delegate.setSavepoint(); } + @Override public Savepoint setSavepoint(String name) throws SQLException { return this.delegate.setSavepoint(name); } + @Override public void rollback(Savepoint savepoint) throws SQLException { this.delegate.rollback(savepoint); } + @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { this.delegate.releaseSavepoint(savepoint); } + @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return this.delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); } + @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return this.delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } + @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return this.delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } + @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return this.delegate.prepareStatement(sql, autoGeneratedKeys); } + @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return this.delegate.prepareStatement(sql, columnIndexes); } + @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return this.delegate.prepareStatement(sql, columnNames); } + @Override public Clob createClob() throws SQLException { return this.delegate.createClob(); } + @Override public Blob createBlob() throws SQLException { return this.delegate.createBlob(); } + @Override public NClob createNClob() throws SQLException { return this.delegate.createNClob(); } + @Override public SQLXML createSQLXML() throws SQLException { return this.delegate.createSQLXML(); } + @Override public boolean isValid(int timeout) throws SQLException { return this.delegate.isValid(timeout); } + @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { this.delegate.setClientInfo(name, value); } + @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { this.delegate.setClientInfo(properties); } + @Override public String getClientInfo(String name) throws SQLException { return this.delegate.getClientInfo(name); } + @Override public Properties getClientInfo() throws SQLException { return this.delegate.getClientInfo(); } + @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return this.delegate.createArrayOf(typeName, elements); } + @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return this.delegate.createStruct(typeName, attributes); } + @Override public void setSchema(String schema) throws SQLException { this.delegate.setSchema(schema); } + @Override public String getSchema() throws SQLException { return this.delegate.getSchema(); } + @Override public void abort(Executor executor) throws SQLException { this.delegate.abort(executor); } + @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { this.delegate.setNetworkTimeout(executor, milliseconds); } + @Override public int getNetworkTimeout() throws SQLException { return this.delegate.getNetworkTimeout(); } + +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java new file mode 100644 index 0000000..ac57c27 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java @@ -0,0 +1,20 @@ +package dev.brighten.antivpn.database.sql.utils; + +import java.sql.Connection; +import java.sql.SQLException; + +public class Query { + private static Connection conn; + + public static void use(Connection conn) { + Query.conn = conn; + } + + public static ExecutableStatement prepare(String query) { + try { + return new ExecutableStatement(conn.prepareStatement(query)); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/ResultSetIterator.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/ResultSetIterator.java new file mode 100644 index 0000000..e99cd7c --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/ResultSetIterator.java @@ -0,0 +1,7 @@ +package dev.brighten.antivpn.database.sql.utils; + +import java.sql.ResultSet; + +public interface ResultSetIterator { + void next(ResultSet rs) throws Exception; +} diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java rename to Common/Source/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java rename to Common/Source/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java rename to Common/Source/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/Relocate.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/Relocate.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/depends/Relocate.java rename to Common/Source/src/main/java/dev/brighten/antivpn/depends/Relocate.java diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/Repository.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/Repository.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/depends/Repository.java rename to Common/Source/src/main/java/dev/brighten/antivpn/depends/Repository.java diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java rename to Common/Source/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java diff --git a/Common/src/main/java/dev/brighten/antivpn/message/MessageHandler.java b/Common/Source/src/main/java/dev/brighten/antivpn/message/MessageHandler.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/message/MessageHandler.java rename to Common/Source/src/main/java/dev/brighten/antivpn/message/MessageHandler.java diff --git a/Common/src/main/java/dev/brighten/antivpn/message/VpnString.java b/Common/Source/src/main/java/dev/brighten/antivpn/message/VpnString.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/message/VpnString.java rename to Common/Source/src/main/java/dev/brighten/antivpn/message/VpnString.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/ConfigDefault.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/ConfigDefault.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/ConfigDefault.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/ConfigDefault.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/EvictingMap.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/EvictingMap.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/EvictingMap.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/EvictingMap.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/MiscUtils.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/MiscUtils.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/MiscUtils.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/MiscUtils.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Preconditions.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/Preconditions.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/Preconditions.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/Preconditions.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/StringUtil.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/StringUtil.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/StringUtil.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/StringUtil.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Supplier.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/Supplier.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/Supplier.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/Supplier.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Suppliers.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/Suppliers.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/Suppliers.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/Suppliers.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Tuple.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/Tuple.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/Tuple.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/Tuple.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/config/Configuration.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/config/Configuration.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/config/Configuration.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/config/Configuration.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/config/ConfigurationProvider.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/config/ConfigurationProvider.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/config/ConfigurationProvider.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/config/ConfigurationProvider.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/config/YamlConfiguration.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/config/YamlConfiguration.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/config/YamlConfiguration.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/config/YamlConfiguration.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/CDL.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/CDL.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/CDL.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/CDL.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/Cookie.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/Cookie.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/Cookie.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/Cookie.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/CookieList.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/CookieList.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/CookieList.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/CookieList.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/HTTP.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/HTTP.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/HTTP.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/HTTP.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/HTTPTokener.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/HTTPTokener.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/HTTPTokener.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/HTTPTokener.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONArray.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONArray.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONArray.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONArray.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONException.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONException.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONException.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONException.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONML.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONML.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONML.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONML.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONObject.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONObject.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONObject.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONObject.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONString.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONString.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONString.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONString.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONStringer.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONStringer.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONStringer.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONStringer.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONTokener.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONTokener.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONTokener.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONTokener.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JSONWriter.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONWriter.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JSONWriter.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JSONWriter.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/JsonReader.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JsonReader.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/JsonReader.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/JsonReader.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/XML.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/XML.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/XML.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/XML.java diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/json/XMLTokener.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/json/XMLTokener.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/utils/json/XMLTokener.java rename to Common/Source/src/main/java/dev/brighten/antivpn/utils/json/XMLTokener.java diff --git a/Common/src/main/java/dev/brighten/antivpn/web/FunkemunkyAPI.java b/Common/Source/src/main/java/dev/brighten/antivpn/web/FunkemunkyAPI.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/web/FunkemunkyAPI.java rename to Common/Source/src/main/java/dev/brighten/antivpn/web/FunkemunkyAPI.java diff --git a/Common/src/main/java/dev/brighten/antivpn/web/objects/QueryResponse.java b/Common/Source/src/main/java/dev/brighten/antivpn/web/objects/QueryResponse.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/web/objects/QueryResponse.java rename to Common/Source/src/main/java/dev/brighten/antivpn/web/objects/QueryResponse.java diff --git a/Common/src/main/java/dev/brighten/antivpn/web/objects/VPNResponse.java b/Common/Source/src/main/java/dev/brighten/antivpn/web/objects/VPNResponse.java similarity index 100% rename from Common/src/main/java/dev/brighten/antivpn/web/objects/VPNResponse.java rename to Common/Source/src/main/java/dev/brighten/antivpn/web/objects/VPNResponse.java diff --git a/Common/src/main/resources/config.yml b/Common/Source/src/main/resources/config.yml similarity index 100% rename from Common/src/main/resources/config.yml rename to Common/Source/src/main/resources/config.yml diff --git a/Common/loader-utils/pom.xml b/Common/loader-utils/pom.xml new file mode 100644 index 0000000..9763696 --- /dev/null +++ b/Common/loader-utils/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + dev.brighten.antivpn + Common + 1.9.4 + + + loader-utils + + + 17 + 17 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + org.projectlombok + lombok + 1.18.30 + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/JarInJarClassLoader.java b/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/JarInJarClassLoader.java new file mode 100644 index 0000000..4d8a4c3 --- /dev/null +++ b/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/JarInJarClassLoader.java @@ -0,0 +1,158 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.brighten.antivpn.loader; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Arrays; + +/** + * Classloader that can load a jar from within another jar file. + * + *

The "loader" jar contains the loading code & public API classes + * and is class-loaded by the platform.

+ * + *

The inner "plugin" jar contains the plugin itself and is class-loaded + * by the loading code & this classloader.

+ */ +public class JarInJarClassLoader extends URLClassLoader { + static { + ClassLoader.registerAsParallelCapable(); + } + + /** + * Creates a new jar-in-jar class loader. + * + * @param loaderClassLoader the loader plugin's classloader (setup and created by the platform) + * @param jarResourcePath the path to the jar-in-jar resource within the loader jar + * @throws LoadingException if something unexpectedly bad happens + */ + public JarInJarClassLoader(ClassLoader loaderClassLoader, String... jarResourcePath) throws LoadingException { + super(Arrays.stream(jarResourcePath) + .map(path -> extractJar(loaderClassLoader, path)) + .toArray(URL[]::new), loaderClassLoader); + } + + public void addJarToClasspath(URL url) { + addURL(url); + } + + public void deleteJarResource() { + URL[] urls = getURLs(); + if (urls.length == 0) { + return; + } + + try { + Path path = Paths.get(urls[0].toURI()); + Files.deleteIfExists(path); + } catch (Exception e) { + // ignore + } + } + + /** + * Creates a new plugin instance. + * + * @param bootstrapClass the name of the bootstrap plugin class + * @param loaderPluginType the type of the loader plugin, the only parameter of the bootstrap + * plugin constructor + * @param loaderPlugin the loader plugin instance + * @param the type of the loader plugin + * @return the instantiated bootstrap plugin + */ + public LoaderBootstrap instantiatePlugin(String bootstrapClass, Class loaderPluginType, T loaderPlugin) throws LoadingException { + Class plugin; + try { + plugin = loadClass(bootstrapClass).asSubclass(LoaderBootstrap.class); + } catch (ReflectiveOperationException e) { + throw new LoadingException("Unable to load bootstrap class", e); + } + + Constructor constructor; + try { + constructor = plugin.getConstructor(loaderPluginType); + } catch (ReflectiveOperationException e) { + throw new LoadingException("Unable to get bootstrap constructor", e); + } + + try { + return constructor.newInstance(loaderPlugin); + } catch (ReflectiveOperationException e) { + throw new LoadingException("Unable to create bootstrap plugin instance", e); + } + } + + /** + * Extracts the "jar-in-jar" from the loader plugin into a temporary file, + * then returns a URL that can be used by the {@link JarInJarClassLoader}. + * + * @param loaderClassLoader the classloader for the "host" loader plugin + * @param jarResourcePath the inner jar resource path + * @return a URL to the extracted file + */ + private static URL extractJar(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException { + // get the jar-in-jar resource + URL jarInJar = loaderClassLoader.getResource(jarResourcePath); + if (jarInJar == null) { + throw new LoadingException("Could not locate jar-in-jar"); + } + + // create a temporary file + // on posix systems; by default, this is only read/writable by the process owner + Path path; + try { + path = Files.createTempFile(jarResourcePath, ".jar.tmp"); + } catch (IOException e) { + throw new LoadingException("Unable to create a temporary file", e); + } + + // mark that the file should be deleted on exit + path.toFile().deleteOnExit(); + + // copy the jar-in-jar to the temporary file path + try (InputStream in = jarInJar.openStream()) { + Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new LoadingException("Unable to copy jar-in-jar to temporary path", e); + } + + try { + return path.toUri().toURL(); + } catch (MalformedURLException e) { + throw new LoadingException("Unable to get URL from path", e); + } + } + +} diff --git a/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/LoaderBootstrap.java b/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/LoaderBootstrap.java new file mode 100644 index 0000000..38cbb29 --- /dev/null +++ b/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/LoaderBootstrap.java @@ -0,0 +1,41 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.brighten.antivpn.loader; + +import java.io.File; + +/** + * Minimal bootstrap plugin, called by the loader plugin. + */ +public interface LoaderBootstrap { + + void onLoad(File dataFolder); + + default void onEnable() {} + + default void onDisable() {} + +} diff --git a/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/LoadingException.java b/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/LoadingException.java new file mode 100644 index 0000000..191ae03 --- /dev/null +++ b/Common/loader-utils/src/main/java/dev/brighten/antivpn/loader/LoadingException.java @@ -0,0 +1,41 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.brighten.antivpn.loader; + +/** + * Runtime exception used if there is a problem during loading + */ +public class LoadingException extends RuntimeException { + + public LoadingException(String message) { + super(message); + } + + public LoadingException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/Common/pom.xml b/Common/pom.xml index cca88e4..dff27de 100644 --- a/Common/pom.xml +++ b/Common/pom.xml @@ -5,8 +5,13 @@ AntiVPN dev.brighten.antivpn - 2.0.0-SNAPSHOT + 1.9.4 + pom + + loader-utils + Source + 4.0.0 Common @@ -16,156 +21,4 @@ 17 - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - 17 - 17 - -XDignore.symbol.file - - - org.projectlombok - lombok - 1.18.30 - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - package - - shade - - - true - - - org.yaml.snakeyaml - dev.brighten.antivpn.shaded.org.yaml.snakeyaml - - - dev.brighten.antivpn.depends.Relocate - dev.brighten.antivpn.depends.MavenLibraries - - - - com.github.benmanes.caffeine - dev.brighten.antivpn.shaded.com.github.benmanes.caffeine - - - org.h2 - dev.brighten.antivpn.shaded.org.h2 - - - dev.brighten.antivpn.depends.Relocate - dev.brighten.antivpn.depends.MavenLibraries - - - - org.bson - dev.brighten.antivpn.shaded.org.bson - - - dev.brighten.antivpn.depends.Relocate - dev.brighten.antivpn.depends.MavenLibraries - - - - com.mongodb.client - dev.brighten.antivpn.shaded.com.mongodb.client - - - dev.brighten.antivpn.depends.Relocate - dev.brighten.antivpn.depends.MavenLibraries - - - - org.postgresql - dev.brighten.antivpn.shaded.org.postgresql - - - dev.brighten.antivpn.depends.Relocate - dev.brighten.antivpn.depends.MavenLibraries - - - - - - - - - - - src/main/resources - true - - - - - - - funkemunky-releases - https://nexus.funkemunky.cc/content/repositories/releases/ - - - - - - org.xerial - sqlite-jdbc - 3.48.0.0 - provided - - - org.ow2.asm - asm - 9.8 - compile - - - org.ow2.asm - asm-commons - 9.8 - compile - - - org.yaml - snakeyaml - 2.2 - compile - - - com.github.ben-manes.caffeine - caffeine - 3.1.8 - provided - - - org.jetbrains - annotations - 24.0.1 - - - org.mongodb - mongodb-driver-sync - 5.5.0 - provided - - - org.postgresql - postgresql - 42.7.6 - provided - - - \ No newline at end of file diff --git a/Common/src/main/java/dev/brighten/antivpn/database/Database.java b/Common/src/main/java/dev/brighten/antivpn/database/Database.java deleted file mode 100644 index 3d5514a..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/Database.java +++ /dev/null @@ -1,39 +0,0 @@ -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/mongodb/MongoDatabase.java b/Common/src/main/java/dev/brighten/antivpn/database/mongodb/MongoDatabase.java deleted file mode 100644 index 0cdf156..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/MongoDatabase.java +++ /dev/null @@ -1,229 +0,0 @@ -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 deleted file mode 100644 index 7fe29f8..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/AlertsUser.java +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index eb24bb5..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/CidrWhitelist.java +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index cc81709..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserIpResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index e2e01c4..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/mongodb/records/UserWhitelist.java +++ /dev/null @@ -1,6 +0,0 @@ -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/postgres/PostgresDatabase.java b/Common/src/main/java/dev/brighten/antivpn/database/postgres/PostgresDatabase.java deleted file mode 100644 index e21a3e0..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/postgres/PostgresDatabase.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.brighten.antivpn.database.postgres; - -import dev.brighten.antivpn.AntiVPN; -import dev.brighten.antivpn.database.sqllite.LiteDatabase; - -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Properties; - -public class PostgresDatabase extends LiteDatabase { - - @Override - public void init() { - - try { - Class.forName("org.postgresql.Driver"); - } catch (ClassNotFoundException e) { - AntiVPN.getInstance().getExecutor().logException(e); - return; - } - String databaseName = AntiVPN.getInstance().getVpnConfig().getDatabaseName(); - String ipAddress = AntiVPN.getInstance().getVpnConfig().getIp(); - int port = AntiVPN.getInstance().getVpnConfig().getPort(); - String username = AntiVPN.getInstance().getVpnConfig().getUsername(); - String password = AntiVPN.getInstance().getVpnConfig().getPassword(); - - String url = String.format("jdbc:postgresql://%s:%s/%s", ipAddress, port, databaseName); - - Properties properties = new Properties(); - - properties.setProperty("user", username); - properties.setProperty("password", password); - properties.setProperty("ssl", "true"); - - try { - connection = DriverManager.getConnection(url, properties); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - - } -} 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 deleted file mode 100644 index da2e8e7..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/LiteDatabase.java +++ /dev/null @@ -1,261 +0,0 @@ -package dev.brighten.antivpn.database.sqllite; - -import dev.brighten.antivpn.AntiVPN; -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; - -@SuppressWarnings("SqlSourceToSinkFlow") -public class LiteDatabase implements dev.brighten.antivpn.database.Database { - - protected Connection connection; - - @Override - public Optional getStoredResponse(String ip) { - return Optional.empty(); - } - - @Override - public void cacheResponse(VPNResponse toCache) { - String jsonResponse; - try { - jsonResponse = toCache.toJson().toString(); - } catch (JSONException e) { - AntiVPN.getInstance().getExecutor().logException(e); - return; - } - - String hashedIp = StringUtil.getHash(toCache.getIp()); - - try { - statement("INSERT INTO vpn_responses (ip, date, response) VALUES (?, ?, ?)", hashedIp, System.currentTimeMillis(), jsonResponse); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @Override - public void deleteResponse(String ip) { - String hashedIp = StringUtil.getHash(ip); - - try { - statement("DELETE FROM vpn_responses WHERE ip = ?", hashedIp); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @SuppressWarnings("SqlWithoutWhere") - @Override - public void clearResponses() { - try { - statement("DELETE FROM vpn_responses"); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @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())) { - return result.next(); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - return false; - } - - @Override - public boolean isWhitelisted(String ip) { - CIDRUtils cidr; - BigDecimal start, end; - try { - cidr = new CIDRUtils(ip); - - start = IpUtils.getIpDecimal(cidr.getStartAddress().getHostAddress()).orElseThrow(); - end = IpUtils.getIpDecimal(cidr.getEndAddress().getHostAddress()).orElseThrow(); - } catch (UnknownHostException e) { - AntiVPN.getInstance().getExecutor().logException(e); - return false; - } - - try(ResultSet result = query("SELECT * FROM whitelist " + - "WHERE minimum >= ? AND maximum <= ?", start, end)) { - return result.next(); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - return false; - } - - @Override - public void addWhitelist(UUID uuid) { - try { - statement("INSERT INTO whitelist (uuid) VALUES (?)", uuid.toString()); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @Override - public void addWhitelist(String cidr) { - CIDRUtils cidrUtils; - BigDecimal start, end; - try { - cidrUtils = new CIDRUtils(cidr); - - start = IpUtils.getIpDecimal(cidrUtils.getStartAddress().getHostAddress()).orElseThrow(); - end = IpUtils.getIpDecimal(cidrUtils.getEndAddress().getHostAddress()).orElseThrow(); - } catch (UnknownHostException e) { - AntiVPN.getInstance().getExecutor().logException(e); - return; - } - - try { - statement("INSERT INTO whitelist (minimum, maximum) VALUES (?, ?)", start, end); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @Override - public void removeWhitelist(UUID uuid) { - try { - statement("DELETE FROM whitelist WHERE uuid = ?", uuid.toString()); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @Override - public void removeWhitelist(String cidr) { - CIDRUtils cidrUtils; - BigDecimal start, end; - try { - cidrUtils = new CIDRUtils(cidr); - - start = IpUtils.getIpDecimal(cidrUtils.getStartAddress().getHostAddress()).orElseThrow(); - end = IpUtils.getIpDecimal(cidrUtils.getEndAddress().getHostAddress()).orElseThrow(); - } catch (UnknownHostException e) { - AntiVPN.getInstance().getExecutor().logException(e); - return; - } - - try { - statement("DELETE FROM whitelist WHERE minimum = ? AND maximum = ?", start, end); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @Override - public boolean getAlertsState(UUID uuid) { - try(ResultSet result = query("SELECT * FROM alerts WHERE uuid = ?", uuid.toString())) { - return result.next(); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - return false; - } - - @Override - public void updateAlertsState(UUID uuid, boolean state) { - try { - statement("DELETE FROM alerts WHERE uuid = ?", uuid.toString()); - if(state) { - statement("INSERT INTO alerts (uuid) VALUES (?)", - uuid.toString()); - } - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - @Override - public void init() { - String url = "jdbc:sqlite:" + AntiVPN.getInstance().getPluginFolder().toPath() + "/database.db"; - - try { - Class.forName("org.sqlite.JDBC"); - - this.connection = DriverManager.getConnection(url); - - setupTable(); - } catch (SQLException | ClassNotFoundException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } - - public void setupTable() throws SQLException { - // 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(); - } - } - - public Connection connection() { - return connection; - } - - @Override - public void shutdown() { - try { - connection.close(); - } catch (SQLException e) { - AntiVPN.getInstance().getExecutor().logException(e); - } - } -} 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 deleted file mode 100644 index eb0b561..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/Version.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.brighten.antivpn.database.sqllite.version; - -import dev.brighten.antivpn.database.sqllite.LiteDatabase; -import dev.brighten.antivpn.database.sqllite.version.impl.First; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -public interface Version { - void update(LiteDatabase database) throws SQLException; - int versionNumber(); - - List versions = new ArrayList<>(); - - static void register() { - versions.add(new First()); - } -} 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 deleted file mode 100644 index 508ad62..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/database/sqllite/version/impl/First.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.brighten.antivpn.database.sqllite.version.impl; - -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(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 - public int versionNumber() { - return 1; - } -} diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/CIDRUtils.java b/Common/src/main/java/dev/brighten/antivpn/utils/CIDRUtils.java deleted file mode 100644 index 26b3ca9..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/utils/CIDRUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -/* -* The MIT License -* -* Copyright (c) 2013 Edin Dazdarevic (edin.dazdarevic@gmail.com) - -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: - -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. - -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -* -* */ - -package dev.brighten.antivpn.utils; - -import lombok.Getter; - -import java.math.BigInteger; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** - * A class that enables to get an IP range from CIDR specification. It supports - * both IPv4 and IPv6. - */ -@Getter -public class CIDRUtils { - private final String cidr; - - private final InetAddress inetAddress; - - private InetAddress startAddress; - private InetAddress endAddress; - private final int prefixLength; - - - public CIDRUtils(String cidr) throws UnknownHostException { - - this.cidr = cidr; - - /* split CIDR to address and prefix part */ - if (this.cidr.contains("/")) { - int index = this.cidr.indexOf("/"); - String addressPart = this.cidr.substring(0, index); - String networkPart = this.cidr.substring(index + 1); - - inetAddress = InetAddress.getByName(addressPart); - prefixLength = Integer.parseInt(networkPart); - - calculate(); - } else { - throw new IllegalArgumentException("not an valid CIDR format!"); - } - } - - - private void calculate() throws UnknownHostException { - - ByteBuffer maskBuffer; - int targetSize; - if (inetAddress.getAddress().length == 4) { - maskBuffer = - ByteBuffer - .allocate(4) - .putInt(-1); - targetSize = 4; - } else { - maskBuffer = ByteBuffer.allocate(16) - .putLong(-1L) - .putLong(-1L); - targetSize = 16; - } - - BigInteger mask = (new BigInteger(1, maskBuffer.array())).not().shiftRight(prefixLength); - - ByteBuffer buffer = ByteBuffer.wrap(inetAddress.getAddress()); - BigInteger ipVal = new BigInteger(1, buffer.array()); - - BigInteger startIp = ipVal.and(mask); - BigInteger endIp = startIp.add(mask.not()); - - byte[] startIpArr = toBytes(startIp.toByteArray(), targetSize); - byte[] endIpArr = toBytes(endIp.toByteArray(), targetSize); - - this.startAddress = InetAddress.getByAddress(startIpArr); - this.endAddress = InetAddress.getByAddress(endIpArr); - - } - - private byte[] toBytes(byte[] array, int targetSize) { - int counter = 0; - List newArr = new ArrayList(); - while (counter < targetSize && (array.length - 1 - counter >= 0)) { - newArr.add(0, array[array.length - 1 - counter]); - counter++; - } - - int size = newArr.size(); - for (int i = 0; i < (targetSize - size); i++) { - - newArr.add(0, (byte) 0); - } - - byte[] ret = new byte[newArr.size()]; - for (int i = 0; i < newArr.size(); i++) { - ret[i] = newArr.get(i); - } - return ret; - } - - public String getNetworkAddress() { - - return this.startAddress.getHostAddress(); - } - - public String getBroadcastAddress() { - return this.endAddress.getHostAddress(); - } - - public boolean isInRange(String ipAddress) throws UnknownHostException { - InetAddress address = InetAddress.getByName(ipAddress); - BigInteger start = new BigInteger(1, this.startAddress.getAddress()); - BigInteger end = new BigInteger(1, this.endAddress.getAddress()); - BigInteger target = new BigInteger(1, address.getAddress()); - - int st = start.compareTo(target); - int te = target.compareTo(end); - - return (st == -1 || st == 0) && (te == -1 || te == 0); - } -} diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/IpUtils.java b/Common/src/main/java/dev/brighten/antivpn/utils/IpUtils.java deleted file mode 100644 index 2ead854..0000000 --- a/Common/src/main/java/dev/brighten/antivpn/utils/IpUtils.java +++ /dev/null @@ -1,93 +0,0 @@ -package dev.brighten.antivpn.utils; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Optional; - -public class IpUtils { - public static Optional getIpDecimal(String address) { - try { - InetAddress inet = InetAddress.getByName(address); - - if(inet instanceof Inet4Address) { - return Optional.of(BigDecimal.valueOf(ipv4ToLong(address))); - } return Optional.of(new BigDecimal(ipv6ToDecimalFormat(address))); - } catch(Exception e) { - return Optional.empty(); - } - } - - public static long ipv4ToLong(String address) { - String[] addrArray = address.split("\\."); - - long ipDecimal = 0; - - for (int i = 0; i < addrArray.length; i++) { - - int power = 3 - i; - ipDecimal += ((Integer.parseInt(addrArray[i]) % 256 * Math.pow(256, power))); - } - - return ipDecimal; - } - - public static String getIpv4(long ip) { - StringBuilder sb = new StringBuilder(15); - - for (int i = 0; i < 4; i++) { - sb.insert(0, ip & 0xff); - - if (i < 3) { - sb.insert(0, '.'); - } - - ip >>= 8; - } - - return sb.toString(); - } - - public static boolean isIpv4(BigDecimal ip) { - return ip.compareTo(BigDecimal.valueOf(4294967295L)) <= 0; - } - - public static boolean isIpv6(BigDecimal ip) { - return ip.compareTo(BigDecimal.valueOf(4294967295L)) > 0; - } - public static boolean isIpv4(String ip) { - return ip.matches("^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$"); - } - - public static boolean isNotIp(String ip) { - return !isIpv4(ip) && !isIpv6(ip); - } - - public static boolean isIpv6(String ip) { - return ip.matches("^([0-9a-fA-F]{1,4}:){7}([0-9a-fA-F]{1,4}|:)$|^(([0-9a-fA-F]{1,4}:){0,6}([0-9a-fA-F]{1,4}|:))?(::([0-9a-fA-F]{1,4}:){0,5}([0-9a-fA-F]{1,4}|:))?$"); - } - - public static String getIpv4(BigDecimal ip) { - try { - return Inet4Address.getByAddress(ip.toBigInteger().toByteArray()).getHostAddress(); - } catch (UnknownHostException e) { - return "Error"; - } - } - - public static String getIpv6(BigDecimal ip) { - try { - return Inet6Address.getByAddress(ip.toBigInteger().toByteArray()).getHostAddress(); - } catch (UnknownHostException e) { - return "Error"; - } - } - - public static BigInteger ipv6ToDecimalFormat(String ipAddress) throws UnknownHostException { - return new BigInteger(1, Inet6Address.getByName(ipAddress).getAddress()); - } - -} diff --git a/Sponge/pom.xml b/Sponge/pom.xml index 3b89136..c9ce89b 100644 --- a/Sponge/pom.xml +++ b/Sponge/pom.xml @@ -5,7 +5,7 @@ AntiVPN dev.brighten.antivpn - 2.0.0-SNAPSHOT + 1.9.4 4.0.0 @@ -31,8 +31,8 @@ dev.brighten.antivpn - Common - 2.0.0-SNAPSHOT + Source + 1.9.4 compile @@ -42,22 +42,29 @@ compile - org.xerial - sqlite-jdbc - 3.48.0.0 + org.mongodb + mongo-java-driver + 3.12.14 compile - org.postgresql - postgresql - 42.7.6 + com.mysql + mysql-connector-j + 9.1.0 + jar + compile + + + com.h2database + h2 + 2.2.220 compile - 21 - 21 + 17 + 17 @@ -67,8 +74,8 @@ maven-compiler-plugin 3.13.0 - 21 - 21 + 17 + 17 -XDignore.symbol.file @@ -127,8 +134,26 @@ - org.postgresql - dev.brighten.antivpn.shaded.org.postgresql + com.mongodb + dev.brighten.antivpn.shaded.com.mongodb + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + com.mysql.cj + dev.brighten.antivpn.shaded.com.mysql.cj + + + dev.brighten.antivpn.depends.Relocate + dev.brighten.antivpn.depends.MavenLibraries + + + + com.mysql.jdbc + dev.brighten.antivpn.shaded.com.mysql.jdbc dev.brighten.antivpn.depends.Relocate diff --git a/Universal/pom.xml b/Universal/pom.xml index 66e21c3..44ff3b2 100644 --- a/Universal/pom.xml +++ b/Universal/pom.xml @@ -6,7 +6,7 @@ dev.brighten.antivpn AntiVPN - 2.0.0-SNAPSHOT + 1.9.4 Universal @@ -14,30 +14,25 @@ 17 17 + UTF-8 - dev.brighten.antivpn - Common + dev.brighten.antivpn.bukkit + Loader ${project.version} compile dev.brighten.antivpn - Bukkit + VelocityLoader ${project.version} compile - dev.brighten.antivpn - Bungee - ${project.version} - compile - - - dev.brighten.antivpn - Velocity + dev.brighten.antivpn.bungee + BungeeLoader ${project.version} compile @@ -60,6 +55,10 @@ false + + antivpn-source.jarinjar + ${project.parent.basedir}/Common/Source/target/Source-${project.version}.jar + diff --git a/Velocity/VelocityLoader/pom.xml b/Velocity/VelocityLoader/pom.xml new file mode 100644 index 0000000..1a52d54 --- /dev/null +++ b/Velocity/VelocityLoader/pom.xml @@ -0,0 +1,109 @@ + + + 4.0.0 + + dev.brighten.antivpn + Velocity + 1.9.4 + ../pom.xml + + + VelocityLoader + + + 17 + 17 + UTF-8 + + + + + velocity + https://nexus.funkemunky.cc/repository/papermc-public/ + + + + + + com.velocitypowered + velocity-api + 3.4.0-SNAPSHOT + provided + + + org.bstats + bstats-velocity + 2.2.1 + compile + + + dev.brighten.antivpn + loader-utils + 1.9.4 + compile + + + dev.brighten.antivpn + VelocityPlugin + 1.9.4 + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + antivpn-velocity.jarinjar + ${project.parent.basedir}/VelocityPlugin/target/VelocityPlugin-${project.version}.jar + + + + + org.bstats + + dev.brighten.antivpn.velocity.org.bstats + + + org.yaml.snakeyaml + dev.brighten.antivpn.shaded.org.yaml.snakeyaml + + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/Velocity/VelocityLoader/src/main/java/dev/brighten/antivpn/velocity/VelocityPluginLoader.java b/Velocity/VelocityLoader/src/main/java/dev/brighten/antivpn/velocity/VelocityPluginLoader.java new file mode 100644 index 0000000..9c7add0 --- /dev/null +++ b/Velocity/VelocityLoader/src/main/java/dev/brighten/antivpn/velocity/VelocityPluginLoader.java @@ -0,0 +1,51 @@ +package dev.brighten.antivpn.velocity; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; +import com.velocitypowered.api.plugin.Plugin; +import com.velocitypowered.api.plugin.annotation.DataDirectory; +import com.velocitypowered.api.proxy.ProxyServer; +import dev.brighten.antivpn.loader.JarInJarClassLoader; +import dev.brighten.antivpn.loader.LoaderBootstrap; +import org.bstats.velocity.Metrics; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +@Plugin(id = "kaurivpn", name = "KauriVPN", version = "1.7.1", authors = {"funkemunky"}) +public class VelocityPluginLoader { + + private static final String JAR_NAME = "antivpn-velocity.jarinjar"; + private static final String SOURCE_NAME = "antivpn-source.jarinjar"; + private static final String BOOTSTRAP_CLASS = "dev.brighten.antivpn.velocity.VelocityPlugin"; + + private final LoaderBootstrap plugin; + + @Inject + public VelocityPluginLoader(ProxyServer server, Logger logger, @DataDirectory Path path, Metrics.Factory metricsFactory) { + Map, Object> instances = new HashMap<>(); + instances.put(ProxyServer.class, server); + instances.put(Logger.class, logger); + instances.put(Path.class, path); + instances.put(String.class, metricsFactory); + instances.put(LoaderBootstrap.class, this); + JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME, SOURCE_NAME); + this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, Map.class, instances); + plugin.onLoad(path.toFile()); + } + + @Subscribe + public void onInit(ProxyInitializeEvent event) { + plugin.onEnable(); + } + + @Subscribe + public void onDisable(ProxyShutdownEvent event) { + plugin.onDisable(); + } + +} diff --git a/Velocity/src/main/resources/velocity-plugin.json b/Velocity/VelocityLoader/src/main/resources/velocity-plugin.json similarity index 75% rename from Velocity/src/main/resources/velocity-plugin.json rename to Velocity/VelocityLoader/src/main/resources/velocity-plugin.json index 1c547a3..d23d87a 100644 --- a/Velocity/src/main/resources/velocity-plugin.json +++ b/Velocity/VelocityLoader/src/main/resources/velocity-plugin.json @@ -1 +1 @@ -{"id":"kaurivpn","name":"KauriVPN","version":"${project.version}","authors":["funkemunky"],"dependencies":[],"main":"dev.brighten.antivpn.velocity.VelocityPlugin"} +{"id":"kaurivpn","name":"KauriVPN","version":"${project.version}","authors":["funkemunky"],"dependencies":[],"main":"dev.brighten.antivpn.velocity.VelocityPluginLoader"} diff --git a/Velocity/VelocityPlugin/pom.xml b/Velocity/VelocityPlugin/pom.xml new file mode 100644 index 0000000..d475480 --- /dev/null +++ b/Velocity/VelocityPlugin/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + + dev.brighten.antivpn + AntiVPN + 1.9.4 + ../../pom.xml + + + VelocityPlugin + + + 17 + 17 + UTF-8 + + + + + velocity + https://nexus.funkemunky.cc/repository/papermc-public/ + + + + + + com.velocitypowered + velocity-api + 3.4.0-SNAPSHOT + provided + + + dev.brighten.antivpn + Source + 1.9.4 + provided + + + org.bstats + bstats-velocity + 2.2.1 + compile + + + dev.brighten.antivpn + loader-utils + 1.9.4 + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + -XDignore.symbol.file + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + + org.bstats + + dev.brighten.antivpn.velocity.org.bstats + + + org.yaml.snakeyaml + dev.brighten.antivpn.shaded.org.yaml.snakeyaml + + + + + + package + + shade + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java similarity index 77% rename from Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java rename to Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java index d88f731..242379b 100644 --- a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java +++ b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java @@ -20,14 +20,14 @@ public class VelocityListener extends VPNExecutor { @Override public void registerListeners() { VelocityPlugin.INSTANCE.getServer().getEventManager() - .register(VelocityPlugin.INSTANCE, this); + .register(VelocityPlugin.INSTANCE.getPluginInstance(), this); - VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE, DisconnectEvent.class, + VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE.getPluginInstance(), DisconnectEvent.class, event -> AntiVPN.getInstance() .getPlayerExecutor() .unloadPlayer(event.getPlayer().getUniqueId())); - VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE, LoginEvent.class, + VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE.getPluginInstance(), LoginEvent.class, event -> { APIPlayer player = AntiVPN.getInstance().getPlayerExecutor().getPlayer(event.getPlayer().getUniqueId()) .orElse(new OfflinePlayer( @@ -49,7 +49,7 @@ public class VelocityListener extends VPNExecutor { LegacyComponentSerializer.builder() .character('&') .build().deserialize(AntiVPN.getInstance().getVpnConfig() - .getCountryVanillaKickReason() + .countryVanillaKickReason() .replace("%player%", event.getPlayer().getUsername()) .replace("%country%", instantResult.response().getCountryName()) .replace("%code%", instantResult.response().getCountryCode())))); @@ -59,7 +59,7 @@ public class VelocityListener extends VPNExecutor { event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder() .character('&') .build().deserialize(AntiVPN.getInstance().getVpnConfig() - .getKickMessage() + .getKickString() .replace("%player%", event.getPlayer().getUsername()) .replace("%country%", instantResult.response().getCountryName()) .replace("%code%", instantResult.response().getCountryCode())))); @@ -77,12 +77,12 @@ public class VelocityListener extends VPNExecutor { private void handleDeniedTasks(LoginEvent event, CheckResult checkResult, boolean deniedOnLogin) { VPNResponse result = checkResult.response(); //Ensuring the user wishes to alert to staff - if (AntiVPN.getInstance().getVpnConfig().isAlertToStaff()) + if (AntiVPN.getInstance().getVpnConfig().alertToStaff()) AntiVPN.getInstance().getPlayerExecutor().getOnlinePlayers().stream() .filter(APIPlayer::isAlertsEnabled) .forEach(pl -> pl.sendMessage(dev.brighten.antivpn.AntiVPN.getInstance().getVpnConfig() - .getAlertMsg() + .alertMessage() .replace("%player%", event.getPlayer().getUsername()) .replace("%reason%", @@ -92,41 +92,41 @@ public class VelocityListener extends VPNExecutor { .replace("%city%", result.getCity()))); - if (deniedOnLogin) return; + if(deniedOnLogin) return; //In case the user wants to run their own commands instead of using the // built in kicking - if (AntiVPN.getInstance().getVpnConfig().isKickPlayers()) { + if(AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect()) { switch (checkResult.resultType()) { case DENIED_PROXY -> VelocityPlugin.INSTANCE.getServer().getScheduler() - .buildTask(VelocityPlugin.INSTANCE, () -> - event.getPlayer().disconnect(LegacyComponentSerializer.builder() - .character('&') - .build().deserialize(AntiVPN.getInstance().getVpnConfig() - .getKickMessage() - .replace("%player%", event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())))) - .delay(1, TimeUnit.SECONDS).schedule(); + .buildTask(VelocityPlugin.INSTANCE.getPluginInstance(), () -> + event.getPlayer().disconnect(LegacyComponentSerializer.builder() + .character('&') + .build().deserialize(AntiVPN.getInstance().getVpnConfig() + .getKickString() + .replace("%player%", event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())))) + .delay(1, TimeUnit.SECONDS).schedule(); case DENIED_COUNTRY -> VelocityPlugin.INSTANCE.getServer().getScheduler() - .buildTask(VelocityPlugin.INSTANCE, () -> - event.getPlayer().disconnect(LegacyComponentSerializer.builder() - .character('&') - .build().deserialize(AntiVPN.getInstance().getVpnConfig() - .getCountryVanillaKickReason() - .replace("%player%", event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())))) - .delay(1, TimeUnit.SECONDS).schedule(); + .buildTask(VelocityPlugin.INSTANCE.getPluginInstance(), () -> + event.getPlayer().disconnect(LegacyComponentSerializer.builder() + .character('&') + .build().deserialize(AntiVPN.getInstance().getVpnConfig() + .countryVanillaKickReason() + .replace("%player%", event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())))) + .delay(1, TimeUnit.SECONDS).schedule(); } } - if (!AntiVPN.getInstance().getVpnConfig().isCommandsEnabled()) return; + if(!AntiVPN.getInstance().getVpnConfig().runCommands()) return; switch (checkResult.resultType()) { case DENIED_PROXY -> { - for (String command : AntiVPN.getInstance().getVpnConfig().getCommands()) { + for (String command : AntiVPN.getInstance().getVpnConfig().commands()) { VelocityPlugin.INSTANCE.getServer().getCommandManager() .executeAsync(VelocityPlugin.INSTANCE.getServer() .getConsoleCommandSource(), @@ -144,7 +144,7 @@ public class VelocityListener extends VPNExecutor { } } case DENIED_COUNTRY -> { - for (String cmd : AntiVPN.getInstance().getVpnConfig().getCountryKickCommands()) { + for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) { final String formattedCommand = StringUtil .translateAlternateColorCodes('&', StringUtil.varReplace( @@ -162,12 +162,7 @@ public class VelocityListener extends VPNExecutor { } } } - } - @Override - public void shutdown() { - VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE, this); - super.shutdown(); } @Override @@ -196,7 +191,7 @@ public class VelocityListener extends VPNExecutor { @Override public void disablePlugin() { - VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE, this); + VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE.getPluginInstance(), this); VelocityPlugin.INSTANCE.getServer().getCommandManager().unregister("antivpn"); } } diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayer.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayer.java similarity index 100% rename from Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayer.java rename to Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayer.java diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayerExecutor.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayerExecutor.java similarity index 100% rename from Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayerExecutor.java rename to Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlayerExecutor.java diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java similarity index 53% rename from Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java rename to Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java index 926b35d..29d3dc4 100644 --- a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java +++ b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java @@ -1,28 +1,26 @@ package dev.brighten.antivpn.velocity; -import com.google.inject.Inject; -import com.velocitypowered.api.event.Subscribe; -import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; -import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; -import com.velocitypowered.api.plugin.Plugin; -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.Database; -import dev.brighten.antivpn.database.sqllite.LiteDatabase; +import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.local.H2VPN; +import dev.brighten.antivpn.database.mongo.MongoVPN; +import dev.brighten.antivpn.database.sql.MySqlVPN; +import dev.brighten.antivpn.loader.LoaderBootstrap; import dev.brighten.antivpn.velocity.command.VelocityCommand; import lombok.Getter; import org.bstats.charts.SimplePie; import org.bstats.velocity.Metrics; import javax.annotation.Nullable; +import java.io.File; import java.nio.file.Path; +import java.util.Map; import java.util.logging.Logger; @Getter -@Plugin(id = "kaurivpn", name = "KauriVPN", version = "1.7.1", authors = {"funkemunky"}) -public class VelocityPlugin { +public class VelocityPlugin implements LoaderBootstrap { private final ProxyServer server; private final Logger logger; @@ -35,16 +33,37 @@ public class VelocityPlugin { public static VelocityPlugin INSTANCE; - @Inject - public VelocityPlugin(ProxyServer server, Logger logger, @DataDirectory Path path, Metrics.Factory metricsFactory) { - this.server = server; - this.logger = logger; - this.configDir = path; - this.metricsFactory = metricsFactory; + private final Object pluginInstance; + + public VelocityPlugin(Map, Object> objectsMap) { + this.server = (ProxyServer) objectsMap.get(ProxyServer.class); + this.logger = (Logger) objectsMap.get(Logger.class); + this.configDir = (Path) objectsMap.get(Path.class); + this.metricsFactory = (Metrics.Factory) objectsMap.get(String.class); + this.pluginInstance = objectsMap.get(LoaderBootstrap.class); } - @Subscribe - public void onInit(ProxyInitializeEvent event) { + private String getDatabaseType() { + VPNDatabase database = AntiVPN.getInstance().getDatabase(); + + if(database instanceof H2VPN) { + return "H2"; + } else if(database instanceof MySqlVPN) { + return "MySQL"; + } else if(database instanceof MongoVPN) { + return "MongoDB"; + } else { + return "No-Database"; + } + } + + @Override + public void onLoad(File dataFolder) { + + } + + @Override + public void onEnable() { INSTANCE = this; logger.info("Loading config..."); @@ -52,9 +71,10 @@ public class VelocityPlugin { logger.info("Starting AntiVPN services..."); AntiVPN.start(new VelocityListener(), new VelocityPlayerExecutor(), configDir.toFile()); - if(AntiVPN.getInstance().getVpnConfig().isMetrics()) { + + if(AntiVPN.getInstance().getVpnConfig().metrics()) { logger.info("Starting metrics..."); - metrics = metricsFactory.make(this, 12791); + metrics = metricsFactory.make(pluginInstance, 12791); metrics.addCustomChart(new SimplePie("database_used", this::getDatabaseType)); } @@ -62,12 +82,12 @@ public class VelocityPlugin { logger.info("Registering commands..."); for (Command command : AntiVPN.getInstance().getCommands()) { server.getCommandManager().register(server.getCommandManager().metaBuilder(command.name()) - .aliases(command.aliases()).build(), new VelocityCommand(command)); + .aliases(command.aliases()).build(), new VelocityCommand(command)); } } - @Subscribe - public void onDisable(ProxyShutdownEvent event) { + @Override + public void onDisable() { logger.info("Disabling AntiVPN..."); AntiVPN.getInstance().getExecutor().log("Disabling AntiVPN..."); @@ -82,12 +102,4 @@ public class VelocityPlugin { INSTANCE = null; logger.info("Disabled AntiVPN."); } - - private String getDatabaseType() { - Database database = AntiVPN.getInstance().getDatabase(); - - if(database instanceof LiteDatabase) { - return "SQLLite"; - } return "No-Database"; - } } diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommand.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommand.java similarity index 100% rename from Velocity/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommand.java rename to Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommand.java diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommandExecutor.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommandExecutor.java similarity index 100% rename from Velocity/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommandExecutor.java rename to Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/command/VelocityCommandExecutor.java diff --git a/Velocity/pom.xml b/Velocity/pom.xml index 98026cc..a88309c 100644 --- a/Velocity/pom.xml +++ b/Velocity/pom.xml @@ -5,8 +5,9 @@ AntiVPN dev.brighten.antivpn - 2.0.0-SNAPSHOT + 1.9.4 + pom 4.0.0 Velocity @@ -15,80 +16,4 @@ 17 17 - - - - velocity - https://nexus.velocitypowered.com/repository/maven-public/ - - - - - - com.velocitypowered - velocity-api - 3.4.0-SNAPSHOT - provided - - - dev.brighten.antivpn - Common - 2.0.0-SNAPSHOT - provided - - - org.bstats - bstats-velocity - 2.2.1 - compile - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - 17 - 17 - -XDignore.symbol.file - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - - org.bstats - - dev.brighten.antivpn.velocity.org.bstats - - - org.yaml.snakeyaml - dev.brighten.antivpn.shaded.org.yaml.snakeyaml - - - - - - package - - shade - - - - - - - - src/main/resources - true - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 267fed9..f895638 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ dev.brighten.antivpn AntiVPN pom - 2.0.0-SNAPSHOT + 1.9.4 Common @@ -16,6 +16,10 @@ Velocity Sponge Universal + Velocity/VelocityLoader + Velocity/VelocityPlugin + Bungee/BungeeLoader + Bungee/BungeePlugin