diff --git a/Plan/api/build.gradle b/Plan/api/build.gradle index 0dad51d1a..e3e535934 100644 --- a/Plan/api/build.gradle +++ b/Plan/api/build.gradle @@ -7,7 +7,7 @@ dependencies { compileOnly "com.google.code.gson:gson:$gsonVersion" } -ext.apiVersion = '5.1-R0.3' +ext.apiVersion = '5.1-R0.4' bintray { user = System.getenv('BINTRAY_USER') diff --git a/Plan/api/src/main/java/com/djrapitops/plan/delivery/web/resolver/request/WebUser.java b/Plan/api/src/main/java/com/djrapitops/plan/delivery/web/resolver/request/WebUser.java index 115c41392..35ac7f128 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/delivery/web/resolver/request/WebUser.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/delivery/web/resolver/request/WebUser.java @@ -17,21 +17,34 @@ package com.djrapitops.plan.delivery.web.resolver.request; import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; import java.util.Set; public final class WebUser { - private final String name; + private final String playerName; + private final String username; private final Set permissions; - public WebUser(String name) { - this.name = name; + public WebUser(String playerName) { + this.playerName = playerName; + this.username = playerName; this.permissions = new HashSet<>(); } - public WebUser(String name, String... permissions) { - this(name); + public WebUser(String playerName, String username, Collection permissions) { + this.playerName = playerName; + this.username = username; + this.permissions = new HashSet<>(permissions); + } + + /** + * @deprecated WebUser now has username and player name. + */ + @Deprecated + public WebUser(String playerName, String... permissions) { + this(playerName); this.permissions.addAll(Arrays.asList(permissions)); } @@ -40,6 +53,10 @@ public final class WebUser { } public String getName() { - return name; + return playerName; + } + + public String getUsername() { + return username; } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/commands/Arguments.java b/Plan/common/src/main/java/com/djrapitops/plan/commands/Arguments.java new file mode 100644 index 000000000..e496b5b70 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/commands/Arguments.java @@ -0,0 +1,65 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.commands; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** + * Utility for managing command arguments. + * + * @author Rsl1122 + */ +public class Arguments { + + private final List args; + + public Arguments(String[] args) { + this.args = Arrays.asList(args); + } + + public Arguments(List args) { + this.args = args; + } + + public Optional get(int index) { + return index < args.size() ? Optional.of(args.get(index)) : Optional.empty(); + } + + public Optional getInteger(int index) { + return get(index).map(Integer::parseInt); + } + + public Optional getAfter(String argumentIdentifier) { + for (int i = 0; i < args.size(); i++) { + String argument = args.get(i); + if (argumentIdentifier.equals(argument)) { + return get(i + 1); + } + } + return Optional.empty(); + } + + public boolean contains(String argument) { + return args.contains(argument); + } + + public List asList() { + return args; + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/RegisterCommand.java b/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/RegisterCommand.java index e636ffdb3..c3f81108e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/RegisterCommand.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/RegisterCommand.java @@ -16,11 +16,13 @@ */ package com.djrapitops.plan.commands.subcommands; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.commands.Arguments; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.delivery.webserver.Addresses; import com.djrapitops.plan.delivery.webserver.auth.FailReason; import com.djrapitops.plan.delivery.webserver.auth.RegistrationBin; import com.djrapitops.plan.exceptions.database.DBOpException; +import com.djrapitops.plan.identification.UUIDUtility; import com.djrapitops.plan.processing.Processing; import com.djrapitops.plan.settings.Permissions; import com.djrapitops.plan.settings.locale.Locale; @@ -39,13 +41,13 @@ import com.djrapitops.plugin.command.Sender; import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.console.PluginLogger; import com.djrapitops.plugin.logging.error.ErrorHandler; -import com.djrapitops.plugin.utilities.Verify; import javax.inject.Inject; import javax.inject.Singleton; import java.util.Arrays; -import java.util.List; +import java.util.Collections; import java.util.Optional; +import java.util.UUID; import java.util.concurrent.ExecutionException; /** @@ -65,6 +67,7 @@ public class RegisterCommand extends CommandNode { private final Locale locale; private final Processing processing; private final DBSystem dbSystem; + private final UUIDUtility uuidUtility; private final Addresses addresses; private final PluginLogger logger; private final ErrorHandler errorHandler; @@ -75,15 +78,17 @@ public class RegisterCommand extends CommandNode { Processing processing, Addresses addresses, DBSystem dbSystem, + UUIDUtility uuidUtility, PluginLogger logger, ErrorHandler errorHandler ) { // No Permission Requirement - super("register", "", CommandType.PLAYER_OR_ARGS); + super("register", "", CommandType.ALL); this.locale = locale; this.processing = processing; this.addresses = addresses; + this.uuidUtility = uuidUtility; this.logger = logger; this.dbSystem = dbSystem; this.errorHandler = errorHandler; @@ -104,27 +109,23 @@ public class RegisterCommand extends CommandNode { return; } - if (args.length < 1) { - throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, Arrays.toString(getArguments()))); + if (args.length == 0) { + String url = addresses.getMainAddress().orElseGet(() -> { + sender.sendMessage(locale.getString(CommandLang.NO_ADDRESS_NOTIFY)); + return addresses.getFallbackLocalhostAddress(); + }) + "/register"; + String linkPrefix = locale.getString(CommandLang.LINK_PREFIX); + sender.sendMessage(linkPrefix); + sender.sendLink(" ", locale.getString(CommandLang.LINK_CLICK_ME), url); + return; } - List argumentList = Arrays.asList(args); - boolean newRegister = argumentList.contains("--code"); - if (newRegister) { - if (CommandUtils.isPlayer(sender)) { - register(argumentList, getPermissionLevel(sender), sender); - } else if (argumentList.contains("superuser")) { - register(argumentList, 0, sender); - } else { - sender.sendMessage("§cInvalid arguments."); - } + Arguments arguments = new Arguments(args); + Optional code = arguments.getAfter("--code"); + if (code.isPresent()) { + registerUsingCode(sender, code.get()); } else { - // Legacy support - if (CommandUtils.isPlayer(sender)) { - playerRegister(args, sender); - } else { - consoleRegister(args, sender, notEnoughArgsMsg); - } + registerUsingLegacy(sender, arguments); } } catch (PassEncryptUtil.CannotPerformOperationException e) { errorHandler.log(L.WARN, this.getClass(), e); @@ -138,43 +139,33 @@ public class RegisterCommand extends CommandNode { } } - private void consoleRegister(String[] args, Sender sender, String notEnoughArgsMsg) throws PassEncryptUtil.CannotPerformOperationException { - Verify.isTrue(args.length >= 3, () -> new IllegalArgumentException(notEnoughArgsMsg)); - - String userName = args[1]; - Verify.isTrue(userName.length() <= 100, () -> new IllegalArgumentException("Username can only be 100 characters long.")); - int permLevel = Integer.parseInt(args[2]); - String passHash = PassEncryptUtil.createHash(args[0]); - registerUser(new WebUser(userName, passHash, permLevel), sender); - } - - private void register(List args, int permissionLevel, Sender sender) { - String code = ""; - for (String arg : args) { - if (arg.length() == 12) code = arg; - } - if (code.isEmpty()) { - throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, "--code !!")); - } - Optional user = RegistrationBin.register(code, permissionLevel); - if (!user.isPresent()) { + public void registerUsingCode(Sender sender, String code) { + UUID linkedToUUID = CommandUtils.isPlayer(sender) ? uuidUtility.getUUIDOf(sender.getName()) : null; + Optional user = RegistrationBin.register(code, linkedToUUID); + if (user.isPresent()) { + registerUser(user.get(), sender, getPermissionLevel(sender)); + } else { sender.sendMessage("§c" + locale.getString(FailReason.USER_DOES_NOT_EXIST)); - } else { - registerUser(user.get(), sender); } } - private void playerRegister(String[] args, Sender sender) throws PassEncryptUtil.CannotPerformOperationException { - boolean registerSenderAsUser = args.length == 1; - if (registerSenderAsUser) { - String user = sender.getName(); - String pass = PassEncryptUtil.createHash(args[0]); - int permLvl = getPermissionLevel(sender); - registerUser(new WebUser(user, pass, permLvl), sender); - } else if (sender.hasPermission(Permissions.MANAGE_WEB.getPermission())) { - consoleRegister(args, sender, notEnoughArgsMsg); + public void registerUsingLegacy(Sender sender, Arguments arguments) { + String password = arguments.get(0) + .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, Arrays.toString(getArguments())))); + String passwordHash = PassEncryptUtil.createHash(password); + int permissionLevel = arguments.getInteger(2) + .filter(arg -> sender.hasPermission(Permissions.MANAGE_WEB.getPerm())) // argument only allowed with plan.webmanage + .orElseGet(() -> getPermissionLevel(sender)); + + if (CommandUtils.isPlayer(sender)) { + String playerName = sender.getName(); + UUID linkedToUUID = uuidUtility.getUUIDOf(playerName); + String username = arguments.get(1).orElse(playerName); + registerUser(new User(username, playerName, linkedToUUID, passwordHash, Collections.emptyList()), sender, permissionLevel); } else { - sender.sendMessage(locale.getString(CommandLang.FAIL_NO_PERMISSION)); + String username = arguments.get(1) + .orElseThrow(() -> new IllegalArgumentException(notEnoughArgsMsg)); + registerUser(new User(username, "console", null, passwordHash, Collections.emptyList()), sender, permissionLevel); } } @@ -194,22 +185,22 @@ public class RegisterCommand extends CommandNode { return 100; } - private void registerUser(WebUser webUser, Sender sender) { + private void registerUser(User user, Sender sender, int permissionLevel) { processing.submitCritical(() -> { - String userName = webUser.getName(); + String username = user.getUsername(); try { Database database = dbSystem.getDatabase(); - boolean userExists = database.query(WebUserQueries.fetchWebUser(userName)).isPresent(); + boolean userExists = database.query(WebUserQueries.fetchUser(username)).isPresent(); if (userExists) { sender.sendMessage(locale.getString(CommandLang.FAIL_WEB_USER_EXISTS)); return; } - database.executeTransaction(new RegisterWebUserTransaction(webUser)) + database.executeTransaction(new RegisterWebUserTransaction(user, permissionLevel)) .get(); // Wait for completion - sender.sendMessage(locale.getString(CommandLang.WEB_USER_REGISTER_SUCCESS, userName)); + sender.sendMessage(locale.getString(CommandLang.WEB_USER_REGISTER_SUCCESS, username)); sendLink(sender); - logger.info(locale.getString(CommandLang.WEB_USER_REGISTER_NOTIFY, userName, webUser.getPermLevel())); + logger.info(locale.getString(CommandLang.WEB_USER_REGISTER_NOTIFY, username, permissionLevel)); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (DBOpException | ExecutionException e) { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/WebUser.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/WebUser.java index 799574503..22226cd06 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/WebUser.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/WebUser.java @@ -30,18 +30,32 @@ import java.util.Objects; @Deprecated public class WebUser { - private final String user; + private final String username; private final String saltedPassHash; private final int permLevel; - public WebUser(String user, String saltedPassHash, int permLevel) { - this.user = user; + public WebUser(String username, String saltedPassHash, int permLevel) { + this.username = username; this.saltedPassHash = saltedPassHash; this.permLevel = permLevel; } - public String getName() { - return user; + public static List getPermissionsForLevel(int level) { + List permissions = new ArrayList<>(); + if (level <= 0) { + permissions.add("page.network"); + permissions.add("page.server"); + permissions.add("page.debug"); + // TODO Add JSON Permissions + } + if (level <= 1) { + permissions.add("page.players"); + permissions.add("page.player.other"); + } + if (level <= 2) { + permissions.add("page.player.self"); + } + return permissions; } public String getSaltedPassHash() { @@ -52,38 +66,28 @@ public class WebUser { return permLevel; } + public String getName() { + return username; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; WebUser webUser = (WebUser) o; return permLevel == webUser.permLevel && - Objects.equals(user, webUser.user) && + Objects.equals(username, webUser.username) && Objects.equals(saltedPassHash, webUser.saltedPassHash); } @Override public int hashCode() { - return Objects.hash(user, saltedPassHash, permLevel); + return Objects.hash(username, saltedPassHash, permLevel); } public com.djrapitops.plan.delivery.web.resolver.request.WebUser toNewWebUser() { - List permissions = new ArrayList<>(); - if (permLevel <= 0) { - permissions.add("page.network"); - permissions.add("page.server"); - permissions.add("page.debug"); - // TODO Add JSON Permissions - } - if (permLevel <= 1) { - permissions.add("page.players"); - permissions.add("page.player.other"); - } - if (permLevel <= 2) { - permissions.add("page.player.self"); - } return new com.djrapitops.plan.delivery.web.resolver.request.WebUser( - user, permissions.toArray(new String[0]) + username, getPermissionsForLevel(permLevel).toArray(new String[0]) ); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/auth/User.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/auth/User.java new file mode 100644 index 000000000..586067bde --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/auth/User.java @@ -0,0 +1,69 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.delivery.domain.auth; + +import com.djrapitops.plan.delivery.web.resolver.request.WebUser; +import com.djrapitops.plan.utilities.PassEncryptUtil; + +import java.util.Collection; +import java.util.UUID; + +/** + * Represents a registered user in the database. + * + * @author Rsl1122 + */ +public class User { + + private final String username; + private final String linkedTo; + private final UUID linkedToUUID; // null for 'console' + private final String passwordHash; + private final Collection permissions; + + public User(String username, String linkedTo, UUID linkedToUUID, String passwordHash, Collection permissions) { + this.username = username; + this.linkedTo = linkedTo; + this.linkedToUUID = linkedToUUID; + this.passwordHash = passwordHash; + this.permissions = permissions; + } + + public boolean doesPasswordMatch(String password) { + return PassEncryptUtil.verifyPassword(password, passwordHash); + } + + public WebUser toWebUser() { + return new WebUser(linkedTo, username, permissions); + } + + public String getUsername() { + return username; + } + + public String getLinkedTo() { + return linkedTo; + } + + public UUID getLinkedToUUID() { + return linkedToUUID; + } + + public String getPasswordHash() { + return passwordHash; + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java index 4e78c699a..adb4a7f57 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java @@ -16,6 +16,7 @@ */ package com.djrapitops.plan.delivery.webserver; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.delivery.web.resolver.Response; import com.djrapitops.plan.delivery.web.resolver.request.Request; import com.djrapitops.plan.delivery.web.resolver.request.URIPath; @@ -153,8 +154,8 @@ public class RequestHandler implements HttpHandler { private WebUser getWebUser(HttpExchange exchange) { return getAuthentication(exchange.getRequestHeaders()) - .map(Authentication::getWebUser) // Can throw WebUserAuthException - .map(com.djrapitops.plan.delivery.domain.WebUser::toNewWebUser) + .map(Authentication::getUser) // Can throw WebUserAuthException + .map(User::toWebUser) .orElse(null); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/ActiveCookieStore.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/ActiveCookieStore.java index 95f353d48..69c9d9f8f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/ActiveCookieStore.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/ActiveCookieStore.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.delivery.webserver.auth; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import org.apache.commons.codec.digest.DigestUtils; import java.util.HashMap; @@ -26,14 +26,14 @@ import java.util.UUID; public class ActiveCookieStore { - private static final Map USERS_BY_COOKIE = new HashMap<>(); + private static final Map USERS_BY_COOKIE = new HashMap<>(); - public static Optional checkCookie(String cookie) { + public static Optional checkCookie(String cookie) { return Optional.ofNullable(USERS_BY_COOKIE.get(cookie)); } - public static String generateNewCookie(WebUser user) { - String cookie = DigestUtils.sha256Hex(user.getName() + UUID.randomUUID() + System.currentTimeMillis()); + public static String generateNewCookie(User user) { + String cookie = DigestUtils.sha256Hex(user.getUsername() + UUID.randomUUID() + System.currentTimeMillis()); USERS_BY_COOKIE.put(cookie, user); return cookie; } @@ -42,8 +42,8 @@ public class ActiveCookieStore { USERS_BY_COOKIE.remove(cookie); } - public static void removeCookie(WebUser user) { - USERS_BY_COOKIE.entrySet().stream().filter(entry -> entry.getValue().getName().equals(user.getName())) + public static void removeCookie(User user) { + USERS_BY_COOKIE.entrySet().stream().filter(entry -> entry.getValue().getUsername().equals(user.getUsername())) .findAny() .map(Map.Entry::getKey) .ifPresent(ActiveCookieStore::removeCookie); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Authentication.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Authentication.java index bfba2ab05..7c652d5f3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Authentication.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Authentication.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.delivery.webserver.auth; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.exceptions.WebUserAuthException; /** @@ -32,6 +32,6 @@ public interface Authentication { * @return Web user for the authentication. * @throws WebUserAuthException If user can't be authenticated */ - WebUser getWebUser(); + User getUser(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/BasicAuthentication.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/BasicAuthentication.java index 1b2383107..c96330f5e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/BasicAuthentication.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/BasicAuthentication.java @@ -16,14 +16,13 @@ */ package com.djrapitops.plan.delivery.webserver.auth; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.exceptions.PassEncryptException; import com.djrapitops.plan.exceptions.WebUserAuthException; import com.djrapitops.plan.exceptions.database.DBOpException; import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.utilities.Base64Util; -import com.djrapitops.plan.utilities.PassEncryptUtil; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; @@ -47,7 +46,7 @@ public class BasicAuthentication implements Authentication { } @Override - public WebUser getWebUser() { + public User getUser() { String decoded = Base64Util.decode(authenticationString); String[] userInfo = StringUtils.split(decoded, ':'); @@ -55,7 +54,7 @@ public class BasicAuthentication implements Authentication { throw new WebUserAuthException(FailReason.USER_AND_PASS_NOT_SPECIFIED, Arrays.toString(userInfo)); } - String user = userInfo[0]; + String username = userInfo[0]; String passwordRaw = userInfo[1]; Database.State dbState = database.getState(); @@ -64,14 +63,14 @@ public class BasicAuthentication implements Authentication { } try { - WebUser webUser = database.query(WebUserQueries.fetchWebUser(user)) - .orElseThrow(() -> new WebUserAuthException(FailReason.USER_DOES_NOT_EXIST, user)); + User user = database.query(WebUserQueries.fetchUser(username)) + .orElseThrow(() -> new WebUserAuthException(FailReason.USER_DOES_NOT_EXIST, username)); - boolean correctPass = PassEncryptUtil.verifyPassword(passwordRaw, webUser.getSaltedPassHash()); + boolean correctPass = user.doesPasswordMatch(passwordRaw); if (!correctPass) { - throw new WebUserAuthException(FailReason.USER_PASS_MISMATCH, user); + throw new WebUserAuthException(FailReason.USER_PASS_MISMATCH, username); } - return webUser; + return user; } catch (DBOpException | PassEncryptException e) { throw new WebUserAuthException(e); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/CookieAuthentication.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/CookieAuthentication.java index 9fed6fbfc..ab0023ead 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/CookieAuthentication.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/CookieAuthentication.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.delivery.webserver.auth; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; public class CookieAuthentication implements Authentication { @@ -27,7 +27,7 @@ public class CookieAuthentication implements Authentication { } @Override - public WebUser getWebUser() { + public User getUser() { return ActiveCookieStore.checkCookie(cookie).orElse(null); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/RegistrationBin.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/RegistrationBin.java index 46aac0e1f..c91bc433f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/RegistrationBin.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/RegistrationBin.java @@ -16,13 +16,11 @@ */ package com.djrapitops.plan.delivery.webserver.auth; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.utilities.PassEncryptUtil; import org.apache.commons.codec.digest.DigestUtils; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; /** * Holds registrations of users before they are confirmed. @@ -33,18 +31,18 @@ public class RegistrationBin { private static final Map REGISTRATION_BIN = new HashMap<>(); - public static String addInfoForRegistration(String username, String password) throws PassEncryptUtil.CannotPerformOperationException { + public static String addInfoForRegistration(String username, String password) { String hash = PassEncryptUtil.createHash(password); String code = DigestUtils.sha256Hex(username + password + System.currentTimeMillis()).substring(0, 12); REGISTRATION_BIN.put(code, new AwaitingForRegistration(username, hash)); return code; } - public static Optional register(String code, int permissionLevel) { + public static Optional register(String code, UUID linkedToUUID) { AwaitingForRegistration found = REGISTRATION_BIN.get(code); if (found == null) return Optional.empty(); REGISTRATION_BIN.remove(code); - return Optional.of(found.toWebUser(permissionLevel)); + return Optional.of(found.toUser(linkedToUUID)); } public static boolean contains(String code) { @@ -60,8 +58,8 @@ public class RegistrationBin { this.passwordHash = passwordHash; } - public WebUser toWebUser(int permissionLevel) { - return new WebUser(username, passwordHash, permissionLevel); + public User toUser(UUID linkedToUUID) { + return new User(username, null, linkedToUUID, passwordHash, Collections.emptyList()); } } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/LoginResolver.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/LoginResolver.java index 03ff4e987..43457adfb 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/LoginResolver.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/LoginResolver.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.delivery.webserver.resolver.auth; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver; import com.djrapitops.plan.delivery.web.resolver.Response; import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException; @@ -29,7 +29,6 @@ import com.djrapitops.plan.exceptions.WebUserAuthException; import com.djrapitops.plan.exceptions.database.DBOpException; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; -import com.djrapitops.plan.utilities.PassEncryptUtil; import javax.inject.Inject; import javax.inject.Singleton; @@ -52,7 +51,7 @@ public class LoginResolver implements NoAuthResolver { @Override public Optional resolve(Request request) { try { - String cookie = ActiveCookieStore.generateNewCookie(getWebUser(request)); + String cookie = ActiveCookieStore.generateNewCookie(getUser(request)); return Optional.of(getResponse(cookie)); } catch (DBOpException | PassEncryptException e) { throw new WebUserAuthException(e); @@ -67,17 +66,17 @@ public class LoginResolver implements NoAuthResolver { .build(); } - public WebUser getWebUser(Request request) throws PassEncryptUtil.CannotPerformOperationException, PassEncryptUtil.InvalidHashException { + public User getUser(Request request) { URIQuery query = request.getQuery(); String username = query.get("user").orElseThrow(() -> new BadRequestException("'user' parameter not defined")); String password = query.get("password").orElseThrow(() -> new BadRequestException("'password' parameter not defined")); - WebUser webUser = dbSystem.getDatabase().query(WebUserQueries.fetchWebUser(username)) + User user = dbSystem.getDatabase().query(WebUserQueries.fetchUser(username)) .orElseThrow(() -> new BadRequestException(FailReason.USER_DOES_NOT_EXIST.getReason() + ": " + username)); - boolean correctPass = PassEncryptUtil.verifyPassword(password, webUser.getSaltedPassHash()); + boolean correctPass = user.doesPasswordMatch(password); if (!correctPass) { throw new WebUserAuthException(FailReason.USER_PASS_MISMATCH); } - return webUser; + return user; } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/RegisterResolver.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/RegisterResolver.java index eeb117d46..bca0bc2bb 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/RegisterResolver.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/auth/RegisterResolver.java @@ -57,7 +57,7 @@ public class RegisterResolver implements NoAuthResolver { String username = query.get("user").orElseThrow(() -> new BadRequestException("'user' parameter not defined")); - boolean alreadyExists = dbSystem.getDatabase().query(WebUserQueries.fetchWebUser(username)).isPresent(); + boolean alreadyExists = dbSystem.getDatabase().query(WebUserQueries.fetchUser(username)).isPresent(); if (alreadyExists) throw new BadRequestException("User '" + username + "' already exists!"); String password = query.get("password").orElseThrow(() -> new BadRequestException("'password' parameter not defined")); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/PassEncryptException.java b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/PassEncryptException.java index 2c08b4816..05a6fca61 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/PassEncryptException.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/PassEncryptException.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.exceptions; -public class PassEncryptException extends Exception { +public class PassEncryptException extends IllegalArgumentException { public PassEncryptException(String s) { super(s); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java index 72c687d47..91fe165bf 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java @@ -170,7 +170,9 @@ public abstract class SQLDB extends AbstractDatabase { new ExtensionTableRowValueLengthPatch(), new CommandUsageTableRemovalPatch(), new RegisterDateMinimizationPatch(), - new BadNukkitRegisterValuePatch() + new BadNukkitRegisterValuePatch(), + new LinkedToSecurityTablePatch(), + new LinkUsersToPlayersSecurityTablePatch() }; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/WebUserQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/WebUserQueries.java index 085b77caa..2800c0541 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/WebUserQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/WebUserQueries.java @@ -17,10 +17,12 @@ package com.djrapitops.plan.storage.database.queries.objects; import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.storage.database.queries.Query; import com.djrapitops.plan.storage.database.queries.QueryAllStatement; import com.djrapitops.plan.storage.database.queries.QueryStatement; import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; +import com.djrapitops.plan.storage.database.sql.tables.UsersTable; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -28,11 +30,12 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.UUID; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; /** - * Queries for {@link WebUser} objects. + * Queries for web user objects. * * @author Rsl1122 */ @@ -47,6 +50,7 @@ public class WebUserQueries { * * @return List of Plan WebUsers. */ + @Deprecated public static Query> fetchAllPlanWebUsers() { String sql = SELECT + '*' + FROM + SecurityTable.TABLE_NAME + ORDER_BY + SecurityTable.PERMISSION_LEVEL + " ASC"; @@ -66,6 +70,31 @@ public class WebUserQueries { }; } + public static Query> fetchUser(String username) { + String sql = SELECT + '*' + FROM + SecurityTable.TABLE_NAME + + LEFT_JOIN + UsersTable.TABLE_NAME + " on " + SecurityTable.LINKED_TO + "=" + UsersTable.USER_UUID + + WHERE + SecurityTable.USERNAME + "=? LIMIT 1"; + return new QueryStatement>(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setString(1, username); + } + + @Override + public Optional processResults(ResultSet set) throws SQLException { + if (set.next()) { + String linkedTo = set.getString(UsersTable.USER_NAME); + UUID linkedToUUID = linkedTo != null ? UUID.fromString(set.getString(SecurityTable.LINKED_TO)) : null; + String passwordHash = set.getString(SecurityTable.SALT_PASSWORD_HASH); + List permissions = WebUser.getPermissionsForLevel(set.getInt(SecurityTable.PERMISSION_LEVEL)); + return Optional.of(new User(username, linkedTo != null ? linkedTo : "console", linkedToUUID, passwordHash, permissions)); + } + return Optional.empty(); + } + }; + } + + @Deprecated public static Query> fetchWebUser(String called) { String sql = SELECT + '*' + FROM + SecurityTable.TABLE_NAME + WHERE + SecurityTable.USERNAME + "=? LIMIT 1"; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/SecurityTable.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/SecurityTable.java index dff075c2f..f523e55bd 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/SecurityTable.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/SecurityTable.java @@ -18,7 +18,6 @@ package com.djrapitops.plan.storage.database.sql.tables; import com.djrapitops.plan.storage.database.DBType; import com.djrapitops.plan.storage.database.sql.building.CreateTableBuilder; -import com.djrapitops.plan.storage.database.sql.building.Insert; import com.djrapitops.plan.storage.database.sql.building.Sql; /** @@ -31,10 +30,15 @@ public class SecurityTable { public static final String TABLE_NAME = "plan_security"; public static final String USERNAME = "username"; + public static final String LINKED_TO = "linked_to_uuid"; public static final String SALT_PASSWORD_HASH = "salted_pass_hash"; public static final String PERMISSION_LEVEL = "permission_level"; - public static final String INSERT_STATEMENT = Insert.values(TABLE_NAME, USERNAME, SALT_PASSWORD_HASH, PERMISSION_LEVEL); + public static final String INSERT_STATEMENT = "INSERT INTO " + TABLE_NAME + " (" + + USERNAME + ',' + + LINKED_TO + ',' + + SALT_PASSWORD_HASH + ',' + + PERMISSION_LEVEL + ") VALUES (?,?,?,?)"; private SecurityTable() { /* Static information class */ @@ -43,6 +47,7 @@ public class SecurityTable { public static String createTableSQL(DBType dbType) { return CreateTableBuilder.create(TABLE_NAME, dbType) .column(USERNAME, Sql.varchar(100)).notNull().unique() + .column(LINKED_TO, Sql.varchar(36)) .column(SALT_PASSWORD_HASH, Sql.varchar(100)).notNull().unique() .column(PERMISSION_LEVEL, Sql.INT).notNull() .toString(); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RegisterWebUserTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RegisterWebUserTransaction.java index 4dd004a37..3e0fa64d5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RegisterWebUserTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RegisterWebUserTransaction.java @@ -16,25 +16,28 @@ */ package com.djrapitops.plan.storage.database.transactions.commands; -import com.djrapitops.plan.delivery.domain.WebUser; +import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; import com.djrapitops.plan.storage.database.transactions.ExecStatement; import com.djrapitops.plan.storage.database.transactions.Transaction; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Types; /** - * Transaction to save a new Plan {@link WebUser} to the database. + * Transaction to save a new Plan {@link User} to the database. * * @author Rsl1122 */ public class RegisterWebUserTransaction extends Transaction { - private final WebUser webUser; + private final User user; + private final int permissionLevel; - public RegisterWebUserTransaction(WebUser webUser) { - this.webUser = webUser; + public RegisterWebUserTransaction(User user, int permissionLevel) { + this.user = user; + this.permissionLevel = permissionLevel; } @Override @@ -42,9 +45,14 @@ public class RegisterWebUserTransaction extends Transaction { execute(new ExecStatement(SecurityTable.INSERT_STATEMENT) { @Override public void prepare(PreparedStatement statement) throws SQLException { - statement.setString(1, webUser.getName()); - statement.setString(2, webUser.getSaltedPassHash()); - statement.setInt(3, webUser.getPermLevel()); + statement.setString(1, user.getUsername()); + if (user.getLinkedToUUID() == null) { + statement.setNull(2, Types.VARCHAR); + } else { + statement.setString(2, user.getLinkedToUUID().toString()); + } + statement.setString(3, user.getPasswordHash()); + statement.setInt(4, permissionLevel); } }); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java new file mode 100644 index 000000000..f6bf20cc5 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java @@ -0,0 +1,78 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.storage.database.transactions.patches; + +import com.djrapitops.plan.storage.database.queries.HasMoreThanZeroQueryStatement; +import com.djrapitops.plan.storage.database.queries.QueryAllStatement; +import com.djrapitops.plan.storage.database.sql.building.Sql; +import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; +import com.djrapitops.plan.storage.database.sql.tables.UsersTable; +import com.djrapitops.plan.storage.database.transactions.ExecBatchStatement; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +import static com.djrapitops.plan.storage.database.sql.building.Sql.*; + +public class LinkUsersToPlayersSecurityTablePatch extends Patch { + + @Override + public boolean hasBeenApplied() { + String sql = SELECT + "COUNT(1) as c" + FROM + SecurityTable.TABLE_NAME + + WHERE + SecurityTable.LINKED_TO + "=''"; + return !query(new HasMoreThanZeroQueryStatement(sql) { + @Override + public void prepare(PreparedStatement statement) { + // No preparation necessary + } + }); + } + + @Override + protected void applyPatch() { + String querySQL = SELECT + UsersTable.USER_UUID + ',' + SecurityTable.USERNAME + + FROM + SecurityTable.TABLE_NAME + + LEFT_JOIN + UsersTable.TABLE_NAME + " on " + UsersTable.USER_NAME + "=" + SecurityTable.USERNAME + + WHERE + SecurityTable.LINKED_TO + "=''"; + String sql = "UPDATE " + SecurityTable.TABLE_NAME + " SET " + SecurityTable.LINKED_TO + "=?" + + WHERE + SecurityTable.USERNAME + "=?"; + + Map byUsername = query(new QueryAllStatement>(querySQL) { + @Override + public Map processResults(ResultSet set) throws SQLException { + Map byUsername = new HashMap<>(); + while (set.next()) { + byUsername.put(set.getString(SecurityTable.USERNAME), set.getString(UsersTable.USER_UUID)); + } + return byUsername; + } + }); + execute(new ExecBatchStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + for (Map.Entry usernameUUIDPair : byUsername.entrySet()) { + Sql.setStringOrNull(statement, 1, usernameUUIDPair.getValue()); + statement.setString(2, usernameUUIDPair.getKey()); + statement.addBatch(); + } + } + }); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java new file mode 100644 index 000000000..5c32cd9db --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java @@ -0,0 +1,33 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.storage.database.transactions.patches; + +import com.djrapitops.plan.storage.database.sql.building.Sql; +import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; + +public class LinkedToSecurityTablePatch extends Patch { + + @Override + public boolean hasBeenApplied() { + return hasColumn(SecurityTable.TABLE_NAME, SecurityTable.LINKED_TO); + } + + @Override + protected void applyPatch() { + addColumn(SecurityTable.TABLE_NAME, SecurityTable.LINKED_TO + ' ' + Sql.varchar(36) + " DEFAULT ''"); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/PassEncryptUtil.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/PassEncryptUtil.java index 89ace6b39..1d9e0062c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/PassEncryptUtil.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/PassEncryptUtil.java @@ -55,11 +55,18 @@ public class PassEncryptUtil { throw new IllegalStateException("Utility class"); } - public static String createHash(String password) throws CannotPerformOperationException { + /** + * Create a hash of password + salt. + * + * @param password Password + * @return Hash + salt + * @throws CannotPerformOperationException If the hash creation fails + */ + public static String createHash(String password) { return createHash(password.toCharArray()); } - private static String createHash(char[] password) throws CannotPerformOperationException { + private static String createHash(char[] password) { // Generate a random salt SecureRandom random = new SecureRandom(); byte[] salt = new byte[SALT_BYTE_SIZE]; @@ -77,11 +84,20 @@ public class PassEncryptUtil { + ":" + toBase64(hash); } - public static boolean verifyPassword(String password, String correctHash) throws CannotPerformOperationException, InvalidHashException { + /** + * Verify that a password matches a hash. + * + * @param password Password + * @param correctHash hash created with {@link PassEncryptUtil#createHash(String)} + * @return true if match + * @throws CannotPerformOperationException If hashing fails + * @throws InvalidHashException If the hash is missing details. + */ + public static boolean verifyPassword(String password, String correctHash) { return verifyPassword(password.toCharArray(), correctHash); } - private static boolean verifyPassword(char[] password, String correctHash) throws CannotPerformOperationException, InvalidHashException { + private static boolean verifyPassword(char[] password, String correctHash) { // Decode the hash into its parameters String[] params = StringUtils.split(correctHash, ':'); if (params.length != HASH_SECTIONS) { @@ -160,7 +176,7 @@ public class PassEncryptUtil { return diff == 0; } - private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws CannotPerformOperationException { + private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) { try { PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8); SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JksHttpsServerTest.java b/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JksHttpsServerTest.java index d07d94d6d..618abc664 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JksHttpsServerTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JksHttpsServerTest.java @@ -59,7 +59,7 @@ class JksHttpsServerTest implements HttpsServerTest { system.enable(); WebUser webUser = new WebUser("test", PassEncryptUtil.createHash("testPass"), 0); - system.getDatabaseSystem().getDatabase().executeTransaction(new RegisterWebUserTransaction(webUser)); + system.getDatabaseSystem().getDatabase().executeTransaction(new RegisterWebUserTransaction(webUser, )); } @AfterAll diff --git a/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/Pkcs12HttpsServerTest.java b/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/Pkcs12HttpsServerTest.java index 96f5c309a..247df984f 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/Pkcs12HttpsServerTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/Pkcs12HttpsServerTest.java @@ -64,7 +64,7 @@ class Pkcs12HttpsServerTest implements HttpsServerTest { system.enable(); WebUser webUser = new WebUser("test", PassEncryptUtil.createHash("testPass"), 0); - system.getDatabaseSystem().getDatabase().executeTransaction(new RegisterWebUserTransaction(webUser)); + system.getDatabaseSystem().getDatabase().executeTransaction(new RegisterWebUserTransaction(webUser, )); } @AfterAll diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/DatabaseBackupTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/DatabaseBackupTest.java index 6dce72b07..1190c5bb3 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/DatabaseBackupTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/DatabaseBackupTest.java @@ -68,7 +68,7 @@ public interface DatabaseBackupTest extends DatabaseTestPreparer { ); WebUser webUser = new WebUser(TestConstants.PLAYER_ONE_NAME, RandomData.randomString(100), 0); - db().executeTransaction(new RegisterWebUserTransaction(webUser)); + db().executeTransaction(new RegisterWebUserTransaction(webUser, )); } @Test diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/WebUserQueriesTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/WebUserQueriesTest.java index 55ad25254..10e64530e 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/WebUserQueriesTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/WebUserQueriesTest.java @@ -34,7 +34,7 @@ public interface WebUserQueriesTest extends DatabaseTestPreparer { @Test default void webUserIsRegistered() { WebUser expected = new WebUser(TestConstants.PLAYER_ONE_NAME, "RandomGarbageBlah", 0); - db().executeTransaction(new RegisterWebUserTransaction(expected)); + db().executeTransaction(new RegisterWebUserTransaction(expected, )); forcePersistenceCheck(); Optional found = db().query(WebUserQueries.fetchWebUser(TestConstants.PLAYER_ONE_NAME));