Implementing database and allowlist system

This commit is contained in:
Dawson Hessler
2021-06-18 16:37:09 -04:00
parent 09482b970b
commit 0a7c2c0207
19 changed files with 796 additions and 26 deletions
@@ -0,0 +1,160 @@
package dev.brighten.antivpn.database.sql;
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.utils.VPNResponse;
import lombok.SneakyThrows;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class MySqlVPN implements VPNDatabase {
private Thread whitelistedThread;
public MySqlVPN() {
whitelistedThread = new Thread(() -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(8));
} catch (InterruptedException e) {
e.printStackTrace();
}
while(true) {
//Updating from database
if(AntiVPN.getInstance().getConfig().isDatabaseEnabled()) {
AntiVPN.getInstance().getExecutor().getWhitelisted().clear();
AntiVPN.getInstance().getExecutor().getWhitelisted()
.addAll(AntiVPN.getInstance().getDatabase().getAllWhitelisted());
}
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(4));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
whitelistedThread.start();;
}
@Override
public Optional<VPNResponse> getStoredResponse(String ip) {
if(!AntiVPN.getInstance().getConfig().isDatabaseEnabled()) return Optional.empty();
ResultSet rs = Query.prepare("select * from `responses` where `ip` = ? limit 1")
.append(ip).executeQuery();
try {
if(rs != null && !rs.wasNull() && rs.next()) {
VPNResponse response = 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"),
rs.getBoolean("proxy"), rs.getBoolean("cached"), true,
rs.getDouble("latitude"), rs.getDouble("longitude"),
System.currentTimeMillis(), -1);
return Optional.of(response);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return Optional.empty();
}
/*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().getConfig().isDatabaseEnabled()) return;
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();
}
@SneakyThrows
@Override
public boolean isWhitelisted(UUID uuid) {
if(!AntiVPN.getInstance().getConfig().isDatabaseEnabled()) return false;
ResultSet set = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1")
.append(uuid.toString()).executeQuery();
return set != null && !set.wasNull() && set.next() && set.getString("uuid") != null;
}
@Override
public void setWhitelisted(UUID uuid, boolean whitelisted) {
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 List<UUID> getAllWhitelisted() {
List<UUID> uuids = new ArrayList<>();
ResultSet set = Query.prepare("select uuid from `whitelisted`").executeQuery();
try {
while(set.next()) {
uuids.add(UUID.fromString(set.getString("uuid")));
}
} catch(SQLException e) {
e.printStackTrace();
}
return uuids;
}
@Override
public void getStoredResponseAsync(String ip, Consumer<Optional<VPNResponse>> result) {
VPNExecutor.threadExecutor.execute(() -> result.accept(getStoredResponse(ip)));
}
@Override
public void isWhitelistedAsync(UUID uuid, Consumer<Boolean> result) {
VPNExecutor.threadExecutor.execute(() -> result.accept(isWhitelisted(uuid)));
}
@Override
public void init() {
if(!AntiVPN.getInstance().getConfig().isDatabaseEnabled()) return;
System.out.println("Initializing MySQL...");
MySQL.init();
System.out.println("Creating tables...");
Query.prepare("create table if not exists `whitelisted` (`uuid` varchar(36) not null)").execute();
Query.prepare("create table if not exists `responses` (`ip` varchar(45) not null, `asn` varchar(12)," +
"`countryName` varchar(64), `countryCode` varchar(10), `city` varchar(64), `timeZone` varchar(64), " +
"`method` varchar(32), `isp` varchar(32), `proxy` boolean, `cached` boolean, `inserted` timestamp," +
"`latitude` double, `longitude` double)").execute();
System.out.println("Creating indexes...");
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();
}
@Override
public void shutdown() {
if(!AntiVPN.getInstance().getConfig().isDatabaseEnabled()) return;
MySQL.shutdown();
}
}
@@ -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;
}
}
@@ -0,0 +1,51 @@
package dev.brighten.antivpn.database.sql.utils;
import dev.brighten.antivpn.AntiVPN;
import java.sql.Connection;
import java.sql.DriverManager;
public class MySQL {
private static Connection conn;
public static void init() {
try {
if (conn == null || conn.isClosed()) {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://" + AntiVPN.getInstance().getConfig().getIp()
+ ":" + AntiVPN.getInstance().getConfig().getPort()
+ "/?useSSL=true&autoReconnect=true",
AntiVPN.getInstance().getConfig().getUsername(),
AntiVPN.getInstance().getConfig().getPassword());
conn.setAutoCommit(true);
Query.use(conn);
Query.prepare("CREATE DATABASE IF NOT EXISTS `"
+ AntiVPN.getInstance().getConfig().getDatabaseName() + "`").execute();
Query.prepare("USE `" + AntiVPN.getInstance().getConfig().getDatabaseName() + "`").execute();
System.out.println("Connection to MySQL has been established.");
}
} catch (Exception e) {
System.out.println("Failed to load mysql: " + e.getMessage());
e.printStackTrace();
}
}
public static void use() {
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void shutdown() {
try {
if(conn != null && !conn.isClosed()) {
conn.close();
conn = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,25 @@
package dev.brighten.antivpn.database.sql.utils;
import lombok.SneakyThrows;
import java.sql.Connection;
public class Query {
private static Connection conn;
public static void use(Connection conn) {
Query.conn = conn;
}
@SneakyThrows
public static ExecutableStatement prepare(String query) {
return new ExecutableStatement(conn.prepareStatement(query));
}
@SneakyThrows
public static ExecutableStatement prepare(String query, Connection con) {
return new ExecutableStatement(con.prepareStatement(query));
}
}
@@ -0,0 +1,7 @@
package dev.brighten.antivpn.database.sql.utils;
import java.sql.ResultSet;
public interface ResultSetIterator {
void next(ResultSet rs) throws Exception;
}