[FEAT] New Access control system to replace whitelisting and account linking

This commit is contained in:
2023-10-20 20:44:21 +02:00
parent d089a214ba
commit fdb51c4d01
21 changed files with 645 additions and 19 deletions

View File

@@ -62,6 +62,9 @@ dependencies {
implementation("com.google.code.gson:gson:${gson}") implementation("com.google.code.gson:gson:${gson}")
implementation("com.google.guava:guava:31.1-jre") implementation("com.google.guava:guava:31.1-jre")
implementation 'com.mojang:authlib:4.0.43' implementation 'com.mojang:authlib:4.0.43'
compileOnly "org.projectlombok:lombok:${lombok}"
annotationProcessor "org.projectlombok:lombok:${lombok}"
} }
shadowJar { shadowJar {
@@ -114,7 +117,7 @@ shadowJar {
relocate 'org.reflections', shade_group + 'org.reflections' relocate 'org.reflections', shade_group + 'org.reflections'
} }
exclude 'META-INF/**' exclude 'META-INF/**'
setArchiveClassifier('') setArchiveClassifier('verification')
} }
publishing { publishing {

View File

@@ -20,3 +20,4 @@ commons=3.12.0
commonsio=2.11.0 commonsio=2.11.0
gson=2.10.1 gson=2.10.1
craterlib=1.0.0 craterlib=1.0.0
lombok=1.18.30

View File

@@ -4,8 +4,20 @@
*/ */
package com.hypherionmc.sdlink.core.accounts; package com.hypherionmc.sdlink.core.accounts;
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.discord.BotController;
import com.hypherionmc.sdlink.core.managers.RoleManager;
import com.hypherionmc.sdlink.core.messaging.Result;
import com.hypherionmc.sdlink.core.util.SDLinkUtils;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.UserSnowflake;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
@@ -18,6 +30,9 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
/** /**
* @author HypherionSA * @author HypherionSA
@@ -85,7 +100,174 @@ public class MinecraftAccount {
return standard(profile.getName()); return standard(profile.getName());
} }
// TODO Verification public static SDLinkAccount getStoredFromUUID(String uuid) {
sdlinkDatabase.reloadCollection("verifiedaccounts");
return sdlinkDatabase.findById(uuid, SDLinkAccount.class);
}
public boolean isAccountVerified() {
SDLinkAccount account = getStoredAccount();
if (account == null)
return false;
return !SDLinkUtils.isNullOrEmpty(account.getDiscordID());
}
public SDLinkAccount getStoredAccount() {
sdlinkDatabase.reloadCollection("verifiedaccounts");
SDLinkAccount account = sdlinkDatabase.findById(this.uuid.toString(), SDLinkAccount.class);
return account == null ? newDBEntry() : account;
}
@NotNull
public SDLinkAccount newDBEntry() {
SDLinkAccount account = new SDLinkAccount();
account.setUsername(this.username);
account.setUuid(this.uuid.toString());
account.setDiscordID(null);
account.setVerifyCode(null);
account.setOffline(this.isOffline);
sdlinkDatabase.upsert(account);
sdlinkDatabase.reloadCollection("verifiedaccounts");
return account;
}
@NotNull
public String getDiscordName() {
SDLinkAccount account = getStoredAccount();
if (account == null || SDLinkUtils.isNullOrEmpty(account.getDiscordID()))
return "Unlinked";
User discordUser = BotController.INSTANCE.getJDA().getUserById(account.getDiscordID());
return discordUser == null ? "Unlinked" : discordUser.getEffectiveName();
}
@Nullable
public User getDiscordUser() {
SDLinkAccount storedAccount = getStoredAccount();
if (storedAccount == null || SDLinkUtils.isNullOrEmpty(storedAccount.getDiscordID()))
return null;
return BotController.INSTANCE.getJDA().getUserById(storedAccount.getDiscordID());
}
public Result verifyAccount(Member member, Guild guild) {
SDLinkAccount account = getStoredAccount();
if (account == null)
return Result.error("We couldn't find your Minecraft account. Please ask the staff for assistance");
account.setDiscordID(member.getId());
account.setVerifyCode(null);
try {
sdlinkDatabase.upsert(account);
sdlinkDatabase.reloadCollection("verifiedaccounts");
} catch (Exception e) {
if (SDLinkConfig.INSTANCE.generalConfig.debugging) {
e.printStackTrace();
}
}
if (RoleManager.getVerifiedRole() != null) {
try {
guild.addRoleToMember(UserSnowflake.fromId(member.getId()), RoleManager.getVerifiedRole()).queue();
} catch (Exception e) {
if (SDLinkConfig.INSTANCE.generalConfig.debugging) {
e.printStackTrace();
}
}
}
return Result.success("Your account has been verified");
}
public Result unverifyAccount(Member member, Guild guild) {
SDLinkAccount account = getStoredAccount();
if (account == null)
return Result.error("We couldn't find your Minecraft account. Please ask the staff for assistance");
account.setDiscordID(null);
account.setVerifyCode(null);
try {
sdlinkDatabase.upsert(account);
sdlinkDatabase.reloadCollection("verifiedaccounts");
} catch (Exception e) {
if (SDLinkConfig.INSTANCE.generalConfig.debugging) {
e.printStackTrace();
}
}
if (RoleManager.getVerifiedRole() != null) {
try {
guild.removeRoleFromMember(UserSnowflake.fromId(member.getId()), RoleManager.getVerifiedRole()).queue();
} catch (Exception e) {
if (SDLinkConfig.INSTANCE.generalConfig.debugging) {
e.printStackTrace();
}
}
}
return Result.success("Your account has been un-verified");
}
public Result checkAccessControl() {
if (!SDLinkConfig.INSTANCE.accessControl.enabled) {
return Result.success("pass");
}
SDLinkAccount account = getStoredAccount();
if (account == null)
return Result.error("notFound");
if (SDLinkUtils.isNullOrEmpty(account.getDiscordID()))
return Result.error("notVerified");
if (SDLinkConfig.INSTANCE.accessControl.requireDiscordMembership) {
Guild guild = BotController.INSTANCE.getJDA().getGuilds().get(0);
if (guild == null)
return Result.error("noGuildFound");
Member member = guild.getMemberById(account.getDiscordID());
if (member == null)
return Result.error("memberNotFound");
}
if (!SDLinkConfig.INSTANCE.accessControl.requiredRoles.isEmpty() && !RoleManager.getVerificationRoles().isEmpty()) {
AtomicBoolean anyFound = new AtomicBoolean(false);
Guild guild = BotController.INSTANCE.getJDA().getGuilds().get(0);
if (guild == null)
return Result.error("noGuildFound");
Member member = guild.getMemberById(account.getDiscordID());
if (member != null) {
member.getRoles().forEach(r -> {
if (RoleManager.getVerificationRoles().stream().anyMatch(role -> role.getIdLong() == r.getIdLong())) {
if (!anyFound.get()) {
anyFound.set(true);
}
}
});
if (!anyFound.get())
return Result.error("rolesNotFound");
} else {
return Result.error("memberNotFound");
}
}
return Result.success("pass");
}
public String getUsername() { public String getUsername() {
return username; return username;

View File

@@ -50,7 +50,9 @@ public class SDLinkConfig extends ModuleConfig {
@SpecComment("Change in which channel messages appear") @SpecComment("Change in which channel messages appear")
public MessageChannelConfig messageDestinations = new MessageChannelConfig(); public MessageChannelConfig messageDestinations = new MessageChannelConfig();
// TODO Verification Config @Path("accessControl")
@SpecComment("Manage access to your server, similar to whitelisting")
public AccessControl accessControl = new AccessControl();
@Path("minecraftCommands") @Path("minecraftCommands")
@SpecComment("Execute Minecraft commands in Discord") @SpecComment("Execute Minecraft commands in Discord")

View File

@@ -0,0 +1,47 @@
package com.hypherionmc.sdlink.core.config.impl;
import me.hypherionmc.moonconfig.core.conversion.Path;
import me.hypherionmc.moonconfig.core.conversion.SpecComment;
import java.util.ArrayList;
import java.util.List;
public class AccessControl {
@Path("enabled")
@SpecComment("Enable Access Control")
public boolean enabled = false;
@Path("requireDiscordMembership")
@SpecComment("Does the player need to be a member of your discord to join")
public boolean requireDiscordMembership = false;
@Path("requiredRoles")
@SpecComment("Optional: The player requires any of these roles to be able to join your server")
public List<String> requiredRoles = new ArrayList<>();
@Path("verifiedRole")
@SpecComment("Optional: Role name or ID to assign to verified player accounts")
public String verifiedRole = "";
@Path("verificationMessages")
@SpecComment("Configure messages shown to players when they don't meet verification requirements")
public AccessMessages verificationMessages = new AccessMessages();
public static class AccessMessages {
@Path("accountVerification")
@SpecComment("The message shown to players that are not verified")
public String accountVerify = "This server requires account verification. Your verification code is: {code}. Please visit our discord server for instructions on how to verify your account.";
@Path("nonMember")
@SpecComment("Message to show to players that are not a member of your discord")
public String nonMember = "Sorry, you need to be a member of our discord server to join this server";
@Path("requireRoles")
@SpecComment("Message to show when player doesn't have one of the required roles. Use {roles} to display the names of configured roles")
public String requireRoles = "Sorry, but you require any of the following roles: {roles}";
}
}

View File

@@ -0,0 +1,27 @@
package com.hypherionmc.sdlink.core.database;
import io.jsondb.annotation.Document;
import io.jsondb.annotation.Id;
import lombok.Getter;
import lombok.Setter;
@Document(collection = "verifiedaccounts", schemaVersion = "1.0")
public class SDLinkAccount {
@Id
@Getter @Setter
private String uuid;
@Getter @Setter
private String username;
@Getter @Setter
private String discordID;
@Getter @Setter
private String verifyCode;
@Getter @Setter
private boolean isOffline;
}

View File

@@ -10,6 +10,7 @@ import com.hypherionmc.sdlink.core.discord.events.DiscordEventHandler;
import com.hypherionmc.sdlink.core.managers.DatabaseManager; import com.hypherionmc.sdlink.core.managers.DatabaseManager;
import com.hypherionmc.sdlink.core.managers.EmbedManager; import com.hypherionmc.sdlink.core.managers.EmbedManager;
import com.hypherionmc.sdlink.core.managers.WebhookManager; import com.hypherionmc.sdlink.core.managers.WebhookManager;
import com.hypherionmc.sdlink.core.services.SDLinkPlatform;
import com.hypherionmc.sdlink.core.util.EncryptionUtil; import com.hypherionmc.sdlink.core.util.EncryptionUtil;
import com.hypherionmc.sdlink.core.util.ThreadedEventManager; import com.hypherionmc.sdlink.core.util.ThreadedEventManager;
import com.jagrosh.jdautilities.command.CommandClient; import com.jagrosh.jdautilities.command.CommandClient;
@@ -192,7 +193,9 @@ public class BotController {
* Ensure that whitelisting is set up properly, so the bot can use the feature * Ensure that whitelisting is set up properly, so the bot can use the feature
*/ */
public void checkWhiteListing() { public void checkWhiteListing() {
// TODO Verification if (SDLinkConfig.INSTANCE.accessControl.enabled && !SDLinkPlatform.minecraftHelper.checkWhitelisting().isError()) {
getLogger().error("SDLink Access Control is enabled, but so is whitelisting on your server. You need to disable whitelisting to use the AccessControl feature");
}
} }
public Logger getLogger() { public Logger getLogger() {

View File

@@ -7,6 +7,7 @@ package com.hypherionmc.sdlink.core.discord.commands;
import com.hypherionmc.sdlink.core.discord.commands.slash.general.HelpSlashCommand; import com.hypherionmc.sdlink.core.discord.commands.slash.general.HelpSlashCommand;
import com.hypherionmc.sdlink.core.discord.commands.slash.general.PlayerListSlashCommand; import com.hypherionmc.sdlink.core.discord.commands.slash.general.PlayerListSlashCommand;
import com.hypherionmc.sdlink.core.discord.commands.slash.general.ServerStatusSlashCommand; import com.hypherionmc.sdlink.core.discord.commands.slash.general.ServerStatusSlashCommand;
import com.hypherionmc.sdlink.core.discord.commands.slash.verification.*;
import com.jagrosh.jdautilities.command.CommandClient; import com.jagrosh.jdautilities.command.CommandClient;
import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommand;
@@ -28,7 +29,11 @@ public class CommandManager {
} }
private void addCommands() { private void addCommands() {
// TODO Verification commands.add(new VerifyAccountCommand());
commands.add(new UnverifyAccountSlashCommand());
commands.add(new StaffUnverifyCommand());
commands.add(new StaffVerifyAccountCommand());
commands.add(new ViewVerifiedAccounts());
// Enable the Server Status command // Enable the Server Status command
commands.add(new ServerStatusSlashCommand()); commands.add(new ServerStatusSlashCommand());

View File

@@ -63,7 +63,9 @@ public class PlayerListSlashCommand extends SDLinkSlashCommand {
p.forEach(account -> { p.forEach(account -> {
sb.append("`").append(account.getUsername()).append("`"); sb.append("`").append(account.getUsername()).append("`");
// TODO Verification if (account.getDiscordUser() != null) {
sb.append(" - ").append(account.getDiscordUser().getAsMention());
}
sb.append("\r\n"); sb.append("\r\n");
}); });

View File

@@ -0,0 +1,58 @@
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.discord.commands.slash.SDLinkSlashCommand;
import com.hypherionmc.sdlink.core.messaging.Result;
import com.jagrosh.jdautilities.command.SlashCommandEvent;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import java.util.ArrayList;
import java.util.List;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
public class StaffUnverifyCommand extends SDLinkSlashCommand {
public StaffUnverifyCommand() {
super(false);
this.name = "staffunverify";
this.help = "Unverify another player's Minecraft account";
List<OptionData> options = new ArrayList<>() {{
add(new OptionData(OptionType.USER, "discorduser", "The discord user the minecraft account belongs to").setRequired(true));
add(new OptionData(OptionType.STRING, "mcname", "The minecraft account of the linked user").setRequired(true));
}};
this.options = options;
}
@Override
protected void execute(SlashCommandEvent event) {
sdlinkDatabase.reloadCollection("verifiedaccounts");
List<SDLinkAccount> accounts = sdlinkDatabase.findAll(SDLinkAccount.class);
if (accounts.isEmpty()) {
event.reply("Sorry, but this server does not contain any stored players in its database").setEphemeral(true).queue();
return;
}
String mcname = event.getOption("mcname").getAsString();
User user = event.getOption("discorduser").getAsUser();
Member member = event.getGuild().getMemberById(user.getId());
if (member == null) {
event.reply(user.getEffectiveName() + " is not a member of this discord server").setEphemeral(true).queue();
return;
}
MinecraftAccount minecraftAccount = MinecraftAccount.standard(mcname);
Result result = minecraftAccount.unverifyAccount(member, event.getGuild());
event.reply(result.getMessage()).setEphemeral(true).queue();
}
}

View File

@@ -0,0 +1,48 @@
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
import com.hypherionmc.sdlink.core.discord.commands.slash.SDLinkSlashCommand;
import com.hypherionmc.sdlink.core.messaging.Result;
import com.jagrosh.jdautilities.command.SlashCommandEvent;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import java.util.ArrayList;
import java.util.List;
public class StaffVerifyAccountCommand extends SDLinkSlashCommand {
public StaffVerifyAccountCommand() {
super(true);
this.name = "staffverify";
this.help = "Allow staff members verify minecraft players, without verification";
List<OptionData> options = new ArrayList<>() {{
add(new OptionData(OptionType.USER, "discorduser", "The discord user the minecraft account belongs to").setRequired(true));
add(new OptionData(OptionType.STRING, "mcname", "The minecraft account to link to the user").setRequired(true));
}};
this.options = options;
}
@Override
protected void execute(SlashCommandEvent event) {
String mcname = event.getOption("mcname").getAsString();
User user = event.getOption("discorduser").getAsUser();
Member member = event.getGuild().getMemberById(user.getId());
if (member == null) {
event.reply(user.getEffectiveName() + " is not a member of this discord server").setEphemeral(true).queue();
return;
}
MinecraftAccount minecraftAccount = MinecraftAccount.standard(mcname);
Result result = minecraftAccount.verifyAccount(member, event.getGuild());
event.reply(result.getMessage()).setEphemeral(true).queue();
}
}

View File

@@ -0,0 +1,43 @@
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.discord.commands.slash.SDLinkSlashCommand;
import com.hypherionmc.sdlink.core.messaging.Result;
import com.jagrosh.jdautilities.command.SlashCommandEvent;
import java.util.List;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
public class UnverifyAccountSlashCommand extends SDLinkSlashCommand {
public UnverifyAccountSlashCommand() {
super(false);
this.name = "unverify";
this.help = "Unverify your previously verified Minecraft account";
}
@Override
protected void execute(SlashCommandEvent event) {
sdlinkDatabase.reloadCollection("verifiedaccounts");
List<SDLinkAccount> accounts = sdlinkDatabase.findAll(SDLinkAccount.class);
if (accounts.isEmpty()) {
event.reply("Sorry, but this server does not contain any stored players in its database").setEphemeral(true).queue();
return;
}
for (SDLinkAccount account : accounts) {
if (account.getDiscordID() != null && account.getDiscordID().equalsIgnoreCase(event.getMember().getId())) {
MinecraftAccount minecraftAccount = MinecraftAccount.standard(account.getUsername());
Result result = minecraftAccount.unverifyAccount(event.getMember(), event.getGuild());
event.reply(result.getMessage()).setEphemeral(true).queue();
break;
}
}
event.reply("Sorry, we could not un-verify your Minecraft account. Please try again").setEphemeral(true).queue();
}
}

View File

@@ -0,0 +1,55 @@
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.discord.commands.slash.SDLinkSlashCommand;
import com.hypherionmc.sdlink.core.messaging.Result;
import com.jagrosh.jdautilities.command.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import java.util.Collections;
import java.util.List;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
public class VerifyAccountCommand extends SDLinkSlashCommand {
public VerifyAccountCommand() {
super(false);
this.name = "verify";
this.help = "Verify your Minecraft account to access the server";
this.options = Collections.singletonList(new OptionData(OptionType.INTEGER, "code", "The verification code from the Minecraft Kick Message").setRequired(true));
}
@Override
protected void execute(SlashCommandEvent event) {
int mcCode = event.getOption("code") != null ? event.getOption("code").getAsInt() : 0;
if (mcCode == 0) {
event.reply("You need to provide a verification code").setEphemeral(true).queue();
return;
}
sdlinkDatabase.reloadCollection("verifiedaccounts");
List<SDLinkAccount> accounts = sdlinkDatabase.findAll(SDLinkAccount.class);
if (accounts.isEmpty()) {
event.reply("Sorry, but this server does not contain any stored players in its database").setEphemeral(true).queue();
return;
}
for (SDLinkAccount account : accounts) {
if (account.getVerifyCode().equalsIgnoreCase(String.valueOf(mcCode))) {
MinecraftAccount minecraftAccount = MinecraftAccount.standard(account.getUsername());
Result result = minecraftAccount.verifyAccount(event.getMember(), event.getGuild());
event.reply(result.getMessage()).setEphemeral(true).queue();
return;
}
}
event.reply("Sorry, we could not verify your Minecraft account. Please try again").setEphemeral(true).queue();
}
}

View File

@@ -0,0 +1,74 @@
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.discord.commands.slash.SDLinkSlashCommand;
import com.hypherionmc.sdlink.core.util.MessageUtil;
import com.jagrosh.jdautilities.command.SlashCommandEvent;
import com.jagrosh.jdautilities.menu.EmbedPaginator;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
/**
* @author HypherionSA
* Staff Command to view a list of Linked Minecraft and Discord accounts
*/
public class ViewVerifiedAccounts extends SDLinkSlashCommand {
public ViewVerifiedAccounts() {
super(true);
this.name = "verifiedaccounts";
this.help = "View a list of verified Minecraft Accounts";
}
@Override
protected void execute(SlashCommandEvent event) {
EmbedPaginator.Builder paginator = MessageUtil.defaultPaginator(event);
sdlinkDatabase.reloadCollection("verifiedaccounts");
List<SDLinkAccount> accounts = sdlinkDatabase.findAll(SDLinkAccount.class);
EmbedBuilder builder = new EmbedBuilder();
ArrayList<MessageEmbed> pages = new ArrayList<>();
AtomicInteger count = new AtomicInteger();
if (accounts.isEmpty()) {
event.reply("There are no verified accounts for this discord").setEphemeral(true).queue();
return;
}
MessageUtil.listBatches(accounts, 10).forEach(itm -> {
count.getAndIncrement();
builder.clear();
builder.setTitle("Verified Accounts - Page " + count + "/" + (int)Math.ceil(((float)accounts.size() / 10)));
builder.setColor(Color.GREEN);
StringBuilder sBuilder = new StringBuilder();
itm.forEach(v -> {
Member member = null;
if (v.getDiscordID() != null && !v.getDiscordID().isEmpty()) {
member = event.getGuild().getMemberById(v.getDiscordID());
}
sBuilder.append(v.getUsername()).append(" -> ").append(member == null ? "Unlinked" : member.getAsMention()).append("\r\n");
});
builder.setDescription(sBuilder);
pages.add(builder.build());
});
paginator.setItems(pages);
EmbedPaginator embedPaginator = paginator.build();
event.replyEmbeds(pages.get(0)).setEphemeral(false).queue(success -> success.retrieveOriginal().queue(msg -> embedPaginator.paginate(msg, 1)));
}
}

View File

@@ -5,6 +5,9 @@
package com.hypherionmc.sdlink.core.discord.events; package com.hypherionmc.sdlink.core.discord.events;
import com.hypherionmc.craterlib.core.event.CraterEventBus; import com.hypherionmc.craterlib.core.event.CraterEventBus;
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.discord.BotController; import com.hypherionmc.sdlink.core.discord.BotController;
import com.hypherionmc.sdlink.core.discord.commands.slash.general.ServerStatusSlashCommand; import com.hypherionmc.sdlink.core.discord.commands.slash.general.ServerStatusSlashCommand;
import com.hypherionmc.sdlink.core.discord.hooks.BotReadyHooks; import com.hypherionmc.sdlink.core.discord.hooks.BotReadyHooks;
@@ -14,6 +17,7 @@ import com.hypherionmc.sdlink.core.events.SDLinkReadyEvent;
import com.hypherionmc.sdlink.core.managers.CacheManager; import com.hypherionmc.sdlink.core.managers.CacheManager;
import com.hypherionmc.sdlink.core.managers.ChannelManager; import com.hypherionmc.sdlink.core.managers.ChannelManager;
import com.hypherionmc.sdlink.core.managers.PermissionChecker; import com.hypherionmc.sdlink.core.managers.PermissionChecker;
import com.hypherionmc.sdlink.core.services.SDLinkPlatform;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.events.channel.ChannelCreateEvent; import net.dv8tion.jda.api.events.channel.ChannelCreateEvent;
import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent; import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent;
@@ -28,6 +32,11 @@ import net.dv8tion.jda.api.events.session.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
/** /**
* @author HypherionSA * @author HypherionSA
* Class to provide Hooks for Discord Events, such as message received, and login * Class to provide Hooks for Discord Events, such as message received, and login
@@ -129,6 +138,26 @@ public class DiscordEventHandler extends ListenerAdapter {
if (event.getUser().isBot()) if (event.getUser().isBot())
return; return;
// TODO Verification if (!SDLinkConfig.INSTANCE.accessControl.enabled)
return;
try {
List<SDLinkAccount> accounts = sdlinkDatabase.getCollection(SDLinkAccount.class);
Optional<SDLinkAccount> account = accounts.stream().filter(a -> a.getDiscordID().equalsIgnoreCase(event.getUser().getId())).findFirst();
account.ifPresent(a -> {
MinecraftAccount acc = MinecraftAccount.standard(a.getUsername());
if (acc != null) {
sdlinkDatabase.remove(a, SDLinkAccount.class);
SDLinkPlatform.minecraftHelper.banPlayer(acc);
sdlinkDatabase.reloadCollection("verifiedaccounts");
}
});
} catch (Exception e) {
if (SDLinkConfig.INSTANCE.generalConfig.debugging) {
e.printStackTrace();
}
}
} }
} }

View File

@@ -5,14 +5,18 @@
package com.hypherionmc.sdlink.core.discord.hooks; package com.hypherionmc.sdlink.core.discord.hooks;
import com.hypherionmc.sdlink.core.config.SDLinkConfig; import com.hypherionmc.sdlink.core.config.SDLinkConfig;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.services.SDLinkPlatform; import com.hypherionmc.sdlink.core.services.SDLinkPlatform;
import net.dv8tion.jda.api.entities.ISnowflake; import net.dv8tion.jda.api.entities.ISnowflake;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabase;
public class MinecraftCommandHook { public class MinecraftCommandHook {
public static void discordMessageEvent(MessageReceivedEvent event) { public static void discordMessageEvent(MessageReceivedEvent event) {
@@ -26,18 +30,19 @@ public class MinecraftCommandHook {
roles.add(event.getMember().getIdLong()); roles.add(event.getMember().getIdLong());
roles.add(0L); roles.add(0L);
// TODO Verification sdlinkDatabase.reloadCollection("verifiedaccounts");
List<SDLinkAccount> accounts = sdlinkDatabase.findAll(SDLinkAccount.class);
Optional<SDLinkAccount> account = accounts.stream().filter(u -> u.getDiscordID().equals(event.getMember().getId())).findFirst();
Integer permLevel = SDLinkConfig.INSTANCE.linkedCommands.permissions.stream().filter(r -> roles.contains(Long.parseLong(r.role))).map(r -> r.permissionLevel).max(Integer::compareTo).orElse(-1); Integer permLevel = SDLinkConfig.INSTANCE.linkedCommands.permissions.stream().filter(r -> roles.contains(Long.parseLong(r.role))).map(r -> r.permissionLevel).max(Integer::compareTo).orElse(-1);
List<String> commands = SDLinkConfig.INSTANCE.linkedCommands.permissions.stream().filter(c -> roles.contains(Long.parseLong(c.role))).flatMap(c -> c.commands.stream()).filter(s -> !s.isEmpty()).toList(); List<String> commands = SDLinkConfig.INSTANCE.linkedCommands.permissions.stream().filter(c -> roles.contains(Long.parseLong(c.role))).flatMap(c -> c.commands.stream()).filter(s -> !s.isEmpty()).toList();
String raw = event.getMessage().getContentRaw().substring(SDLinkConfig.INSTANCE.linkedCommands.prefix.length()); String raw = event.getMessage().getContentRaw().substring(SDLinkConfig.INSTANCE.linkedCommands.prefix.length());
// TODO Verification
if (commands.stream().anyMatch(raw::startsWith)) { if (commands.stream().anyMatch(raw::startsWith)) {
SDLinkPlatform.minecraftHelper.executeMinecraftCommand(raw, Integer.MAX_VALUE, event, null); SDLinkPlatform.minecraftHelper.executeMinecraftCommand(raw, Integer.MAX_VALUE, event, account.orElse(null));
} else { } else {
SDLinkPlatform.minecraftHelper.executeMinecraftCommand(raw, permLevel, event, null); SDLinkPlatform.minecraftHelper.executeMinecraftCommand(raw, permLevel, event, account.orElse(null));
} }
} }
} }

View File

@@ -4,8 +4,11 @@
*/ */
package com.hypherionmc.sdlink.core.managers; package com.hypherionmc.sdlink.core.managers;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import io.jsondb.JsonDBTemplate; import io.jsondb.JsonDBTemplate;
import java.util.Collections;
/** /**
* @author HypherionSA * @author HypherionSA
* Helper class to initialize the JSON database * Helper class to initialize the JSON database
@@ -15,10 +18,14 @@ public class DatabaseManager {
public static final JsonDBTemplate sdlinkDatabase = new JsonDBTemplate("sdlinkstorage", "com.hypherionmc.sdlink.core.database"); public static final JsonDBTemplate sdlinkDatabase = new JsonDBTemplate("sdlinkstorage", "com.hypherionmc.sdlink.core.database");
static { static {
sdlinkDatabase.setupDB(Collections.singleton(SDLinkAccount.class));
} }
public static void initialize() { public static void initialize() {
// Todo Verification if (!sdlinkDatabase.collectionExists(SDLinkAccount.class)) {
sdlinkDatabase.createCollection(SDLinkAccount.class);
}
sdlinkDatabase.reloadCollection("verifiedaccounts");
} }
} }

View File

@@ -4,7 +4,9 @@
*/ */
package com.hypherionmc.sdlink.core.managers; package com.hypherionmc.sdlink.core.managers;
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
import com.hypherionmc.sdlink.core.discord.BotController; import com.hypherionmc.sdlink.core.discord.BotController;
import com.hypherionmc.sdlink.core.util.SDLinkUtils;
import com.hypherionmc.sdlink.core.util.SystemUtils; import com.hypherionmc.sdlink.core.util.SystemUtils;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
@@ -19,7 +21,8 @@ import java.util.concurrent.atomic.AtomicInteger;
*/ */
public class RoleManager { public class RoleManager {
private static final Set<Role> autoWhitelistRoles = new HashSet<>(); private static final Set<Role> verificationRoles = new HashSet<>();
private static Role verifiedRole = null;
/** /**
* Check and load the roles required by the bot * Check and load the roles required by the bot
@@ -27,7 +30,18 @@ public class RoleManager {
* @param builder * @param builder
*/ */
public static void loadRequiredRoles(AtomicInteger errCount, StringBuilder builder) { public static void loadRequiredRoles(AtomicInteger errCount, StringBuilder builder) {
// TODO Verification Roles if (SDLinkConfig.INSTANCE.accessControl.enabled) {
SDLinkConfig.INSTANCE.accessControl.requiredRoles.forEach(r -> {
Role role = getRole(errCount, builder, "Access Control Role", r);
if (role != null)
verificationRoles.add(role);
});
if (!SDLinkUtils.isNullOrEmpty(SDLinkConfig.INSTANCE.accessControl.verifiedRole)) {
verifiedRole = getRole(errCount, builder, "Verified Player Role", SDLinkConfig.INSTANCE.accessControl.verifiedRole);
}
}
} }
/** /**
@@ -65,4 +79,12 @@ public class RoleManager {
return null; return null;
} }
public static Set<Role> getVerificationRoles() {
return verificationRoles;
}
public static Role getVerifiedRole() {
return verifiedRole;
}
} }

View File

@@ -42,7 +42,11 @@ public final class DiscordMessageBuilder {
if (SDLinkConfig.INSTANCE.chatConfig.useLinkedNames && this.author != DiscordAuthor.SERVER) { if (SDLinkConfig.INSTANCE.chatConfig.useLinkedNames && this.author != DiscordAuthor.SERVER) {
MinecraftAccount account = MinecraftAccount.standard(author.getRawUsername()); MinecraftAccount account = MinecraftAccount.standard(author.getRawUsername());
// TODO Verification User discordUser = account.getDiscordUser();
if (account != null && discordUser != null) {
this.author = DiscordAuthor.of(discordUser.getEffectiveName(), author.getUuid(), author.getRawUsername());
}
} }
return this; return this;

View File

@@ -5,6 +5,7 @@
package com.hypherionmc.sdlink.core.services.helpers; package com.hypherionmc.sdlink.core.services.helpers;
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount; import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
import com.hypherionmc.sdlink.core.messaging.Result; import com.hypherionmc.sdlink.core.messaging.Result;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
@@ -26,8 +27,7 @@ public interface IMinecraftHelper {
List<MinecraftAccount> getOnlinePlayers(); List<MinecraftAccount> getOnlinePlayers();
long getServerUptime(); long getServerUptime();
String getServerVersion(); String getServerVersion();
// TODO Verification void executeMinecraftCommand(String command, int permLevel, MessageReceivedEvent event, @Nullable SDLinkAccount account);
void executeMinecraftCommand(String command, int permLevel, MessageReceivedEvent event, @Nullable Object account);
boolean isOnlineMode(); boolean isOnlineMode();
void banPlayer(MinecraftAccount acc); void banPlayer(MinecraftAccount acc);
} }

View File

@@ -0,0 +1,9 @@
package com.hypherionmc.sdlink.core.util;
public class SDLinkUtils {
public static boolean isNullOrEmpty(String inString) {
return inString == null || inString.isEmpty();
}
}