aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Ilin <hevav@hevav.dev>2021-12-24 19:06:43 +0300
committermdxd44 <ogurec332@mail.ru>2021-12-27 18:27:50 +0900
commitcc2ccfbe22044e98a66257488cf5bd26e21ca340 (patch)
treef451d85b385788f8ed906e89c34c714b1d35b57f
parent6ff5931596633aa842877c9f7bea04b11c5353a8 (diff)
downloadLimboAuth-cc2ccfbe22044e98a66257488cf5bd26e21ca340.tar.gz
LimboAuth-cc2ccfbe22044e98a66257488cf5bd26e21ca340.tar.bz2
LimboAuth-cc2ccfbe22044e98a66257488cf5bd26e21ca340.zip
Fixes of PREMIUM feature. (Closed LimboAPI#31)
-rw-r--r--src/main/java/net/elytrium/limboauth/LimboAuth.java52
-rw-r--r--src/main/java/net/elytrium/limboauth/Settings.java11
-rw-r--r--src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java4
-rw-r--r--src/main/java/net/elytrium/limboauth/command/PremiumCommand.java108
-rw-r--r--src/main/java/net/elytrium/limboauth/command/TotpCommand.java8
-rw-r--r--src/main/java/net/elytrium/limboauth/handler/AuthSessionHandler.java8
-rw-r--r--src/main/java/net/elytrium/limboauth/listener/AuthListener.java24
7 files changed, 179 insertions, 36 deletions
diff --git a/src/main/java/net/elytrium/limboauth/LimboAuth.java b/src/main/java/net/elytrium/limboauth/LimboAuth.java
index ba29a20..f0fcda0 100644
--- a/src/main/java/net/elytrium/limboauth/LimboAuth.java
+++ b/src/main/java/net/elytrium/limboauth/LimboAuth.java
@@ -23,6 +23,7 @@ import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.jdbc.JdbcPooledConnectionSource;
+import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.table.TableUtils;
import com.velocitypowered.api.command.CommandManager;
import com.velocitypowered.api.event.Subscribe;
@@ -68,6 +69,7 @@ import net.elytrium.limboauth.command.ChangePasswordCommand;
import net.elytrium.limboauth.command.DestroySessionCommand;
import net.elytrium.limboauth.command.ForceUnregisterCommand;
import net.elytrium.limboauth.command.LimboAuthCommand;
+import net.elytrium.limboauth.command.PremiumCommand;
import net.elytrium.limboauth.command.TotpCommand;
import net.elytrium.limboauth.command.UnregisterCommand;
import net.elytrium.limboauth.handler.AuthSessionHandler;
@@ -187,6 +189,7 @@ public class LimboAuth {
manager.unregister("limboauth");
manager.register("unregister", new UnregisterCommand(this, this.playerDao), "unreg");
+ manager.register("premium", new PremiumCommand(this, this.playerDao));
manager.register("forceunregister", new ForceUnregisterCommand(this, this.server, this.playerDao), "forceunreg");
manager.register("changepassword", new ChangePasswordCommand(this.playerDao), "changepass");
manager.register("destroysession", new DestroySessionCommand(this));
@@ -233,7 +236,7 @@ public class LimboAuth {
this.server.getEventManager().register(this, new AuthListener(this.playerDao));
Executors.newScheduledThreadPool(1, task -> new Thread(task, "purge-cache")).scheduleAtFixedRate(() ->
- this.checkCache(this.cachedAuthChecks, Settings.IMP.MAIN.PURGE_CACHE_MILLIS),
+ this.checkCache(this.cachedAuthChecks, Settings.IMP.MAIN.PURGE_CACHE_MILLIS),
Settings.IMP.MAIN.PURGE_CACHE_MILLIS,
Settings.IMP.MAIN.PURGE_CACHE_MILLIS,
TimeUnit.MILLISECONDS
@@ -316,28 +319,31 @@ public class LimboAuth {
return;
}
- if (!Settings.IMP.MAIN.ONLINE_MODE_NEED_AUTH && player.isOnlineMode()) {
- RegisteredPlayer registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, player.getUsername());
+ RegisteredPlayer registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, nickname);
+ if (player.isOnlineMode()) {
if (registeredPlayer == null || registeredPlayer.getHash().isEmpty()) {
- this.factory.passLoginLimbo(player);
- return;
+ registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, player.getUniqueId());
+ if (registeredPlayer == null || registeredPlayer.getHash().isEmpty()) {
+ this.factory.passLoginLimbo(player);
+ return;
+ }
}
}
-
// Send player to auth virtual server.
try {
- this.authServer.spawnPlayer(player, new AuthSessionHandler(this.playerDao, player, this, nickname));
+ this.authServer.spawnPlayer(player, new AuthSessionHandler(this.playerDao, player, this, registeredPlayer));
} catch (Throwable t) {
this.getLogger().error("Error", t);
}
}
- public boolean isPremium(String nickname) {
+ public boolean isPremiumExternal(String nickname) {
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(String.format(Settings.IMP.MAIN.ISPREMIUM_AUTH_URL, nickname)))
.build();
+
HttpResponse<String> response = this.client.send(request, HttpResponse.BodyHandlers.ofString());
return response.statusCode() == 200;
} catch (IOException | InterruptedException e) {
@@ -346,6 +352,36 @@ public class LimboAuth {
}
}
+ public boolean isPremium(String nickname) {
+ try {
+ if (this.isPremiumExternal(nickname)) {
+ QueryBuilder<RegisteredPlayer, String> query = this.playerDao.queryBuilder();
+ query.where()
+ .eq("LOWERCASENICKNAME", nickname.toLowerCase(Locale.ROOT))
+ .and()
+ .ne("HASH", "");
+ query.setCountOf(true);
+ QueryBuilder<RegisteredPlayer, String> query2 = this.playerDao.queryBuilder();
+ query2.where()
+ .eq("LOWERCASENICKNAME", nickname.toLowerCase(Locale.ROOT))
+ .and()
+ .eq("HASH", "");
+ query2.setCountOf(true);
+ if (Settings.IMP.MAIN.ONLINE_MODE_NEED_AUTH) {
+ return this.playerDao.countOf(query.prepare()) == 0
+ && this.playerDao.countOf(query2.prepare()) != 0;
+ } else {
+ return this.playerDao.countOf(query.prepare()) == 0;
+ }
+ } else {
+ return false;
+ }
+ } catch (SQLException e) {
+ this.getLogger().error("Unable to authenticate with Mojang", e);
+ return true;
+ }
+ }
+
private void checkCache(Map<String, CachedUser> userMap, long time) {
userMap.entrySet().stream()
.filter(u -> u.getValue().getCheckTime() + time <= System.currentTimeMillis())
diff --git a/src/main/java/net/elytrium/limboauth/Settings.java b/src/main/java/net/elytrium/limboauth/Settings.java
index 0886cdf..42cb470 100644
--- a/src/main/java/net/elytrium/limboauth/Settings.java
+++ b/src/main/java/net/elytrium/limboauth/Settings.java
@@ -43,7 +43,7 @@ public class Settings extends Config {
@Comment("Available overlays: PROGRESS, NOTCHED_6, NOTCHED_10, NOTCHED_12, NOTCHED_20")
public String BOSSBAR_OVERLAY = "NOTCHED_20";
public int MIN_PASSWORD_LENGTH = 4;
- @Comment("Максимальная длинна пароля для BCrypt равняется 71 символу.")
+ @Comment("Max password length for the BCrypt hashing algorithm, which is used in this plugin, can't be higher than 71. You can set a lower value than 71.")
public int MAX_PASSWORD_LENGTH = 71;
public boolean CHECK_PASSWORD_STRENGTH = true;
public String UNSAFE_PASSWORDS_FILE = "unsafe_passwords.txt";
@@ -139,8 +139,8 @@ public class Settings extends Config {
public String IP_LIMIT = "{PRFX} &cYour IP has reached max registered accounts. If this is an error, restart your router, or wait about 6 hours.";
public String WRONG_NICKNAME_CASE_KICK = "{PRFX}{NL}&cThe case of your nickname is wrong. Nickname is CaSe SeNsItIvE.";
- public String BOSSBAR = "{PRFX} У вас осталось &6{0} &fсекунд чтобы авторизироваться.";
- public String TIMES_UP = "{PRFX}{NL}&cВремя авторизации вышло.";
+ public String BOSSBAR = "{PRFX} You have &6{0} &fseconds left to log in.";
+ public String TIMES_UP = "{PRFX}{NL}&cAuthorization time is up.";
public String LOGIN = "{PRFX} &aPlease, login using &6/login <password>&a, you have &6{0} &aattempts.";
public String LOGIN_WRONG_PASSWORD = "{PRFX} &cYou''ve entered the wrong password, you have &6{0} &cattempts left.";
@@ -166,6 +166,11 @@ public class Settings extends Config {
public String UNREGISTER_SUCCESSFUL = "{PRFX}{NL}&aSuccessfully unregistered!";
public String UNREGISTER_USAGE = "{PRFX} Usage: &6/unregister <current password> confirm";
+ public String PREMIUM_SUCCESSFUL = "{PRFX}{NL}&aSuccessfully changed account state to PREMIUM!";
+ public String PREMIUM_USAGE = "{PRFX} Usage: &6/premium <current password> confirm";
+ public String NOT_PREMIUM = "{PRFX} Your account is not PREMIUM";
+ public String ALREADY_PREMIUM = "{PRFX} Your account is already PREMIUM";
+
public String FORCE_UNREGISTER_SUCCESSFUL = "{PRFX} &a{0} successfully unregistered!";
public String FORCE_UNREGISTER_KICK = "{PRFX}{NL}&aYou have been unregistered by administrator!";
public String FORCE_UNREGISTER_NOT_SUCCESSFUL = "{PRFX} &cUnable to unregister {0}. Most likely this player has never been on this server.";
diff --git a/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java b/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java
index 2373938..abda93d 100644
--- a/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java
+++ b/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java
@@ -78,8 +78,8 @@ public class ChangePasswordCommand implements SimpleCommand {
try {
UpdateBuilder<RegisteredPlayer, String> updateBuilder = this.playerDao.updateBuilder();
- updateBuilder.where().eq("nickname", ((Player) source).getUsername());
- updateBuilder.updateColumnValue("hash", AuthSessionHandler.genHash(this.needOldPass ? args[1] : args[0]));
+ updateBuilder.where().eq("NICKNAME", ((Player) source).getUsername());
+ updateBuilder.updateColumnValue("HASH", AuthSessionHandler.genHash(this.needOldPass ? args[1] : args[0]));
updateBuilder.update();
source.sendMessage(this.successful);
diff --git a/src/main/java/net/elytrium/limboauth/command/PremiumCommand.java b/src/main/java/net/elytrium/limboauth/command/PremiumCommand.java
new file mode 100644
index 0000000..7b209c5
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/PremiumCommand.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 Elytrium
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.elytrium.limboauth.command;
+
+import com.j256.ormlite.dao.Dao;
+import com.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.command.SimpleCommand;
+import com.velocitypowered.api.permission.Tristate;
+import com.velocitypowered.api.proxy.Player;
+import java.sql.SQLException;
+import net.elytrium.limboauth.LimboAuth;
+import net.elytrium.limboauth.Settings;
+import net.elytrium.limboauth.handler.AuthSessionHandler;
+import net.elytrium.limboauth.model.RegisteredPlayer;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+
+public class PremiumCommand implements SimpleCommand {
+
+ private final LimboAuth plugin;
+ private final Dao<RegisteredPlayer, String> playerDao;
+
+ private final Component notPlayer;
+ private final Component notPremium;
+ private final Component alreadyPremium;
+ private final Component notRegistered;
+ private final Component successful;
+ private final Component errorOccurred;
+ private final Component wrongPassword;
+ private final Component usage;
+
+ public PremiumCommand(LimboAuth plugin, Dao<RegisteredPlayer, String> playerDao) {
+ this.plugin = plugin;
+ this.playerDao = playerDao;
+
+ this.notPlayer = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_PLAYER);
+ this.notPremium = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_PREMIUM);
+ this.alreadyPremium = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.ALREADY_PREMIUM);
+ this.notRegistered = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_REGISTERED);
+ this.successful = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.PREMIUM_SUCCESSFUL);
+ this.errorOccurred = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.ERROR_OCCURRED);
+ this.wrongPassword = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.WRONG_PASSWORD);
+ this.usage = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.PREMIUM_USAGE);
+ }
+
+ @Override
+ public void execute(SimpleCommand.Invocation invocation) {
+ CommandSource source = invocation.source();
+ String[] args = invocation.arguments();
+
+ if (!(source instanceof Player)) {
+ source.sendMessage(this.notPlayer);
+ return;
+ }
+
+ if (args.length == 2) {
+ if (args[1].equalsIgnoreCase("confirm")) {
+ String username = ((Player) source).getUsername();
+ RegisteredPlayer player = AuthSessionHandler.fetchInfo(this.playerDao, username);
+ if (player == null) {
+ source.sendMessage(this.notRegistered);
+ } else if (player.getHash().isEmpty()) {
+ source.sendMessage(this.alreadyPremium);
+ } else if (AuthSessionHandler.checkPassword(args[0], player, this.playerDao)) {
+ if (this.plugin.isPremiumExternal(username)) {
+ try {
+ player.setHash("");
+ this.playerDao.update(player);
+ this.plugin.removePlayerFromCache(username);
+ ((Player) source).disconnect(this.successful);
+ } catch (SQLException e) {
+ source.sendMessage(this.errorOccurred);
+ e.printStackTrace();
+ }
+ } else {
+ source.sendMessage(this.notPremium);
+ }
+ } else {
+ source.sendMessage(this.wrongPassword);
+ }
+
+ return;
+ }
+ }
+
+ source.sendMessage(this.usage);
+ }
+
+ @Override
+ public boolean hasPermission(SimpleCommand.Invocation invocation) {
+ return invocation.source().getPermissionValue("limboauth.commands.unregister") != Tristate.FALSE;
+ }
+}
diff --git a/src/main/java/net/elytrium/limboauth/command/TotpCommand.java b/src/main/java/net/elytrium/limboauth/command/TotpCommand.java
index d51da7d..d7306bd 100644
--- a/src/main/java/net/elytrium/limboauth/command/TotpCommand.java
+++ b/src/main/java/net/elytrium/limboauth/command/TotpCommand.java
@@ -121,8 +121,8 @@ public class TotpCommand implements SimpleCommand {
try {
updateBuilder = this.playerDao.updateBuilder();
- updateBuilder.where().eq("nickname", username);
- updateBuilder.updateColumnValue("totpToken", secret);
+ updateBuilder.where().eq("NICKNAME", username);
+ updateBuilder.updateColumnValue("TOTPTOKEN", secret);
updateBuilder.update();
} catch (SQLException e) {
source.sendMessage(this.errorOccurred);
@@ -175,8 +175,8 @@ public class TotpCommand implements SimpleCommand {
if (AuthSessionHandler.getVerifier().isValidCode(playerInfo.getTotpToken(), args[1])) {
try {
updateBuilder = this.playerDao.updateBuilder();
- updateBuilder.where().eq("nickname", username);
- updateBuilder.updateColumnValue("totpToken", "");
+ updateBuilder.where().eq("NICKNAME", username);
+ updateBuilder.updateColumnValue("TOTPTOKEN", "");
updateBuilder.update();
source.sendMessage(this.disabled);
diff --git a/src/main/java/net/elytrium/limboauth/handler/AuthSessionHandler.java b/src/main/java/net/elytrium/limboauth/handler/AuthSessionHandler.java
index 59f5074..9619b2d 100644
--- a/src/main/java/net/elytrium/limboauth/handler/AuthSessionHandler.java
+++ b/src/main/java/net/elytrium/limboauth/handler/AuthSessionHandler.java
@@ -68,11 +68,11 @@ public class AuthSessionHandler implements LimboSessionHandler {
private int attempts = Settings.IMP.MAIN.LOGIN_ATTEMPTS;
private boolean totp = false;
- public AuthSessionHandler(Dao<RegisteredPlayer, String> playerDao, Player proxyPlayer, LimboAuth plugin, String lowercaseNickname) {
+ public AuthSessionHandler(Dao<RegisteredPlayer, String> playerDao, Player proxyPlayer, LimboAuth plugin, RegisteredPlayer playerInfo) {
this.playerDao = playerDao;
this.proxyPlayer = proxyPlayer;
- this.playerInfo = this.fetchInfo(lowercaseNickname);
this.plugin = plugin;
+ this.playerInfo = playerInfo;
}
@Override
@@ -203,10 +203,6 @@ public class AuthSessionHandler implements LimboSessionHandler {
return (playerList != null ? playerList.size() : 0) == 0 ? null : playerList.get(0);
}
- private RegisteredPlayer fetchInfo(String nickname) {
- return fetchInfo(this.playerDao, nickname);
- }
-
public static CodeVerifier getVerifier() {
return verifier;
}
diff --git a/src/main/java/net/elytrium/limboauth/listener/AuthListener.java b/src/main/java/net/elytrium/limboauth/listener/AuthListener.java
index 4189c12..0b0db2c 100644
--- a/src/main/java/net/elytrium/limboauth/listener/AuthListener.java
+++ b/src/main/java/net/elytrium/limboauth/listener/AuthListener.java
@@ -43,7 +43,7 @@ public class AuthListener {
@Subscribe
public void onProxyConnect(PreLoginEvent event) {
if (!event.getResult().isForceOfflineMode()) {
- if (Settings.IMP.MAIN.ONLINE_MODE_NEED_AUTH || !LimboAuth.getInstance().isPremium(event.getUsername())) {
+ if (!LimboAuth.getInstance().isPremium(event.getUsername())) {
event.setResult(PreLoginEvent.PreLoginComponentResult.forceOfflineMode());
} else {
event.setResult(PreLoginEvent.PreLoginComponentResult.forceOnlineMode());
@@ -73,22 +73,18 @@ public class AuthListener {
if (registeredPlayer != null) {
String currentUuid = registeredPlayer.getUuid();
- if (event.isOnlineMode()) {
+ if (event.isOnlineMode()
+ && registeredPlayer.getHash().isEmpty()
+ && registeredPlayer.getPremiumUuid().isEmpty()) {
try {
registeredPlayer.setPremiumUuid(event.getOriginalProfile().getId().toString());
- registeredPlayer.setHash("");
-
- if (currentUuid.isEmpty()) {
- registeredPlayer.setUuid(UuidUtils.generateOfflinePlayerUuid(event.getUsername()).toString());
- }
-
this.playerDao.update(registeredPlayer);
} catch (SQLException e) {
e.printStackTrace();
}
+ }
- event.setGameProfile(event.getOriginalProfile().withId(UUID.fromString(currentUuid)));
- } else if (currentUuid.isEmpty()) {
+ if (currentUuid.isEmpty()) {
try {
registeredPlayer.setUuid(event.getGameProfile().getId().toString());
this.playerDao.update(registeredPlayer);
@@ -96,19 +92,21 @@ public class AuthListener {
ex.printStackTrace();
}
}
+
+ event.setGameProfile(event.getOriginalProfile().withId(UUID.fromString(currentUuid)));
}
} else if (event.isOnlineMode()) {
try {
UpdateBuilder<RegisteredPlayer, String> updateBuilder = this.playerDao.updateBuilder();
- updateBuilder.where().eq("nickname", event.getUsername());
- updateBuilder.updateColumnValue("hash", "");
+ updateBuilder.where().eq("NICKNAME", event.getUsername());
+ updateBuilder.updateColumnValue("HASH", "");
updateBuilder.update();
} catch (SQLException e) {
e.printStackTrace();
}
}
- if (!Settings.IMP.MAIN.FORCE_OFFLINE_UUID) {
+ if (Settings.IMP.MAIN.FORCE_OFFLINE_UUID) {
event.setGameProfile(event.getOriginalProfile().withId(UuidUtils.generateOfflinePlayerUuid(event.getUsername())));
}
}