From 65a2c5de15eea64aaffe26e8c8b06e3985e4b4e4 Mon Sep 17 00:00:00 2001 From: samo_lego <34912839+samolego@users.noreply.github.com> Date: Fri, 10 Apr 2020 14:57:15 +0200 Subject: [PATCH 1/2] Starting with leveldb database system. --- build.gradle | 9 +- .../org/samo_lego/simpleauth/SimpleAuth.java | 5 +- .../simpleauth/commands/AuthCommand.java | 3 +- .../simpleauth/commands/ChangepwCommand.java | 1 - .../simpleauth/commands/RegisterCommand.java | 3 +- .../commands/UnregisterCommand.java | 2 +- .../database/SimpleAuthDatabase.java | 135 +++++------------- 7 files changed, 48 insertions(+), 110 deletions(-) diff --git a/build.gradle b/build.gradle index 98772bd..8b89ebe 100644 --- a/build.gradle +++ b/build.gradle @@ -26,9 +26,12 @@ dependencies { implementation 'de.mkammerer:argon2-jvm:2.6' include 'de.mkammerer:argon2-jvm:2.6' - // JDBC SQLite Driver - implementation group:'org.xerial', name:'sqlite-jdbc', version:'3.8.11.2' - include group:'org.xerial', name:'sqlite-jdbc', version:'3.8.11.2' + // leveldb + implementation group: 'org.iq80.leveldb', name: 'leveldb', version: '0.12' + implementation group: 'org.iq80.leveldb', name: 'leveldb-api', version: '0.12' + include group: 'org.iq80.leveldb', name: 'leveldb', version: '0.12' + include group: 'org.iq80.leveldb', name: 'leveldb-api', version: '0.12' + // JNA lib include 'net.java.dev.jna:jna:5.5.0' diff --git a/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java b/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java index bd40a99..525d2a3 100644 --- a/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java +++ b/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java @@ -52,15 +52,14 @@ public class SimpleAuth implements DedicatedServerModInitializer { LOGGER.info("[SimpleAuth] This mod wouldn't exist without the awesome Fabric Community. TYSM guys!"); // Creating data directory (database and config files are stored there) - File file = new File(gameDirectory + "/mods/SimpleAuth"); + File file = new File(gameDirectory + "/mods/SimpleAuth/levelDBStore"); if (!file.exists() && !file.mkdir()) LOGGER.error("[SimpleAuth] Error creating directory!"); // Loading config config = AuthConfig.load(new File(gameDirectory + "/mods/SimpleAuth/config.json")); // Connecting to db db.openConnection(); - // Making a table in the database - db.makeTable(); + // Registering the commands CommandRegistry.INSTANCE.register(false, dispatcher -> { diff --git a/src/main/java/org/samo_lego/simpleauth/commands/AuthCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/AuthCommand.java index 6d892d1..c23f082 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/AuthCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/AuthCommand.java @@ -112,7 +112,6 @@ public class AuthCommand { SimpleAuth.db.update( uuid, - username, AuthHelper.hashPass(pass.toCharArray()) ); if(sender != null) @@ -124,7 +123,7 @@ public class AuthCommand { } private static int removeAccount(ServerCommandSource source, String uuid, String username) { Entity sender = source.getEntity(); - SimpleAuth.db.delete(uuid, username); + SimpleAuth.db.delete(uuid); // TODO -> Kick player that was unregistered? diff --git a/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java index fcf12d0..73b5c39 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java @@ -57,7 +57,6 @@ public class ChangepwCommand { else if (AuthHelper.checkPass(player.getUuidAsString(), oldPass.toCharArray())) { SimpleAuth.db.update( player.getUuidAsString(), - null, AuthHelper.hashPass(newPass.toCharArray()) ); player.sendMessage(passwordUpdated); diff --git a/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java index 602fd85..132b0d3 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java @@ -7,7 +7,6 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import org.samo_lego.simpleauth.SimpleAuth; -import org.samo_lego.simpleauth.utils.AuthConfig; import org.samo_lego.simpleauth.utils.AuthHelper; import static com.mojang.brigadier.arguments.StringArgumentType.getString; @@ -51,7 +50,7 @@ public class RegisterCommand { } else if(pass1.equals(pass2)) { String hash = AuthHelper.hashPass(pass1.toCharArray()); - if (SimpleAuth.db.registerUser(player.getUuidAsString(), source.getName(), hash)) { + if (SimpleAuth.db.registerUser(player.getUuidAsString(), hash)) { SimpleAuth.authenticatePlayer(player, registerSuccess); return 1; } diff --git a/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java index 696d499..f7e74d0 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java @@ -46,7 +46,7 @@ public class UnregisterCommand { return 0; } else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray())) { - SimpleAuth.db.delete(player.getUuidAsString(), null); + SimpleAuth.db.delete(player.getUuidAsString()); player.sendMessage(accountDeleted); return 1; } diff --git a/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java b/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java index c32bd04..5c9ee3c 100644 --- a/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java +++ b/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java @@ -2,146 +2,85 @@ package org.samo_lego.simpleauth.database; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.iq80.leveldb.DB; +import org.iq80.leveldb.Options; import org.samo_lego.simpleauth.SimpleAuth; -import java.sql.*; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; -/** - * Thanks to - * @author sqlitetutorial.net - */ +import static org.iq80.leveldb.impl.Iq80DBFactory.bytes; +import static org.iq80.leveldb.impl.Iq80DBFactory.factory; public class SimpleAuthDatabase { private static final Logger LOGGER = LogManager.getLogger(); + private DB levelDBStore; // Connects to the DB - private Connection conn; - public void openConnection() { - // SQLite connection string - String url = "jdbc:sqlite:" + SimpleAuth.gameDirectory + "/mods/SimpleAuth/players.db"; try { - conn = DriverManager.getConnection(url); - } catch (SQLException e) { + + Options options = new Options(); + levelDBStore = factory.open(new File(SimpleAuth.gameDirectory + "/mods/SimpleAuth/levelDBStore"), options); + } catch (Error | IOException e) { LOGGER.error("[SimpleAuth] " + e.getMessage()); } } // Closing connection public void close() { - if (conn != null) { + if (levelDBStore != null) { try { - conn.close(); + levelDBStore.close(); LOGGER.info("[SimpleAuth] Database connection closed successfully."); - } catch (SQLException e) { + } catch (Error | IOException e) { LOGGER.info("[SimpleAuth] Error: " + e.getMessage()); } } } - // If the mod runs for the first time, we need to create the DB table - public void makeTable() { - try { - // Creating database table if it doesn't exist yet - String sql = "CREATE TABLE IF NOT EXISTS users (\n" + - " `UserID` INTEGER PRIMARY KEY AUTOINCREMENT,\n" + - " `UUID` BINARY(16) NOT NULL,\n" + - " `Username` VARCHAR(16) NOT NULL,\n" + - " `Password` VARCHAR(64) NOT NULL,\n" + - " UNIQUE (`UUID`)\n" + - " UNIQUE (`Username`)\n" + - ");"; - Statement stmt = conn.createStatement(); - stmt.execute(sql); - } catch (SQLException e) { - LOGGER.error("[SimpleAuth] Error: " + e.getMessage()); - } - } - // When player registers, we insert the data into DB - public boolean registerUser(String uuid, String username, String password) { - String sql = "INSERT INTO users(uuid, username, password) VALUES(?,?,?)"; - String sqlCheck = "SELECT UUID " - + "FROM users WHERE UUID = ?"; - - try (PreparedStatement pstmt = conn.prepareStatement(sql); - PreparedStatement pstmtCheck = conn.prepareStatement(sqlCheck)) { - - pstmtCheck.setString(1, uuid); - ResultSet rs = pstmtCheck.executeQuery(); - - // Getting the password - //String dbUuid = null; - try { - rs.getString("UUID"); - return false; - } catch(SQLException ignored) { - // User is not registered - } finally { - pstmt.setString(1, uuid); - pstmt.setString(2, username); - pstmt.setString(3, password); - - pstmt.executeUpdate(); + public boolean registerUser(String uuid, String password) { + System.out.println(Arrays.toString(levelDBStore.get(bytes("UUID:" + uuid)))); + try { + if(levelDBStore.get(bytes("UUID:" + uuid)) == null) { + levelDBStore.put(bytes("UUID:" + uuid), bytes("password:" + password)); + return true; } - return true; - } catch (SQLException e) { + return false; + } catch (Error e) { LOGGER.error("[SimpleAuth] Register error: " + e.getMessage()); return false; } } // Deletes row containing the username provided - public void delete(String uuid, String username) { - String sql = "DELETE FROM users WHERE uuid = ? OR username = ?"; - - try (PreparedStatement pstmt = conn.prepareStatement(sql)) { - - // set the corresponding param - pstmt.setString(1, uuid); - pstmt.setString(2, username); - // execute the delete statement - pstmt.executeUpdate(); - - } catch (SQLException e) { + public void delete(String uuid) { + try { + levelDBStore.delete(bytes("UUID:" + uuid)); + } catch (Error e) { LOGGER.error("[SimpleAuth] " + e.getMessage()); } } // Updates the password of the user - public void update(String uuid, String username, String pass) { - String sql = "UPDATE users SET password = ? " - + "WHERE uuid = ? OR username = ?"; - - try (PreparedStatement pstmt = conn.prepareStatement(sql)) { - - // set the corresponding param - pstmt.setString(1, pass); - pstmt.setString(2, uuid); - pstmt.setString(3, username); - - // update - pstmt.executeUpdate(); - } catch (SQLException e) { + public void update(String uuid, String password) { + try { + levelDBStore.put(bytes("UUID:" + uuid),bytes("password:" + password)); + } catch (Error e) { LOGGER.error("[SimpleAuth] " + e.getMessage()); } } // Gets the hashed password from DB public String getPassword(String uuid){ - String sql = "SELECT UUID, Password " - + "FROM users WHERE UUID = ?"; - String pass = null; - - try (PreparedStatement pstmt = conn.prepareStatement(sql)) { - // Setting statement - pstmt.setString(1, uuid); - ResultSet rs = pstmt.executeQuery(); - - // Getting the password - pass = rs.getString("Password"); - } catch (SQLException e) { + String password = null; + try { + // Gets password from db and removes "password:" prefix from it + password = new String(levelDBStore.get(bytes("UUID:" + uuid))).substring(9); + } catch (Error e) { LOGGER.error("[SimpleAuth] Error getting password: " + e.getMessage()); } - return pass; + return password; } } \ No newline at end of file From 1083665fac5b5bb6551c8f505fd9ff8ba1921f9b Mon Sep 17 00:00:00 2001 From: samo_lego <34912839+samolego@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:27:49 +0200 Subject: [PATCH 2/2] Checking if user is registered, finalising leveldb. --- .../simpleauth/commands/ChangepwCommand.java | 2 +- .../simpleauth/commands/LoginCommand.java | 13 ++++++------ .../commands/UnregisterCommand.java | 2 +- .../database/SimpleAuthDatabase.java | 21 +++++++++++++------ .../simpleauth/utils/AuthConfig.java | 1 + .../simpleauth/utils/AuthHelper.java | 14 ++++++++----- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java index 73b5c39..e401266 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/ChangepwCommand.java @@ -54,7 +54,7 @@ public class ChangepwCommand { player.sendMessage(cannotChangePassword); return 0; } - else if (AuthHelper.checkPass(player.getUuidAsString(), oldPass.toCharArray())) { + else if (AuthHelper.checkPass(player.getUuidAsString(), oldPass.toCharArray()) == 1) { SimpleAuth.db.update( player.getUuidAsString(), AuthHelper.hashPass(newPass.toCharArray()) diff --git a/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java index cf269f9..ed8b032 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java @@ -18,6 +18,7 @@ public class LoginCommand { private static Text enterPassword = new LiteralText(SimpleAuth.config.lang.enterPassword); private static Text wrongPassword = new LiteralText(SimpleAuth.config.lang.wrongPassword); private static Text alreadyAuthenticated = new LiteralText(SimpleAuth.config.lang.alreadyAuthenticated); + private static Text notRegistered = new LiteralText(SimpleAuth.config.lang.notRegistered); private static Text loginTriesExceeded = new LiteralText(SimpleAuth.config.lang.loginTriesExceeded); private static Text successfullyAuthenticated = new LiteralText(SimpleAuth.config.lang.successfullyAuthenticated); private static int maxLoginTries = SimpleAuth.config.main.maxLoginTries; @@ -48,16 +49,14 @@ public class LoginCommand { player.networkHandler.disconnect(loginTriesExceeded); return 0; } - else if(SimpleAuth.config.main.enableGlobalPassword) { - if (AuthHelper.checkPass(null, pass.toCharArray())) { - SimpleAuth.authenticatePlayer(player, successfullyAuthenticated); - return 1; - } - } - else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray())) { + else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray()) == 1) { SimpleAuth.authenticatePlayer(player, successfullyAuthenticated); return 1; } + else if(AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray()) == -1) { + player.sendMessage(notRegistered); + return 0; + } // Kicking the player out else if(maxLoginTries == 1) { SimpleAuth.deauthenticatePlayer(player); diff --git a/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java index f7e74d0..ed7984a 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/UnregisterCommand.java @@ -45,7 +45,7 @@ public class UnregisterCommand { player.sendMessage(cannotUnregister); return 0; } - else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray())) { + else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray()) == 1) { SimpleAuth.db.delete(player.getUuidAsString()); player.sendMessage(accountDeleted); return 1; diff --git a/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java b/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java index 5c9ee3c..e03146f 100644 --- a/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java +++ b/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java @@ -3,6 +3,7 @@ package org.samo_lego.simpleauth.database; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.iq80.leveldb.DB; +import org.iq80.leveldb.DBException; import org.iq80.leveldb.Options; import org.samo_lego.simpleauth.SimpleAuth; @@ -41,9 +42,8 @@ public class SimpleAuthDatabase { // When player registers, we insert the data into DB public boolean registerUser(String uuid, String password) { - System.out.println(Arrays.toString(levelDBStore.get(bytes("UUID:" + uuid)))); try { - if(levelDBStore.get(bytes("UUID:" + uuid)) == null) { + if(!this.isRegistered(uuid)) { levelDBStore.put(bytes("UUID:" + uuid), bytes("password:" + password)); return true; } @@ -54,6 +54,16 @@ public class SimpleAuthDatabase { } } + // Checks if user is registered + private boolean isRegistered(String uuid) { + try { + return levelDBStore.get(bytes("UUID:" + uuid)) != null; + } catch (DBException e) { + LOGGER.error("[SimpleAuth] " + e.getMessage()); + } + return false; + } + // Deletes row containing the username provided public void delete(String uuid) { try { @@ -74,13 +84,12 @@ public class SimpleAuthDatabase { // Gets the hashed password from DB public String getPassword(String uuid){ - String password = null; try { - // Gets password from db and removes "password:" prefix from it - password = new String(levelDBStore.get(bytes("UUID:" + uuid))).substring(9); + if(this.isRegistered(uuid)) // Gets password from db and removes "password:" prefix from it + return new String(levelDBStore.get(bytes("UUID:" + uuid))).substring(9); } catch (Error e) { LOGGER.error("[SimpleAuth] Error getting password: " + e.getMessage()); } - return password; + return ""; } } \ No newline at end of file diff --git a/src/main/java/org/samo_lego/simpleauth/utils/AuthConfig.java b/src/main/java/org/samo_lego/simpleauth/utils/AuthConfig.java index 5dd5dc6..5d12846 100644 --- a/src/main/java/org/samo_lego/simpleauth/utils/AuthConfig.java +++ b/src/main/java/org/samo_lego/simpleauth/utils/AuthConfig.java @@ -90,6 +90,7 @@ public class AuthConfig { public String accountDeleted = "§aYour account was successfully deleted!"; public String configurationReloaded = "§aConfiguration file was reloaded successfully."; public String successfulPortalRescue = "§aYou were rescued from nether portal successfully!"; + public String notRegistered = "§6This account is not yet registered! Type `/register` first"; } private static final Logger LOGGER = LogManager.getLogger(); private static final Gson gson = new GsonBuilder() diff --git a/src/main/java/org/samo_lego/simpleauth/utils/AuthHelper.java b/src/main/java/org/samo_lego/simpleauth/utils/AuthHelper.java index bd8dcc1..45cbf2e 100644 --- a/src/main/java/org/samo_lego/simpleauth/utils/AuthHelper.java +++ b/src/main/java/org/samo_lego/simpleauth/utils/AuthHelper.java @@ -12,15 +12,17 @@ public class AuthHelper { // Creating the instance private static Argon2 argon2 = Argon2Factory.create(); - public static boolean checkPass(String uuid, char[] pass) { + // Returns 1 if password is correct, 0 if not + // and -1 if user is not registered yet + public static int checkPass(String uuid, char[] pass) { if(SimpleAuth.config.main.enableGlobalPassword) { // We have global password enabled try { - return argon2.verify(SimpleAuth.config.main.globalPassword, pass); + return argon2.verify(SimpleAuth.config.main.globalPassword, pass) ? 1 : 0; } catch (Error e) { LOGGER.error("[SimpleAuth] Argon2 error: " + e); - return false; + return 0; } finally { // Wipe confidential data argon2.wipeArray(pass); @@ -30,11 +32,13 @@ public class AuthHelper { try { // Hashed password from DB String hashed = SimpleAuth.db.getPassword(uuid); + if(hashed.equals("")) + return -1; // User is not yet registered // Verify password - return argon2.verify(hashed, pass); + return argon2.verify(hashed, pass) ? 1 : 0; } catch (Error e) { LOGGER.error("[SimpleAuth] error: " + e); - return false; + return 0; } finally { // Wipe confidential data argon2.wipeArray(pass);