diff --git a/src/io/github/packserver/Cedar/AuthenticationManager.java b/src/io/github/packserver/Cedar/AuthenticationManager.java index 1b99e54e47a475a9add8c465f6a72e798b470647..33b47e0517e91dfd19f5c089941d48d661ab5ea3 100644 --- a/src/io/github/packserver/Cedar/AuthenticationManager.java +++ b/src/io/github/packserver/Cedar/AuthenticationManager.java @@ -2,12 +2,16 @@ package io.github.packserver.Cedar; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; +import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import java.security.SecureRandom; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Objects; +import java.util.UUID; + +import static io.github.packserver.Cedar.ErrorsAndTheirMeanings.*; /** * Handles authentication via QR code. @@ -15,11 +19,7 @@ import java.util.Objects; */ class AuthenticationManager { - private final Player p; - - AuthenticationManager(Player p) { - this.p = p; - } + private final Main plugin = Main.plugin; // This is the format that the data is stored in the Redis. class StorageFormat { @@ -33,7 +33,7 @@ class AuthenticationManager { /** * Send authentication data to player */ - Integer generateAuthString() { + Integer generateAuthString(Player p) { StorageFormat toBeStored = new StorageFormat(); // Generate random number toBeStored.code = 100000 + new SecureRandom().nextInt(900000); @@ -53,16 +53,40 @@ class AuthenticationManager { return toBeStored.code; } + String continueAuth(WebsocketServer.ParseWithCode jsonResult) { + String potentialPlayerUUID = jsonResult.uuid; + if (Main.DEBUG) { + Main.plugin.getLogger().info("I found " + potentialPlayerUUID + " as the player's UUID."); + } + // Check if it's an actual UUID. + UUID playerUUID; + try { + playerUUID = UUID.fromString(potentialPlayerUUID); + } catch (IllegalArgumentException e) { + return returnJSON(USER_UUID_INVALID); + } + + // Check UUID and such + String result = checkPlayer(playerUUID); + if (!(result.equals(returnJSON(SUCCESS)))) { + return result; + } + + // It appears to be valid. Validate the code. + result = checkCode(jsonResult.code, playerUUID); + return result; + // TODO: add more checking + } + /** * Verify code. - * @param givenCode Code recieved from client + * @param givenCode Code received from client * @return Status */ - Integer checkCode(Integer givenCode) { - Main.plugin.getLogger().info("I ran! xdxdxdxdxd"); + private String checkCode(Integer givenCode, UUID playerUUID) { // Get data - String jsonFromStorage = new RedisFactory().getString("app_code_" + p.getUniqueId()); - Main.plugin.getLogger().info("Retrived " + jsonFromStorage); + String jsonFromStorage = new RedisFactory().getString("app_code_" + playerUUID.toString()); + Main.plugin.getLogger().info("Retrieved " + jsonFromStorage); Gson gson = new Gson(); StorageFormat storedData = gson.fromJson(jsonFromStorage, StorageFormat.class); Main.plugin.getLogger().info("Given code: " + givenCode + ", and we have " + storedData.code + "."); @@ -70,16 +94,43 @@ class AuthenticationManager { // We can check this by subtracting 30 minutes from right now. // If that time is after the saved time, it's too late. Instant savedTime = storedData.time; - Instant thirtyMinutesBefore = Instant.now().plus(30, ChronoUnit.MINUTES); - if (savedTime.isAfter(thirtyMinutesBefore)) { - return ErrorsAndTheirMeanings.CODE_EXPIRED.getId(); + // Go 30 minutes from then + Instant thirtyMinutesAfter = savedTime.plus(30, ChronoUnit.MINUTES); + // Check if we're past that time + if (Instant.now().isAfter(thirtyMinutesAfter)) { + return returnJSON(CODE_EXPIRED); } // Now that time has been verified, we can check the code. if (Objects.equals(givenCode, storedData.code)) { - return ErrorsAndTheirMeanings.SUCCESS.getId(); + return returnJSON(SUCCESS); } else { - return ErrorsAndTheirMeanings.CODE_INCORRECT.getId(); + return returnJSON(CODE_INCORRECT); } } + /** + * Validate the UUID/player + * + * @param playerUUID The UUID to check + * @return The errors encountered, or success + */ + private String checkPlayer(UUID playerUUID) { + OfflinePlayer possiblePlayer = plugin.getServer().getOfflinePlayer(playerUUID); + if (possiblePlayer.hasPlayedBefore()) { + if (possiblePlayer.isOnline()) { + Player p = possiblePlayer.getPlayer(); + return returnJSON(SUCCESS); + } else return returnJSON(USER_NOT_ONLINE); + } else return returnJSON(USER_NEVER_JOINED); + } + + /** + * A method to get JSON to return for errors. + * + * @param error The ErrorsAndTheirMeanings error you want + * @return JSON result with error + */ + private String returnJSON(ErrorsAndTheirMeanings error) { + return "{\"result\":" + error.getId() + "}"; + } } diff --git a/src/io/github/packserver/Cedar/CommandHandle.java b/src/io/github/packserver/Cedar/CommandHandle.java index 0aa7d32db9cef757a82abb66306edae59655baee..c5ac252316ae0a1b403504794340312ec9c67a26 100644 --- a/src/io/github/packserver/Cedar/CommandHandle.java +++ b/src/io/github/packserver/Cedar/CommandHandle.java @@ -87,13 +87,13 @@ class ImageRenderer extends MapRenderer { Gson gson = new Gson(); QRString toDisplay = new QRString(); toDisplay.playerUUID = player.getUniqueId(); - toDisplay.code = new AuthenticationManager(player).generateAuthString(); + toDisplay.code = new AuthenticationManager().generateAuthString(player); File qrFile = QRCode.from(gson.toJson(toDisplay)).to(ImageType.PNG).file(); try { canvas.drawImage(0, 0, ImageIO.read(qrFile)); } catch (IOException e) { - player.sendMessage("Looks like I just done messed up lol"); + player.sendMessage(ChatColor.RED + "I couldn't grab the QR code for you to scan! This is an error."); e.printStackTrace(); } this.hasRendered = true; diff --git a/src/io/github/packserver/Cedar/ErrorsAndTheirMeanings.java b/src/io/github/packserver/Cedar/ErrorsAndTheirMeanings.java index c4b6ae4c052ba675f41905bcf06d38fc3e22d6e0..f80a6ce255dc95bd6133447d50de9bf1d7fc9bb6 100644 --- a/src/io/github/packserver/Cedar/ErrorsAndTheirMeanings.java +++ b/src/io/github/packserver/Cedar/ErrorsAndTheirMeanings.java @@ -9,6 +9,7 @@ enum ErrorsAndTheirMeanings { // Chapter 1: your basic username issues. USER_NEVER_JOINED(1), USER_NOT_ONLINE(2), + USER_UUID_INVALID(3), // Chapter 2: authentication related stuff. CODE_EXPIRED(100), diff --git a/src/io/github/packserver/Cedar/Utils.java b/src/io/github/packserver/Cedar/Utils.java index 59d0af73efddbbfe07aea56ba3dcf9df2414fbd2..bb24281041d06637533bec072712097289ade01a 100644 --- a/src/io/github/packserver/Cedar/Utils.java +++ b/src/io/github/packserver/Cedar/Utils.java @@ -1,47 +1,11 @@ package io.github.packserver.Cedar; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.util.UUID; - -import static io.github.packserver.Cedar.ErrorsAndTheirMeanings.*; - /** - * @author spotlight + * Various utilities + * + * @author Spotlight */ class Utils { - private UUID playerUUID; - private final Main plugin = Main.plugin; - - /** - * Be warned, we want to use UUIDs though. - * - * @param playerUUID UUID of player - */ - Utils(UUID playerUUID) { - this.playerUUID = playerUUID; - } - - private Boolean checkHasJoined() { - //noinspection deprecation - OfflinePlayer p = plugin.getServer().getOfflinePlayer(playerUUID); - // Actual checking - return p.hasPlayedBefore(); - } - Integer authenticateCheck(Integer code) { - Main.plugin.getLogger().info("I ran! xdxd"); - if (checkHasJoined()) { - Main.plugin.getLogger().info("I ran! xdxdxd"); - //noinspection deprecation - OfflinePlayer possiblePlayer = plugin.getServer().getOfflinePlayer(playerUUID); - if (possiblePlayer.isOnline()) { - Main.plugin.getLogger().info("I ran! xdxdxdxd"); - Player p = possiblePlayer.getPlayer(); - return new AuthenticationManager(p).checkCode(code); - } else return USER_NOT_ONLINE.getId(); - } else return USER_NEVER_JOINED.getId(); - } } diff --git a/src/io/github/packserver/Cedar/WebsocketServer.java b/src/io/github/packserver/Cedar/WebsocketServer.java index f1cd2626de3c50d705601bdc8723ae4a3daef672..2e673c436ab8cecf877870ac5bf34075cce5d890 100644 --- a/src/io/github/packserver/Cedar/WebsocketServer.java +++ b/src/io/github/packserver/Cedar/WebsocketServer.java @@ -6,7 +6,6 @@ import com.google.gson.JsonSyntaxException; import java.io.IOException; import java.net.InetSocketAddress; import java.util.Collection; -import java.util.UUID; import java.util.logging.Level; import com.google.gson.annotations.SerializedName; @@ -43,28 +42,13 @@ public class WebsocketServer extends WebSocketServer { private Integer action; } - class ParseWithUsername { - @SerializedName("action") - private Integer action; - @SerializedName("username") - private String username; - } - - // We want to use the UUID from now on. - class ParseWithUUID { - @SerializedName("action") - private Integer action; - @SerializedName("uuid") - private UUID playerUUID; - } - class ParseWithCode { @SerializedName("action") - private Integer action; + Integer action; @SerializedName("uuid") - private UUID playerUUID; + String uuid; @SerializedName("code") - private Integer code; + Integer code; } @Override @@ -87,11 +71,13 @@ public class WebsocketServer extends WebSocketServer { switch (action) { case 105: // Sends back success or nah. - // "Well, uh, technically, uh, nah" Main.plugin.getLogger().info("I did something useful!"); ParseWithCode jsonRequest = gson.fromJson(json, ParseWithCode.class); - Main.plugin.getLogger().info("Code recieved in onMessage: " + jsonRequest.code); - conn.send("{\"result\": " + new Utils(jsonRequest.playerUUID).authenticateCheck(jsonRequest.code) + "}"); + Main.plugin.getLogger().info(jsonRequest.toString()); + + Main.plugin.getLogger().info("Code received in onMessage: " + jsonRequest.code); + Main.plugin.getLogger().info("I found the following: " + jsonRequest.uuid); + conn.send(new AuthenticationManager().continueAuth(jsonRequest)); conn.close(); break; default: