Implement allowedCommands configuration

- Forward more events to proxy
- Now all commands that are executed if the player is not logged in and is not on a login server will be blocked.
If the player is on a login server and executes a command that is not allowed, it will be blocked.
- Removed server argument from events
If a specific server is required, it can be obtained from the player.
- Add isAuthServer and isInAuthServer methods to API
This commit is contained in:
4drian3d 2021-11-22 13:00:45 -05:00
parent 8d16142c4e
commit 2303f9b709
13 changed files with 237 additions and 103 deletions

View File

@ -2,6 +2,7 @@ package com.glyart.authmevelocity.proxy;
import com.glyart.authmevelocity.proxy.config.AuthMeConfig; import com.glyart.authmevelocity.proxy.config.AuthMeConfig;
import com.glyart.authmevelocity.proxy.listener.FastLoginListener; import com.glyart.authmevelocity.proxy.listener.FastLoginListener;
import com.glyart.authmevelocity.proxy.listener.PluginMessageListener;
import com.glyart.authmevelocity.proxy.listener.ProxyListener; import com.glyart.authmevelocity.proxy.listener.ProxyListener;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
@ -42,7 +43,8 @@ public class AuthMeVelocityPlugin {
proxy.getChannelRegistrar().register( proxy.getChannelRegistrar().register(
MinecraftChannelIdentifier.create("authmevelocity", "main")); MinecraftChannelIdentifier.create("authmevelocity", "main"));
proxy.getEventManager().register(this, new ProxyListener(proxy, logger, config)); proxy.getEventManager().register(this, new ProxyListener(config));
proxy.getEventManager().register(this, new PluginMessageListener(proxy, logger, config));
proxy.getPluginManager().getPlugin("fastlogin").ifPresent(fastlogin -> proxy.getPluginManager().getPlugin("fastlogin").ifPresent(fastlogin ->
proxy.getEventManager().register(this, new FastLoginListener(proxy))); proxy.getEventManager().register(this, new FastLoginListener(proxy)));

View File

@ -3,7 +3,10 @@ package com.glyart.authmevelocity.proxy;
import java.util.UUID; import java.util.UUID;
import java.util.function.Predicate; import java.util.function.Predicate;
import com.glyart.authmevelocity.proxy.config.AuthMeConfig;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -52,5 +55,33 @@ public class AuthmeVelocityAPI {
.forEach(player -> AuthMeVelocityPlugin.loggedPlayers.remove(player.getUniqueId())); .forEach(player -> AuthMeVelocityPlugin.loggedPlayers.remove(player.getUniqueId()));
} }
/**
* Check if the player is on a login server
* @param player the player
* @return if the player is on a login server
*/
public static boolean isInAuthServer(@NotNull Player player){
var connection = player.getCurrentServer();
return connection.isPresent() && isAuthServer(connection.get());
}
/**
* Check if a server is intended to be a logging server
* @param server the server
* @return if the server is a login server
*/
public static boolean isAuthServer(@NotNull RegisteredServer server){
return AuthMeConfig.getConfig().getAuthServers().contains(server.getServerInfo().getName());
}
/**
* Checks if a connection is made from a login server
* @param connection the connection
* @return if the connection is made from a login server
*/
public static boolean isAuthServer(@NotNull ServerConnection connection){
return AuthMeConfig.getConfig().getAuthServers().contains(connection.getServerInfo().getName());
}
private AuthmeVelocityAPI(){} private AuthmeVelocityAPI(){}
} }

View File

@ -17,7 +17,7 @@ public class AuthMeConfig {
AuthmeVelocity Proxy AuthmeVelocity Proxy
Original Developer: xQuickGlare Original Developer: xQuickGlare
Actual Developer: 4drian3d Current Developer: 4drian3d
"""; """;
private static final HoconConfigurationLoader.Builder configBuilder = HoconConfigurationLoader.builder() private static final HoconConfigurationLoader.Builder configBuilder = HoconConfigurationLoader.builder()
.defaultOptions(opts -> opts .defaultOptions(opts -> opts
@ -49,12 +49,18 @@ public class AuthMeConfig {
"auth2" "auth2"
); );
private Commands commands = new Commands();
private ServerOnLogin send = new ServerOnLogin(); private ServerOnLogin send = new ServerOnLogin();
public Set<String> getAuthServers(){ public Set<String> getAuthServers(){
return this.authservers; return this.authservers;
} }
public Commands getCommandsConfig(){
return this.commands;
}
public ServerOnLogin getToServerOptions(){ public ServerOnLogin getToServerOptions(){
return this.send; return this.send;
} }
@ -81,6 +87,32 @@ public class AuthMeConfig {
return this.teleportServers; return this.teleportServers;
} }
} }
@ConfigSerializable
public static class Commands{
@Comment("Sets the commands that users who have not yet logged in can execute")
private Set<String> allowedCommands = Set.of(
"login",
"register",
"l",
"reg",
"email",
"captcha"
);
@Comment("""
Sets the message to send in case a non-logged-in player executes an unauthorized command
To deactivate the message, leave it empty""")
private String blockedCommandMessage = "&4You cannot execute commands if you are not logged in yet.";
public Set<String> getAllowedCommands(){
return this.allowedCommands;
}
public String getBlockedMessage() {
return this.blockedCommandMessage;
}
}
private static Config config; private static Config config;
public static Config getConfig(){ public static Config getConfig(){
return config; return config;

View File

@ -0,0 +1,17 @@
package com.glyart.authmevelocity.proxy.config;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class ConfigUtils {
public static void sendBlockedMessage(Player player){
var config = AuthMeConfig.getConfig();
String blockedMessage = config.getCommandsConfig().getBlockedMessage();
if(!blockedMessage.isBlank()){
player.sendMessage(
LegacyComponentSerializer.legacyAmpersand().deserialize(
blockedMessage));
}
}
}

View File

@ -1,11 +1,10 @@
package com.glyart.authmevelocity.proxy.event; package com.glyart.authmevelocity.proxy.event;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Event executed in case the player is successfully logged in * Event executed in case the player is successfully logged in
*/ */
public record ProxyLoginEvent(@NotNull Player player, @NotNull RegisteredServer server) {} public record ProxyLoginEvent(@NotNull Player player) {}

View File

@ -0,0 +1,7 @@
package com.glyart.authmevelocity.proxy.event;
import com.velocitypowered.api.proxy.Player;
import org.jetbrains.annotations.NotNull;
public record ProxyLogoutEvent(@NotNull Player player) {}

View File

@ -0,0 +1,7 @@
package com.glyart.authmevelocity.proxy.event;
import com.velocitypowered.api.proxy.Player;
import org.jetbrains.annotations.NotNull;
public record ProxyRegisterEvent(@NotNull Player player){}

View File

@ -1,11 +1,8 @@
package com.glyart.authmevelocity.proxy.listener; package com.glyart.authmevelocity.proxy.listener;
import java.util.Optional;
import com.github.games647.fastlogin.velocity.event.VelocityFastLoginAutoLoginEvent; import com.github.games647.fastlogin.velocity.event.VelocityFastLoginAutoLoginEvent;
import com.glyart.authmevelocity.proxy.AuthmeVelocityAPI; import com.glyart.authmevelocity.proxy.AuthmeVelocityAPI;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
public class FastLoginListener { public class FastLoginListener {
@ -15,7 +12,6 @@ public class FastLoginListener {
} }
@Subscribe @Subscribe
public void onAutoLogin(VelocityFastLoginAutoLoginEvent event){ public void onAutoLogin(VelocityFastLoginAutoLoginEvent event){
Optional<Player> autoLoginPlayer = server.getPlayer(event.getProfile().getName()); server.getPlayer(event.getProfile().getName()).ifPresent(AuthmeVelocityAPI::addPlayer);
autoLoginPlayer.ifPresent(AuthmeVelocityAPI::addPlayer);
} }
} }

View File

@ -0,0 +1,92 @@
package com.glyart.authmevelocity.proxy.listener;
import java.util.List;
import java.util.Random;
import com.glyart.authmevelocity.proxy.AuthmeVelocityAPI;
import com.glyart.authmevelocity.proxy.config.AuthMeConfig;
import com.glyart.authmevelocity.proxy.event.PreSendOnLoginEvent;
import com.glyart.authmevelocity.proxy.event.ProxyLoginEvent;
import com.glyart.authmevelocity.proxy.event.ProxyLogoutEvent;
import com.glyart.authmevelocity.proxy.event.ProxyRegisterEvent;
import com.google.common.io.ByteArrayDataInput;
import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
public class PluginMessageListener {
private final ProxyServer proxy;
private final Logger logger;
private final Random rm;
private AuthMeConfig.Config config;
public PluginMessageListener(@NotNull ProxyServer proxy, @NotNull Logger logger, @NotNull AuthMeConfig.Config config) {
this.proxy = proxy;
this.logger = logger;
this.rm = new Random();
this.config = config;
}
@Subscribe
public void onPluginMessage(final PluginMessageEvent event, Continuation continuation) {
if (!(event.getSource() instanceof ServerConnection connection) || !event.getIdentifier().getId().equals("authmevelocity:main")){
continuation.resume();
return;
}
event.setResult(PluginMessageEvent.ForwardResult.handled());
ByteArrayDataInput input = event.dataAsDataStream();
final String sChannel = input.readUTF();
final Player loggedPlayer = connection.getPlayer();
switch(sChannel){
case "LOGIN" -> {
if (AuthmeVelocityAPI.addPlayer(loggedPlayer)){
createServerConnectionRequest(loggedPlayer, config, proxy, logger, connection);
}
continuation.resume();
}
case "LOGOUT" -> {
if(AuthmeVelocityAPI.removePlayer(loggedPlayer)){
proxy.getEventManager().fireAndForget(new ProxyLogoutEvent(loggedPlayer));
}
continuation.resume();
}
case "REGISTER" -> {
proxy.getEventManager().fireAndForget(new ProxyRegisterEvent(loggedPlayer));
continuation.resume();
}
default -> continuation.resume();
}
}
private void createServerConnectionRequest(Player loggedPlayer, AuthMeConfig.Config config, ProxyServer proxy, Logger logger, ServerConnection connection){
final RegisteredServer loginServer = loggedPlayer.getCurrentServer().orElse(connection).getServer();
proxy.getEventManager().fireAndForget(new ProxyLoginEvent(loggedPlayer));
if(config.getToServerOptions().sendToServer()){
final List<String> serverList = config.getToServerOptions().getTeleportServers();
final String randomServer = serverList.get(rm.nextInt(serverList.size()));
proxy.getServer(randomServer).ifPresentOrElse(serverToSend ->
proxy.getEventManager().fire(new PreSendOnLoginEvent(loggedPlayer, loginServer, serverToSend)).thenAcceptAsync(preSendEvent -> {
if(preSendEvent.getResult().isAllowed()){
loggedPlayer.createConnectionRequest(serverToSend).connect().thenAcceptAsync(result -> {
if(!result.isSuccessful()) {
logger.info("Unable to connect the player {} to the server {}",
loggedPlayer.getUsername(),
serverToSend.getServerInfo().getName());
}
});
}
})
, () -> logger.info("The server {} does not exist", randomServer));
}
}
}

View File

@ -2,89 +2,25 @@ package com.glyart.authmevelocity.proxy.listener;
import com.glyart.authmevelocity.proxy.AuthmeVelocityAPI; import com.glyart.authmevelocity.proxy.AuthmeVelocityAPI;
import com.glyart.authmevelocity.proxy.config.AuthMeConfig; import com.glyart.authmevelocity.proxy.config.AuthMeConfig;
import com.glyart.authmevelocity.proxy.event.PreSendOnLoginEvent; import com.glyart.authmevelocity.proxy.config.ConfigUtils;
import com.glyart.authmevelocity.proxy.event.ProxyLoginEvent;
import com.google.common.io.ByteArrayDataInput;
import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.EventTask; import com.velocitypowered.api.event.EventTask;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.command.CommandExecuteEvent; import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.player.PlayerChatEvent; import com.velocitypowered.api.event.player.PlayerChatEvent;
import com.velocitypowered.api.event.player.ServerPreConnectEvent; import com.velocitypowered.api.event.player.ServerPreConnectEvent;
import com.velocitypowered.api.event.player.TabCompleteEvent; import com.velocitypowered.api.event.player.TabCompleteEvent;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import java.util.List;
import java.util.Optional;
import java.util.Random;
public class ProxyListener { public class ProxyListener {
private final ProxyServer proxy;
private final Logger logger;
private final Random rm;
private AuthMeConfig.Config config; private AuthMeConfig.Config config;
public ProxyListener(@NotNull ProxyServer proxy, @NotNull Logger logger, @NotNull AuthMeConfig.Config config) { public ProxyListener(@NotNull AuthMeConfig.Config config) {
this.proxy = proxy;
this.logger = logger;
this.rm = new Random();
this.config = config; this.config = config;
} }
@Subscribe
public void onPluginMessage(final PluginMessageEvent event, Continuation continuation) {
if (!(event.getSource() instanceof ServerConnection connection) || !event.getIdentifier().getId().equals("authmevelocity:main")){
continuation.resume();
return;
}
ByteArrayDataInput input = event.dataAsDataStream();
final String sChannel = input.readUTF();
if (!sChannel.equals("LOGIN")) {
continuation.resume();
return;
}
event.setResult(PluginMessageEvent.ForwardResult.handled());
//TODO: Test this
final Player loggedPlayer = connection.getPlayer();
if (AuthmeVelocityAPI.addPlayer(loggedPlayer)){
createServerConnectionRequest(loggedPlayer, config, proxy, logger, connection);
continuation.resume();
}
}
private void createServerConnectionRequest(Player loggedPlayer, AuthMeConfig.Config config, ProxyServer proxy, Logger logger, ServerConnection connection){
final RegisteredServer loginServer = loggedPlayer.getCurrentServer().orElse(connection).getServer();
proxy.getEventManager().fireAndForget(new ProxyLoginEvent(loggedPlayer, loginServer));
if(config.getToServerOptions().sendToServer()){
final List<String> serverList = config.getToServerOptions().getTeleportServers();
final String randomServer = serverList.get(rm.nextInt(serverList.size()));
Optional<RegisteredServer> optionalServer = proxy.getServer(randomServer);
optionalServer.ifPresentOrElse(serverToSend ->
proxy.getEventManager().fire(new PreSendOnLoginEvent(loggedPlayer, loginServer, serverToSend)).thenAcceptAsync(preSendEvent -> {
if(preSendEvent.getResult().isAllowed()){
loggedPlayer.createConnectionRequest(serverToSend).connect().thenAcceptAsync(result -> {
if(!result.isSuccessful()) {
logger.info("Unable to connect the player {} to the server {}",
loggedPlayer.getUsername(),
serverToSend.getServerInfo().getName());
}
});
}
})
, () -> logger.info("The server {} does not exist", randomServer));
}
}
@Subscribe @Subscribe
public void onDisconnect(final DisconnectEvent event) { public void onDisconnect(final DisconnectEvent event) {
AuthmeVelocityAPI.removePlayer(event.getPlayer()); AuthmeVelocityAPI.removePlayer(event.getPlayer());
@ -95,43 +31,39 @@ public class ProxyListener {
if (!(event.getCommandSource() instanceof Player player) || AuthmeVelocityAPI.isLogged(player)) if (!(event.getCommandSource() instanceof Player player) || AuthmeVelocityAPI.isLogged(player))
return; return;
Optional<ServerConnection> server = player.getCurrentServer(); if(AuthmeVelocityAPI.isInAuthServer(player)){
var commandconfig = config.getCommandsConfig();
if (server.isPresent() && config.getAuthServers().contains(server.get().getServerInfo().getName())) { String command = event.getCommand();
event.setResult(CommandExecuteEvent.CommandResult.forwardToServer()); if(command.contains(" ")){
command = command.split(" ")[0];
}
if(!commandconfig.getAllowedCommands().contains(command)){
ConfigUtils.sendBlockedMessage(player);
event.setResult(CommandExecuteEvent.CommandResult.denied());
}
} else { } else {
ConfigUtils.sendBlockedMessage(player);
event.setResult(CommandExecuteEvent.CommandResult.denied()); event.setResult(CommandExecuteEvent.CommandResult.denied());
} }
} }
@Subscribe @Subscribe
public void onPlayerChat(final PlayerChatEvent event, Continuation continuation) { public void onPlayerChat(final PlayerChatEvent event) {
final Player player = event.getPlayer(); if (!AuthmeVelocityAPI.isLogged(event.getPlayer())) {
if (AuthmeVelocityAPI.isLogged(player)) {
continuation.resume();
return;
}
Optional<ServerConnection> server = player.getCurrentServer();
if (server.isPresent() && config.getAuthServers().contains(server.get().getServerInfo().getName())) {
continuation.resume();
return;
}
event.setResult(PlayerChatEvent.ChatResult.denied()); event.setResult(PlayerChatEvent.ChatResult.denied());
} }
}
@Subscribe @Subscribe
public void onServerPreConnect(ServerPreConnectEvent event) { public void onServerPreConnect(ServerPreConnectEvent event) {
if (AuthmeVelocityAPI.isLogged(event.getPlayer())) return; if (AuthmeVelocityAPI.isLogged(event.getPlayer())) return;
Optional<RegisteredServer> server = event.getResult().getServer(); event.getResult().getServer().ifPresent(server -> {
if (server.isPresent() && config.getAuthServers().contains(server.get().getServerInfo().getName())) { if(!AuthmeVelocityAPI.isAuthServer(server)){
return;
}
event.setResult(ServerPreConnectEvent.ServerResult.denied()); event.setResult(ServerPreConnectEvent.ServerResult.denied());
} }
});
}
@Subscribe @Subscribe
public EventTask onTabComplete(TabCompleteEvent event){ public EventTask onTabComplete(TabCompleteEvent event){

View File

@ -8,18 +8,19 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class AuthMeVelocityPlugin extends JavaPlugin { public class AuthMeVelocityPlugin extends JavaPlugin {
private static final String CHANNEL = "authmevelocity:main";
@Override @Override
public void onEnable() { public void onEnable() {
this.getServer().getMessenger().registerOutgoingPluginChannel(this, "authmevelocity:main"); this.getServer().getMessenger().registerOutgoingPluginChannel(this, CHANNEL);
this.getServer().getPluginManager().registerEvents(new AuthMeListener(this), this); this.getServer().getPluginManager().registerEvents(new AuthMeListener(this), this);
this.getLogger().info("AuthMeVelocity enabled."); this.getLogger().info("AuthMeVelocity enabled.");
} }
public void sendLoginToProxy(@NotNull final Player player) { public void sendMessageToProxy(@NotNull final Player player, MessageType type) {
ByteArrayDataOutput out = ByteStreams.newDataOutput(); ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("LOGIN"); out.writeUTF(type.toString());
player.sendPluginMessage(this, "authmevelocity:main", out.toByteArray()); player.sendPluginMessage(this, CHANNEL, out.toByteArray());
} }
} }

View File

@ -0,0 +1,5 @@
package com.glyart.authmevelocity.spigot;
public enum MessageType {
LOGIN, REGISTER, LOGOUT
}

View File

@ -1,9 +1,12 @@
package com.glyart.authmevelocity.spigot.listeners; package com.glyart.authmevelocity.spigot.listeners;
import com.glyart.authmevelocity.spigot.AuthMeVelocityPlugin; import com.glyart.authmevelocity.spigot.AuthMeVelocityPlugin;
import com.glyart.authmevelocity.spigot.MessageType;
import com.glyart.authmevelocity.spigot.events.PreSendLoginEvent; import com.glyart.authmevelocity.spigot.events.PreSendLoginEvent;
import fr.xephi.authme.events.LoginEvent; import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.LogoutEvent;
import fr.xephi.authme.events.RegisterEvent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -23,7 +26,17 @@ public class AuthMeListener implements Listener {
PreSendLoginEvent preSendLoginEvent = new PreSendLoginEvent(player); PreSendLoginEvent preSendLoginEvent = new PreSendLoginEvent(player);
Bukkit.getPluginManager().callEvent(preSendLoginEvent); Bukkit.getPluginManager().callEvent(preSendLoginEvent);
if(!preSendLoginEvent.isCancelled()){ if(!preSendLoginEvent.isCancelled()){
plugin.sendLoginToProxy(player); plugin.sendMessageToProxy(player, MessageType.LOGIN);
} }
} }
@EventHandler
public void onRegister(RegisterEvent event){
plugin.sendMessageToProxy(event.getPlayer(), MessageType.REGISTER);
}
@EventHandler
public void onLogout(LogoutEvent event){
plugin.sendMessageToProxy(event.getPlayer(), MessageType.LOGOUT);
}
} }