aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/net/elytrium/limboauth/command
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/elytrium/limboauth/command')
-rw-r--r--src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java101
-rw-r--r--src/main/java/net/elytrium/limboauth/command/DestroySessionCommand.java60
-rw-r--r--src/main/java/net/elytrium/limboauth/command/ForceUnregisterCommand.java106
-rw-r--r--src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java95
-rw-r--r--src/main/java/net/elytrium/limboauth/command/TotpCommand.java204
-rw-r--r--src/main/java/net/elytrium/limboauth/command/UnregisterCommand.java97
6 files changed, 663 insertions, 0 deletions
diff --git a/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java b/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java
new file mode 100644
index 0000000..2373938
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/ChangePasswordCommand.java
@@ -0,0 +1,101 @@
+/*
+ * 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.j256.ormlite.stmt.UpdateBuilder;
+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.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 ChangePasswordCommand implements SimpleCommand {
+
+ private final Dao<RegisteredPlayer, String> playerDao;
+
+ private final Component notPlayer;
+ private final boolean needOldPass;
+ private final Component notRegistered;
+ private final Component wrongPassword;
+ private final Component successful;
+ private final Component errorOccurred;
+ private final Component usage;
+
+ public ChangePasswordCommand(Dao<RegisteredPlayer, String> playerDao) {
+ this.playerDao = playerDao;
+
+ this.notPlayer = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_PLAYER);
+ this.needOldPass = Settings.IMP.MAIN.CHANGE_PASSWORD_NEED_OLD_PASSWORD;
+ this.notRegistered = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_REGISTERED);
+ this.wrongPassword = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.WRONG_PASSWORD);
+ this.successful = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.CHANGE_PASSWORD_SUCCESSFUL);
+ this.errorOccurred = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.ERROR_OCCURRED);
+ this.usage = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.CHANGE_PASSWORD_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 (this.needOldPass ? args.length == 2 : args.length == 1) {
+ if (this.needOldPass) {
+ RegisteredPlayer player = AuthSessionHandler.fetchInfo(this.playerDao, ((Player) source).getUsername());
+ if (player == null) {
+ source.sendMessage(this.notRegistered);
+ return;
+ } else if (!AuthSessionHandler.checkPassword(args[0], player, this.playerDao)) {
+ source.sendMessage(this.wrongPassword);
+ return;
+ }
+ }
+
+ 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.update();
+
+ source.sendMessage(this.successful);
+ } catch (SQLException e) {
+ source.sendMessage(this.errorOccurred);
+ e.printStackTrace();
+ }
+
+ return;
+ }
+
+ source.sendMessage(this.usage);
+ }
+
+ @Override
+ public boolean hasPermission(SimpleCommand.Invocation invocation) {
+ return invocation.source().getPermissionValue("limboauth.commands.changepassword") != Tristate.FALSE;
+ }
+}
diff --git a/src/main/java/net/elytrium/limboauth/command/DestroySessionCommand.java b/src/main/java/net/elytrium/limboauth/command/DestroySessionCommand.java
new file mode 100644
index 0000000..27dff72
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/DestroySessionCommand.java
@@ -0,0 +1,60 @@
+/*
+ * 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.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.command.SimpleCommand;
+import com.velocitypowered.api.permission.Tristate;
+import com.velocitypowered.api.proxy.Player;
+import net.elytrium.limboauth.LimboAuth;
+import net.elytrium.limboauth.Settings;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+
+public class DestroySessionCommand implements SimpleCommand {
+
+ private final LimboAuth plugin;
+
+ private final Component notPlayer;
+ private final Component successful;
+
+ public DestroySessionCommand(LimboAuth plugin) {
+ this.plugin = plugin;
+
+ this.notPlayer = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_PLAYER);
+ this.successful = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.DESTROY_SESSION_SUCCESSFUL);
+ }
+
+ @Override
+ public void execute(SimpleCommand.Invocation invocation) {
+ CommandSource source = invocation.source();
+
+ if (!(source instanceof Player)) {
+ source.sendMessage(this.notPlayer);
+ return;
+ }
+
+ this.plugin.removePlayerFromCache((Player) source);
+ source.sendMessage(this.successful);
+ }
+
+ @Override
+ public boolean hasPermission(SimpleCommand.Invocation invocation) {
+ return invocation.source().getPermissionValue("limboauth.commands.destroysession") != Tristate.FALSE;
+ }
+}
diff --git a/src/main/java/net/elytrium/limboauth/command/ForceUnregisterCommand.java b/src/main/java/net/elytrium/limboauth/command/ForceUnregisterCommand.java
new file mode 100644
index 0000000..d45eae9
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/ForceUnregisterCommand.java
@@ -0,0 +1,106 @@
+/*
+ * 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.google.common.collect.ImmutableList;
+import com.j256.ormlite.dao.Dao;
+import com.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.command.SimpleCommand;
+import com.velocitypowered.api.proxy.Player;
+import com.velocitypowered.api.proxy.ProxyServer;
+import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+import net.elytrium.limboauth.LimboAuth;
+import net.elytrium.limboauth.Settings;
+import net.elytrium.limboauth.model.RegisteredPlayer;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+
+public class ForceUnregisterCommand implements SimpleCommand {
+
+ private final LimboAuth plugin;
+ private final ProxyServer server;
+ private final Dao<RegisteredPlayer, String> playerDao;
+
+ private final Component successfulPlayer;
+ private final String successful;
+ private final String notSuccessful;
+ private final Component usage;
+
+ public ForceUnregisterCommand(LimboAuth plugin, ProxyServer server, Dao<RegisteredPlayer, String> playerDao) {
+ this.plugin = plugin;
+ this.server = server;
+ this.playerDao = playerDao;
+
+ this.successfulPlayer = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.FORCE_UNREGISTER_SUCCESSFUL_PLAYER);
+ this.successful = Settings.IMP.MAIN.STRINGS.FORCE_UNREGISTER_SUCCESSFUL;
+ this.notSuccessful = Settings.IMP.MAIN.STRINGS.FORCE_UNREGISTER_NOT_SUCCESSFUL;
+ this.usage = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.FORCE_UNREGISTER_USAGE);
+ }
+
+ @Override
+ public List<String> suggest(SimpleCommand.Invocation invocation) {
+ String[] args = invocation.arguments();
+
+ if (args.length == 0) {
+ return this.server.getAllPlayers().stream()
+ .map(Player::getUsername)
+ .collect(Collectors.toList());
+ } else if (args.length == 1) {
+ return this.server.getAllPlayers().stream()
+ .map(Player::getUsername)
+ .filter(str -> str.regionMatches(true, 0, args[0], 0, args[0].length()))
+ .collect(Collectors.toList());
+ }
+
+ return ImmutableList.of();
+ }
+
+ @Override
+ public void execute(SimpleCommand.Invocation invocation) {
+ CommandSource source = invocation.source();
+ String[] args = invocation.arguments();
+
+ if (args.length == 1) {
+ String playerNick = args[0];
+ try {
+ this.playerDao.deleteById(playerNick.toLowerCase(Locale.ROOT));
+ this.server.getPlayer(playerNick).ifPresent(player -> {
+ this.plugin.removePlayerFromCache(player);
+ player.disconnect(this.successfulPlayer);
+ });
+ source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(MessageFormat.format(this.successful, playerNick)));
+ } catch (SQLException e) {
+ source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(MessageFormat.format(this.notSuccessful, playerNick)));
+ e.printStackTrace();
+ }
+
+ return;
+ }
+
+ source.sendMessage(this.usage);
+ }
+
+ @Override
+ public boolean hasPermission(SimpleCommand.Invocation invocation) {
+ return invocation.source().hasPermission("limboauth.admin.forceunregister");
+ }
+}
diff --git a/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java b/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java
new file mode 100644
index 0000000..611b1c3
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java
@@ -0,0 +1,95 @@
+/*
+ * 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.google.common.collect.ImmutableList;
+import com.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.command.SimpleCommand;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import net.elytrium.limboauth.LimboAuth;
+import net.elytrium.limboauth.Settings;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+
+public class LimboAuthCommand implements SimpleCommand {
+
+ @Override
+ public List<String> suggest(SimpleCommand.Invocation invocation) {
+ CommandSource source = invocation.source();
+ String[] args = invocation.arguments();
+
+ if (args.length == 0) {
+ return this.getSubCommands()
+ .filter(cmd -> source.hasPermission("limboauth.admin." + cmd))
+ .collect(Collectors.toList());
+ } else if (args.length == 1) {
+ return this.getSubCommands()
+ .filter(cmd -> source.hasPermission("limboauth.admin." + cmd))
+ .filter(str -> str.regionMatches(true, 0, args[0], 0, args[0].length()))
+ .collect(Collectors.toList());
+ }
+
+ return ImmutableList.of();
+ }
+
+ @Override
+ public void execute(SimpleCommand.Invocation invocation) {
+ CommandSource source = invocation.source();
+ String[] args = invocation.arguments();
+
+ if (args.length == 1) {
+ if (args[0].equalsIgnoreCase("reload") && source.hasPermission("limboauth.admin.reload")) {
+ try {
+ LimboAuth.getInstance().reload();
+ source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.RELOAD));
+ } catch (Exception e) {
+ source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.RELOAD_FAILED));
+ e.printStackTrace();
+ }
+ } else {
+ this.showHelp(source);
+ }
+
+ return;
+ }
+
+ this.showHelp(source);
+ }
+
+ private void showHelp(CommandSource source) {
+ source.sendMessage(Component.text("§eThis server is using LimboAuth and LimboAPI"));
+ source.sendMessage(Component.text("§e(c) 2021 Elytrium"));
+ source.sendMessage(Component.text("§ahttps://ely.su/github/"));
+ source.sendMessage(Component.text("§r"));
+ source.sendMessage(Component.text("§fAvailable subcommands:"));
+ // Java moment
+ this.getSubCommands()
+ .filter(cmd -> source.hasPermission("limboauth.admin." + cmd))
+ .forEach(cmd -> {
+ if (cmd.equals("reload")) {
+ source.sendMessage(Component.text(" §a/limboauth reload §8- §eReload config"));
+ }
+ });
+ }
+
+ private Stream<String> getSubCommands() {
+ return Stream.of("reload");
+ }
+}
diff --git a/src/main/java/net/elytrium/limboauth/command/TotpCommand.java b/src/main/java/net/elytrium/limboauth/command/TotpCommand.java
new file mode 100644
index 0000000..d51da7d
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/TotpCommand.java
@@ -0,0 +1,204 @@
+/*
+ * 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.j256.ormlite.stmt.UpdateBuilder;
+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 dev.samstevens.totp.qr.QrData;
+import dev.samstevens.totp.recovery.RecoveryCodeGenerator;
+import dev.samstevens.totp.secret.DefaultSecretGenerator;
+import dev.samstevens.totp.secret.SecretGenerator;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.sql.SQLException;
+import java.text.MessageFormat;
+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.event.ClickEvent;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+
+public class TotpCommand implements SimpleCommand {
+
+ private final SecretGenerator secretGenerator = new DefaultSecretGenerator();
+ private final RecoveryCodeGenerator codesGenerator = new RecoveryCodeGenerator();
+ private final Dao<RegisteredPlayer, String> playerDao;
+
+ private final Component notPlayer;
+ private final Component usage;
+ private final boolean needPassword;
+ private final Component notRegistered;
+ private final Component wrongPassword;
+ private final Component alreadyEnabled;
+ private final Component errorOccurred;
+ private final Component successful;
+ private final String issuer;
+ private final String qrGeneratorUrl;
+ private final Component qr;
+ private final String token;
+ private final int recoveryCodesAmount;
+ private final String recovery;
+ private final Component disabled;
+ private final Component wrong;
+
+ public TotpCommand(Dao<RegisteredPlayer, String> playerDao) {
+ this.playerDao = playerDao;
+
+ this.notPlayer = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_PLAYER);
+ this.usage = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.TOTP_USAGE);
+ this.needPassword = Settings.IMP.MAIN.TOTP_NEED_PASSWORD;
+ this.notRegistered = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_REGISTERED);
+ this.wrongPassword = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.WRONG_PASSWORD);
+ this.alreadyEnabled = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.TOTP_ALREADY_ENABLED);
+ this.errorOccurred = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.ERROR_OCCURRED);
+ this.successful = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.TOTP_SUCCESSFUL);
+ this.issuer = Settings.IMP.MAIN.TOTP_ISSUER;
+ this.qrGeneratorUrl = Settings.IMP.MAIN.QR_GENERATOR_URL;
+ this.qr = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.TOTP_QR);
+ this.token = Settings.IMP.MAIN.STRINGS.TOTP_TOKEN;
+ this.recoveryCodesAmount = Settings.IMP.MAIN.TOTP_RECOVERY_CODES_AMOUNT;
+ this.recovery = Settings.IMP.MAIN.STRINGS.TOTP_RECOVERY;
+ this.disabled = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.TOTP_DISABLED);
+ this.wrong = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.TOTP_WRONG);
+ }
+
+ @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 == 0) {
+ source.sendMessage(this.usage);
+ } else {
+ String username = ((Player) source).getUsername();
+
+ RegisteredPlayer playerInfo;
+ UpdateBuilder<RegisteredPlayer, String> updateBuilder;
+ switch (args[0]) {
+ case "enable": {
+ if (this.needPassword ? args.length == 2 : args.length == 1) {
+ playerInfo = AuthSessionHandler.fetchInfo(this.playerDao, username);
+
+ if (playerInfo == null) {
+ source.sendMessage(this.notRegistered);
+ return;
+ } else if (this.needPassword && !AuthSessionHandler.checkPassword(args[1], playerInfo, this.playerDao)) {
+ source.sendMessage(this.wrongPassword);
+ return;
+ }
+
+ if (!playerInfo.getTotpToken().isEmpty()) {
+ source.sendMessage(this.alreadyEnabled);
+ return;
+ }
+
+ String secret = this.secretGenerator.generate();
+
+ try {
+ updateBuilder = this.playerDao.updateBuilder();
+ updateBuilder.where().eq("nickname", username);
+ updateBuilder.updateColumnValue("totpToken", secret);
+ updateBuilder.update();
+ } catch (SQLException e) {
+ source.sendMessage(this.errorOccurred);
+ e.printStackTrace();
+ }
+
+ source.sendMessage(this.successful);
+
+ QrData data = new QrData.Builder()
+ .label(username)
+ .secret(secret)
+ .issuer(this.issuer)
+ .build();
+
+ String qrUrl = this.qrGeneratorUrl.replace("{data}", URLEncoder.encode(data.getUri(), StandardCharsets.UTF_8));
+
+ source.sendMessage(this.qr.clickEvent(ClickEvent.openUrl(qrUrl)));
+
+ source.sendMessage(
+ LegacyComponentSerializer.legacyAmpersand().deserialize(
+ MessageFormat.format(this.token, secret)
+ ).clickEvent(ClickEvent.copyToClipboard(secret))
+ );
+
+ String codes = String.join(", ", this.codesGenerator.generateCodes(this.recoveryCodesAmount));
+
+ source.sendMessage(
+ LegacyComponentSerializer.legacyAmpersand().deserialize(
+ MessageFormat.format(this.recovery, codes)
+ ).clickEvent(ClickEvent.copyToClipboard(codes))
+ );
+ } else {
+ source.sendMessage(this.usage);
+ }
+ break;
+ }
+ case "disable": {
+ if (args.length != 2) {
+ source.sendMessage(this.usage);
+ return;
+ }
+
+ playerInfo = AuthSessionHandler.fetchInfo(this.playerDao, username);
+
+ if (playerInfo == null) {
+ source.sendMessage(this.notRegistered);
+ return;
+ }
+
+ if (AuthSessionHandler.getVerifier().isValidCode(playerInfo.getTotpToken(), args[1])) {
+ try {
+ updateBuilder = this.playerDao.updateBuilder();
+ updateBuilder.where().eq("nickname", username);
+ updateBuilder.updateColumnValue("totpToken", "");
+ updateBuilder.update();
+
+ source.sendMessage(this.disabled);
+ } catch (SQLException e) {
+ source.sendMessage(this.errorOccurred);
+ e.printStackTrace();
+ }
+ } else {
+ source.sendMessage(this.wrong);
+ }
+ break;
+ }
+ default: {
+ source.sendMessage(this.usage);
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean hasPermission(SimpleCommand.Invocation invocation) {
+ return invocation.source().getPermissionValue("limboauth.commands.totp") != Tristate.FALSE;
+ }
+}
diff --git a/src/main/java/net/elytrium/limboauth/command/UnregisterCommand.java b/src/main/java/net/elytrium/limboauth/command/UnregisterCommand.java
new file mode 100644
index 0000000..aeab6ec
--- /dev/null
+++ b/src/main/java/net/elytrium/limboauth/command/UnregisterCommand.java
@@ -0,0 +1,97 @@
+/*
+ * 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 java.util.Locale;
+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 UnregisterCommand implements SimpleCommand {
+
+ private final LimboAuth plugin;
+ private final Dao<RegisteredPlayer, String> playerDao;
+
+ private final Component notPlayer;
+ private final Component notRegistered;
+ private final Component successful;
+ private final Component errorOccurred;
+ private final Component wrongPassword;
+ private final Component usage;
+
+ public UnregisterCommand(LimboAuth plugin, Dao<RegisteredPlayer, String> playerDao) {
+ this.plugin = plugin;
+ this.playerDao = playerDao;
+
+ this.notPlayer = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_PLAYER);
+ this.notRegistered = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NOT_REGISTERED);
+ this.successful = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.UNREGISTER_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.UNREGISTER_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")) {
+ RegisteredPlayer player = AuthSessionHandler.fetchInfo(this.playerDao, ((Player) source).getUsername());
+ if (player == null) {
+ source.sendMessage(this.notRegistered);
+ } else if (AuthSessionHandler.checkPassword(args[0], player, this.playerDao)) {
+ try {
+ this.playerDao.deleteById(((Player) source).getUsername().toLowerCase(Locale.ROOT));
+ this.plugin.removePlayerFromCache((Player) source);
+ ((Player) source).disconnect(this.successful);
+ } catch (SQLException e) {
+ source.sendMessage(this.errorOccurred);
+ e.printStackTrace();
+ }
+ } 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;
+ }
+}