Fix messaging [WIP] (#1614)

* Fix messaging [WIP]

* Make codeclimate happy

* Codeclimate, pls

* got it, i hope

* Improvements

* Remove duplicated checks, other improvements, make login/logout broadcasts

* Optimize project imports

* Make codeclimate happy again
This commit is contained in:
Gabriele C 2018-08-26 15:29:47 +02:00 committed by GitHub
parent adb3c06f51
commit da7e7edc37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 130 additions and 59 deletions

View File

@ -12,13 +12,11 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.service.GeoIpService; import fr.xephi.authme.service.GeoIpService;
import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.util.PlayerUtils; import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.inject.Inject; import javax.inject.Inject;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;

View File

@ -1,8 +1,8 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.task.purge.PurgeService;
import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.task.purge.PurgeService;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.service.AntiBotService;
import fr.xephi.authme.command.CommandMapper; import fr.xephi.authme.command.CommandMapper;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.FoundCommandResult;
import fr.xephi.authme.command.help.HelpProvider; import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.service.AntiBotService;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;

View File

@ -17,8 +17,8 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.formatLocation;
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.applyToLimboPlayersMap; import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.applyToLimboPlayersMap;
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.formatLocation;
/** /**
* Shows the data stored in LimboPlayers and the equivalent properties on online players. * Shows the data stored in LimboPlayers and the equivalent properties on online players.

View File

@ -71,6 +71,11 @@ public class CacheDataSource implements DataSource {
source.reload(); source.reload();
} }
@Override
public boolean isCached() {
return true;
}
@Override @Override
public boolean isAuthAvailable(String user) { public boolean isAuthAvailable(String user) {
return getAuth(user) != null; return getAuth(user) != null;

View File

@ -14,6 +14,15 @@ import java.util.Set;
*/ */
public interface DataSource extends Reloadable { public interface DataSource extends Reloadable {
/**
* Return whether the data source is cached and needs to send plugin messaging updates.
*
* @return true if the data source is cached.
*/
default boolean isCached() {
return false;
}
/** /**
* Return whether there is a record for the given username. * Return whether there is a record for the given username.
* *

View File

@ -1,7 +1,6 @@
package fr.xephi.authme.listener; package fr.xephi.authme.listener;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile; import org.bukkit.entity.Projectile;

View File

@ -1,15 +1,16 @@
package fr.xephi.authme.listener; package fr.xephi.authme.listener;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.service.PluginHookService;
import fr.xephi.authme.listener.protocollib.ProtocolLibService; import fr.xephi.authme.listener.protocollib.ProtocolLibService;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.service.PluginHookService;
import fr.xephi.authme.settings.SpawnLoader; import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent; import org.bukkit.event.server.PluginEnableEvent;
import javax.inject.Inject; import javax.inject.Inject;
/** /**

View File

@ -14,13 +14,13 @@
*/ */
package fr.xephi.authme.mail; package fr.xephi.authme.mail;
import java.io.IOException;
import javax.security.auth.callback.Callback; import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.SaslClient; import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException; import javax.security.sasl.SaslException;
import java.io.IOException;
/** /**
* An OAuth2 implementation of SaslClient. * An OAuth2 implementation of SaslClient.
@ -95,4 +95,4 @@ class OAuth2SaslClient implements SaslClient {
public void dispose() throws SaslException { public void dispose() throws SaslException {
} }
} }

View File

@ -15,12 +15,11 @@
*/ */
package fr.xephi.authme.mail; package fr.xephi.authme.mail;
import java.util.Map;
import java.util.logging.Logger;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslClient; import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslClientFactory; import javax.security.sasl.SaslClientFactory;
import java.util.Map;
import java.util.logging.Logger;
/** /**
* A SaslClientFactory that returns instances of OAuth2SaslClient. * A SaslClientFactory that returns instances of OAuth2SaslClient.

View File

@ -35,16 +35,17 @@ public class AsyncChangeEmail implements AsynchronousProcess {
@Inject @Inject
private BungeeSender bungeeSender; private BungeeSender bungeeSender;
@Inject @Inject
private BukkitService bukkitService; private BukkitService bukkitService;
AsyncChangeEmail() { } AsyncChangeEmail() {
}
/** /**
* Handles the request to change the player's email address. * Handles the request to change the player's email address.
* *
* @param player the player to change the email for * @param player the player to change the email for
* @param oldEmail provided old email * @param oldEmail provided old email
* @param newEmail provided new email * @param newEmail provided new email
*/ */
@ -70,6 +71,14 @@ public class AsyncChangeEmail implements AsynchronousProcess {
} }
} }
/**
* Saves the new email value into the database and informs services.
*
* @param auth the player auth object
* @param player the player object
* @param oldEmail the old email value
* @param newEmail the new email value
*/
private void saveNewEmail(PlayerAuth auth, Player player, String oldEmail, String newEmail) { private void saveNewEmail(PlayerAuth auth, Player player, String oldEmail, String newEmail) {
EmailChangedEvent event = bukkitService.createAndCallEvent(isAsync EmailChangedEvent event = bukkitService.createAndCallEvent(isAsync
-> new EmailChangedEvent(player, oldEmail, newEmail, isAsync)); -> new EmailChangedEvent(player, oldEmail, newEmail, isAsync));

View File

@ -66,7 +66,7 @@ public class AsyncRegister implements AsynchronousProcess {
* Checks if the player is able to register, in that case the {@link AuthMeAsyncPreRegisterEvent} is invoked. * Checks if the player is able to register, in that case the {@link AuthMeAsyncPreRegisterEvent} is invoked.
* *
* @param variant the registration type variant. * @param variant the registration type variant.
* @param player the player which is trying to register. * @param player the player which is trying to register.
* *
* @return true if the checks are successful and the event hasn't marked the action as denied, false otherwise. * @return true if the checks are successful and the event hasn't marked the action as denied, false otherwise.
*/ */

View File

@ -15,7 +15,6 @@ package fr.xephi.authme.security.crypts;
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.security.SecureRandom; import java.security.SecureRandom;
/** /**

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.HasSalt; import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType; import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.util.RandomStringUtils;
/** /**
* Common type for encryption methods which use a random String of hexadecimal characters * Common type for encryption methods which use a random String of hexadecimal characters

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.HasSalt; import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType; import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.util.RandomStringUtils;
import static fr.xephi.authme.security.HashUtils.md5; import static fr.xephi.authme.security.HashUtils.md5;

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.HasSalt; import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType; import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.util.RandomStringUtils;
import static fr.xephi.authme.security.HashUtils.md5; import static fr.xephi.authme.security.HashUtils.md5;

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.security.HashUtils; import fr.xephi.authme.security.HashUtils;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.AsciiRestricted; import fr.xephi.authme.security.crypts.description.AsciiRestricted;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.util.RandomStringUtils;
import javax.crypto.Mac; import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;

View File

@ -1,12 +1,12 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.HasSalt; import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType; import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.RandomStringUtils;
import javax.inject.Inject; import javax.inject.Inject;

View File

@ -1,9 +1,9 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.security.HashUtils; import fr.xephi.authme.security.HashUtils;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.util.RandomStringUtils;
@Recommendation(Usage.RECOMMENDED) @Recommendation(Usage.RECOMMENDED)
public class SaltedSha512 extends SeparateSaltMethod { public class SaltedSha512 extends SeparateSaltMethod {

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.security.crypts; package fr.xephi.authme.security.crypts;
import fr.xephi.authme.util.RandomStringUtils;
import fr.xephi.authme.security.crypts.description.HasSalt; import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType; import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.util.RandomStringUtils;
import static fr.xephi.authme.security.HashUtils.sha1; import static fr.xephi.authme.security.HashUtils.sha1;

View File

@ -13,12 +13,12 @@ import com.maxmind.db.Reader.FileMode;
import com.maxmind.db.cache.CHMCache; import com.maxmind.db.cache.CHMCache;
import com.maxmind.db.model.Country; import com.maxmind.db.model.Country;
import com.maxmind.db.model.CountryResponse; import com.maxmind.db.model.CountryResponse;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.util.FileUtils; import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.InternetProtocolUtils; import fr.xephi.authme.util.InternetProtocolUtils;
import javax.inject.Inject;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -41,8 +41,6 @@ import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import javax.inject.Inject;
public class GeoIpService { public class GeoIpService {
private static final String LICENSE = private static final String LICENSE =

View File

@ -15,6 +15,7 @@ import org.bukkit.plugin.messaging.Messenger;
import org.bukkit.plugin.messaging.PluginMessageListener; import org.bukkit.plugin.messaging.PluginMessageListener;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.Optional;
public class BungeeReceiver implements PluginMessageListener, SettingsDependent { public class BungeeReceiver implements PluginMessageListener, SettingsDependent {
@ -59,32 +60,36 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
return; return;
} }
String type = in.readUTF(); Optional<MessageType> type = MessageType.fromId(in.readUTF());
String name = in.readUTF(); if(!type.isPresent()) {
switch (type) { ConsoleLogger.debug("Received unsupported bungeecord message type! ({0})", type);
case MessageType.UNREGISTER: return;
dataSource.invalidateCache(name); }
String argument = in.readUTF();
switch (type.get()) {
case UNREGISTER:
dataSource.invalidateCache(argument);
break; break;
case MessageType.REFRESH_PASSWORD: case REFRESH_PASSWORD:
case MessageType.REFRESH_QUITLOC: case REFRESH_QUITLOC:
case MessageType.REFRESH_EMAIL: case REFRESH_EMAIL:
case MessageType.REFRESH: case REFRESH:
dataSource.refreshCache(name); dataSource.refreshCache(argument);
break; break;
case MessageType.BUNGEE_LOGIN: case PERFORM_LOGIN:
handleBungeeLogin(name); performLogin(argument);
break; break;
default: default:
ConsoleLogger.debug("Received unsupported bungeecord message type! ({0})", type);
} }
} }
private void handleBungeeLogin(String name) { private void performLogin(String name) {
Player player = bukkitService.getPlayerExact(name); Player player = bukkitService.getPlayerExact(name);
if (player != null && player.isOnline()) { if (player != null && player.isOnline()) {
management.forceLogin(player); management.forceLogin(player);
ConsoleLogger.info("The user " + player.getName() + " has been automatically logged in, " ConsoleLogger.info("The user " + player.getName() + " has been automatically logged in, "
+ "as requested by the AuthMeBungee integration."); + "as requested via plugin messaging.");
} }
} }

View File

@ -4,6 +4,7 @@ import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.SettingsDependent; import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
@ -17,6 +18,7 @@ public class BungeeSender implements SettingsDependent {
private final AuthMe plugin; private final AuthMe plugin;
private final BukkitService bukkitService; private final BukkitService bukkitService;
private final DataSource dataSource;
private boolean isEnabled; private boolean isEnabled;
private String destinationServerOnLogin; private String destinationServerOnLogin;
@ -25,9 +27,10 @@ public class BungeeSender implements SettingsDependent {
* Constructor. * Constructor.
*/ */
@Inject @Inject
BungeeSender(AuthMe plugin, BukkitService bukkitService, Settings settings) { BungeeSender(AuthMe plugin, BukkitService bukkitService, DataSource dataSource, Settings settings) {
this.plugin = plugin; this.plugin = plugin;
this.bukkitService = bukkitService; this.bukkitService = bukkitService;
this.dataSource = dataSource;
reload(settings); reload(settings);
} }
@ -75,13 +78,20 @@ public class BungeeSender implements SettingsDependent {
* @param type The message type, See {@link MessageType} * @param type The message type, See {@link MessageType}
* @param playerName the player related to the message * @param playerName the player related to the message
*/ */
public void sendAuthMeBungeecordMessage(String type, String playerName) { public void sendAuthMeBungeecordMessage(MessageType type, String playerName) {
if (isEnabled) { if (isEnabled) {
if(!plugin.isEnabled()) { if (!plugin.isEnabled()) {
ConsoleLogger.debug("Tried to send a " + type + " bungeecord message but the plugin was disabled!"); ConsoleLogger.debug("Tried to send a " + type + " bungeecord message but the plugin was disabled!");
return; return;
} }
sendBungeecordMessage("AuthMe", type, playerName.toLowerCase()); if(type.isRequiresCaching() && !dataSource.isCached()) {
return;
}
if (type.isBroadcast()) {
sendBungeecordMessage("Forward", "ALL", "AuthMe", type.getId(), playerName.toLowerCase());
} else {
sendBungeecordMessage("AuthMe", type.getId(), playerName.toLowerCase());
}
} }
} }

View File

@ -1,19 +1,59 @@
package fr.xephi.authme.service.bungeecord; package fr.xephi.authme.service.bungeecord;
public final class MessageType { import java.util.Optional;
public static final String LOGIN = "login"; public enum MessageType {
public static final String LOGOUT = "logout"; REFRESH_PASSWORD("refresh.password", true),
public static final String REGISTER = "register"; REFRESH_SESSION("refresh.session", true),
public static final String UNREGISTER = "unregister"; REFRESH_QUITLOC("refresh.quitloc", true),
public static final String REFRESH_PASSWORD = "refresh.password"; REFRESH_EMAIL("refresh.email", true),
public static final String REFRESH_SESSION = "refresh.session"; REFRESH("refresh", true),
public static final String REFRESH_QUITLOC = "refresh.quitloc"; REGISTER("register", true),
public static final String REFRESH_EMAIL = "refresh.email"; UNREGISTER("unregister", true),
public static final String REFRESH = "refresh"; LOGIN("login", true),
public static final String BUNGEE_LOGIN = "bungeelogin"; LOGOUT("logout", true),
PERFORM_LOGIN("perform.login", false);
private MessageType() { private final String id;
private final boolean broadcast;
private final boolean requiresCaching;
MessageType(String id, boolean broadcast, boolean requiresCaching) {
this.id = id;
this.broadcast = broadcast;
this.requiresCaching = requiresCaching;
}
MessageType(String id, boolean broadcast) {
this(id, broadcast, false);
}
public String getId() {
return id;
}
public boolean isBroadcast() {
return broadcast;
}
public boolean isRequiresCaching() {
return requiresCaching;
}
/**
* Returns the MessageType with the given ID.
*
* @param id the message type id.
*
* @return the MessageType with the given id, empty if invalid.
*/
public static Optional<MessageType> fromId(String id) {
for (MessageType current : values()) {
if (current.getId().equals(id)) {
return Optional.of(current);
}
}
return Optional.empty();
} }
} }

View File

@ -3,7 +3,6 @@ package fr.xephi.authme.task.purge;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.permission.handlers.PermissionLoadUserException;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;