From 753d61fee18ba0fdf58632caf60dc9fc732879af Mon Sep 17 00:00:00 2001
From: Spotlight <spotlight@joscomputing.space>
Date: Sun, 19 Mar 2017 20:50:46 -0500
Subject: [PATCH] Rearrange auth manager

---
 .../Cedar/AuthenticationManager.java          | 83 +++++++++++++++----
 .../packserver/Cedar/CommandHandle.java       |  4 +-
 .../Cedar/ErrorsAndTheirMeanings.java         |  1 +
 src/io/github/packserver/Cedar/Utils.java     | 42 +---------
 .../packserver/Cedar/WebsocketServer.java     | 30 ++-----
 5 files changed, 81 insertions(+), 79 deletions(-)

diff --git a/src/io/github/packserver/Cedar/AuthenticationManager.java b/src/io/github/packserver/Cedar/AuthenticationManager.java
index 1b99e54..33b47e0 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 0aa7d32..c5ac252 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 c4b6ae4..f80a6ce 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 59d0af7..bb24281 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 f1cd262..2e673c4 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:
-- 
GitLab