Merge branch 'master' of https://github.com/AuthMe-Team/AuthMeReloaded into command-perms-refactor

Conflicts:
	src/main/java/fr/xephi/authme/output/Log4JFilter.java
This commit is contained in:
ljacqu 2015-12-02 21:56:53 +01:00
commit f698c9241b
11 changed files with 850 additions and 800 deletions

View File

@ -86,8 +86,7 @@ public class SendMailSSL {
try { try {
email.send(); email.send();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); ConsoleLogger.showError("Fail to send a mail to " + mail + " cause " + e.getLocalizedMessage());
ConsoleLogger.showError("Fail to send a mail to " + mail);
} }
if (file != null) if (file != null)
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored

View File

@ -23,9 +23,8 @@ public class PlayerAuth {
/** /**
* *
*/ */
public PlayerAuth(String serialized) public PlayerAuth(String serialized) {
{ this.deserialize(serialized);
this.unserialize(serialized);
} }
/** /**
@ -163,8 +162,10 @@ public class PlayerAuth {
* @param email String * @param email String
* @param realName String * @param realName String
*/ */
public PlayerAuth(String nickname, String hash, String salt, int groupId, String ip, long lastLogin, double x, double y, double z, String world, String email, String realName) { public PlayerAuth(String nickname, String hash, String salt, int groupId, String ip,
this.nickname = nickname; long lastLogin, double x, double y, double z, String world, String email,
String realName) {
this.nickname = nickname.toLowerCase();
this.hash = hash; this.hash = hash;
this.ip = ip; this.ip = ip;
this.lastLogin = lastLogin; this.lastLogin = lastLogin;
@ -203,7 +204,7 @@ public class PlayerAuth {
* @param nickname String * @param nickname String
*/ */
public void setName(String nickname) { public void setName(String nickname) {
this.nickname = nickname; this.nickname = nickname.toLowerCase();
} }
/** /**
@ -455,34 +456,32 @@ public class PlayerAuth {
} }
/** /**
* Method to serialize playerauth * Method to serialize PlayerAuth
* *
* @return String * @return String
*/ */
public String serialize() public String serialize() {
{
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
str.append(this.nickname).append(';'); char d = ';';
str.append(this.realName).append(';'); str.append(this.nickname).append(d);
str.append(this.ip).append(';'); str.append(this.realName).append(d);
str.append(this.email).append(';'); str.append(this.ip).append(d);
str.append(this.hash).append(';'); str.append(this.email).append(d);
str.append(this.salt).append(';'); str.append(this.hash).append(d);
str.append(this.groupId).append(';'); str.append(this.salt).append(d);
str.append(this.lastLogin).append(';'); str.append(this.groupId).append(d);
str.append(this.world).append(';'); str.append(this.lastLogin).append(d);
str.append(this.x).append(';'); str.append(this.world).append(d);
str.append(this.y).append(';'); str.append(this.x).append(d);
str.append(this.y).append(d);
str.append(this.z); str.append(this.z);
return str.toString(); return str.toString();
} }
/** /**
* Method to unserialize playerauth * Method to deserialize PlayerAuth
*
*/ */
public void unserialize(String str) public void deserialize(String str) {
{
String[] args = str.split(";"); String[] args = str.split(";");
this.nickname = args[0]; this.nickname = args[0];
this.realName = args[1]; this.realName = args[1];
@ -497,4 +496,97 @@ public class PlayerAuth {
this.y = Double.parseDouble(args[10]); this.y = Double.parseDouble(args[10]);
this.z = Double.parseDouble(args[11]); this.z = Double.parseDouble(args[11]);
} }
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private String name;
private String realName = "Player";
private String hash = "";
private String salt = "";
private String ip = "127.0.0.1";
private String world = "world";
private double x = 0.0f;
private double y = 0.0f;
private double z = 0.0f;
private long lastLogin = System.currentTimeMillis();
private int groupId = -1;
private String email = "your@email.com";
public PlayerAuth build() {
return new PlayerAuth(
name,
hash,
salt,
groupId,
ip,
lastLogin,
x, y, z, world,
email,
realName
);
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder realName(String realName) {
this.realName = realName;
return this;
}
public Builder hash(String hash) {
this.hash = hash;
return this;
}
public Builder salt(String salt) {
this.salt = salt;
return this;
}
public Builder ip(String ip) {
this.ip = ip;
return this;
}
public Builder locWorld(String world) {
this.world = world;
return this;
}
public Builder locX(double x) {
this.x = x;
return this;
}
public Builder locY(double y) {
this.y = y;
return this;
}
public Builder locZ(double z) {
this.z = z;
return this;
}
public Builder lastLogin(long lastLogin) {
this.lastLogin = lastLogin;
return this;
}
public Builder groupId(int groupId) {
this.groupId = groupId;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ import java.util.logging.Filter;
import java.util.logging.LogRecord; import java.util.logging.LogRecord;
/** /**
* Console filter Class * Console filter to replace sensitive AuthMe commands with a generic message.
* *
* @author Xephi59 * @author Xephi59
*/ */
@ -12,20 +12,15 @@ public class ConsoleFilter implements Filter {
@Override @Override
public boolean isLoggable(LogRecord record) { public boolean isLoggable(LogRecord record) {
try { if (record == null || record.getMessage() == null) {
if (record == null || record.getMessage() == null)
return true;
String logM = record.getMessage().toLowerCase();
if (!logM.contains("issued server command:"))
return true;
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
return true;
String playerName = record.getMessage().split(" ")[0];
record.setMessage(playerName + " issued an AuthMe command!");
return true;
} catch (NullPointerException npe) {
return true; return true;
} }
if (LogFilterHelper.isSensitiveAuthMeCommand(record.getMessage())) {
String playerName = record.getMessage().split(" ")[0];
record.setMessage(playerName + " issued an AuthMe command");
}
return true;
} }
} }

View File

@ -1,6 +1,5 @@
package fr.xephi.authme.output; package fr.xephi.authme.output;
import fr.xephi.authme.util.StringUtils;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.Filter;
@ -15,13 +14,6 @@ import org.apache.logging.log4j.message.Message;
*/ */
public class Log4JFilter implements Filter { public class Log4JFilter implements Filter {
/**
* List of commands (lower-case) to skip.
*/
private static final String[] COMMANDS_TO_SKIP = {"/login ", "/l ", "/reg ", "/changepassword ",
"/unregister ", "/authme register ", "/authme changepassword ", "/authme reg ", "/authme cp ",
"/register "};
/** /**
* Constructor. * Constructor.
*/ */
@ -32,9 +24,9 @@ public class Log4JFilter implements Filter {
* Validates a Message instance and returns the {@link Result} value * Validates a Message instance and returns the {@link Result} value
* depending on whether the message contains sensitive AuthMe data. * depending on whether the message contains sensitive AuthMe data.
* *
* @param message the Message object to verify * @param message The Message object to verify
* *
* @return the Result value * @return The Result value
*/ */
private static Result validateMessage(Message message) { private static Result validateMessage(Message message) {
if (message == null) { if (message == null) {
@ -47,21 +39,14 @@ public class Log4JFilter implements Filter {
* Validates a message and returns the {@link Result} value depending * Validates a message and returns the {@link Result} value depending
* on whether the message contains sensitive AuthMe data. * on whether the message contains sensitive AuthMe data.
* *
* @param message the message to verify * @param message The message to verify
* *
* @return the Result value * @return The Result value
*/ */
private static Result validateMessage(String message) { private static Result validateMessage(String message) {
if (message == null) { return LogFilterHelper.isSensitiveAuthMeCommand(message)
return Result.NEUTRAL; ? Result.DENY
} : Result.NEUTRAL;
String lowerMessage = message.toLowerCase();
if (lowerMessage.contains("issued server command:")
&& StringUtils.containsAny(lowerMessage, COMMANDS_TO_SKIP)) {
return Result.DENY;
}
return Result.NEUTRAL;
} }
@Override @Override

View File

@ -0,0 +1,34 @@
package fr.xephi.authme.output;
import fr.xephi.authme.util.StringUtils;
/**
* Service class for the log filters.
*/
public final class LogFilterHelper {
private static final String ISSUED_COMMAND_TEXT = "issued server command:";
private static final String[] COMMANDS_TO_SKIP = {"/login ", "/l ", "/reg ", "/changepassword ",
"/unregister ", "/authme register ", "/authme changepassword ", "/authme reg ", "/authme cp ",
"/register "};
private LogFilterHelper() {
// Util class
}
/**
* Validate a message and return whether the message contains a sensitive AuthMe command.
*
* @param message The message to verify
*
* @return True if it is a sensitive AuthMe command, false otherwise
*/
public static boolean isSensitiveAuthMeCommand(String message) {
if (message == null) {
return false;
}
String lowerMessage = message.toLowerCase();
return lowerMessage.contains(ISSUED_COMMAND_TEXT) && StringUtils.containsAny(lowerMessage, COMMANDS_TO_SKIP);
}
}

View File

@ -17,7 +17,7 @@ import java.util.regex.Pattern;
/** /**
*/ */
public final class Settings extends YamlConfiguration { public final class Settings {
public static final File PLUGIN_FOLDER = Wrapper.getInstance().getDataFolder(); public static final File PLUGIN_FOLDER = Wrapper.getInstance().getDataFolder();
public static final File MODULE_FOLDER = new File(PLUGIN_FOLDER, "modules"); public static final File MODULE_FOLDER = new File(PLUGIN_FOLDER, "modules");
@ -68,7 +68,7 @@ public final class Settings extends YamlConfiguration {
enableProtection, enableAntiBot, recallEmail, useWelcomeMessage, enableProtection, enableAntiBot, recallEmail, useWelcomeMessage,
broadcastWelcomeMessage, forceRegKick, forceRegLogin, broadcastWelcomeMessage, forceRegKick, forceRegLogin,
checkVeryGames, delayJoinLeaveMessages, noTeleport, applyBlindEffect, checkVeryGames, delayJoinLeaveMessages, noTeleport, applyBlindEffect,
customAttributes, generateImage, isRemoveSpeedEnabled, isMySQLWebsite; customAttributes, generateImage, isRemoveSpeedEnabled;
public static String helpHeader, getNickRegex, getUnloggedinGroup, getMySQLHost, public static String helpHeader, getNickRegex, getUnloggedinGroup, getMySQLHost,
getMySQLPort, getMySQLUsername, getMySQLPassword, getMySQLDatabase, getMySQLPort, getMySQLUsername, getMySQLPassword, getMySQLDatabase,
getMySQLTablename, getMySQLColumnName, getMySQLColumnPassword, getMySQLTablename, getMySQLColumnName, getMySQLColumnPassword,
@ -105,18 +105,13 @@ public final class Settings extends YamlConfiguration {
configFile = (YamlConfiguration) plugin.getConfig(); configFile = (YamlConfiguration) plugin.getConfig();
} }
/**
* Method reload.
*
* @throws Exception
*/
public static void reload() throws Exception { public static void reload() throws Exception {
plugin.getLogger().info("Loading Configuration File..."); plugin.getLogger().info("Loading Configuration File...");
boolean exist = SETTINGS_FILE.exists(); boolean exist = SETTINGS_FILE.exists();
if (!exist) { if (!exist) {
plugin.saveDefaultConfig(); plugin.saveDefaultConfig();
} }
instance.load(SETTINGS_FILE); configFile.load(SETTINGS_FILE);
if (exist) { if (exist) {
instance.mergeConfig(); instance.mergeConfig();
} }
@ -284,29 +279,17 @@ public final class Settings extends YamlConfiguration {
forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole"); forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole");
customAttributes = configFile.getBoolean("Hooks.customAttributes"); customAttributes = configFile.getBoolean("Hooks.customAttributes");
generateImage = configFile.getBoolean("Email.generateImage", false); generateImage = configFile.getBoolean("Email.generateImage", false);
isMySQLWebsite = configFile.getBoolean("DataSource.mySQLWebsite", false);
// Load the welcome message // Load the welcome message
getWelcomeMessage(); getWelcomeMessage();
} }
/**
* Method setValue.
*
* @param key String
* @param value Object
*/
public static void setValue(String key, Object value) { public static void setValue(String key, Object value) {
instance.set(key, value); instance.set(key, value);
save(); save();
} }
/**
* Method getPasswordHash.
*
* @return HashAlgorithm
*/
private static HashAlgorithm getPasswordHash() { private static HashAlgorithm getPasswordHash() {
String key = "settings.security.passwordHash"; String key = "settings.security.passwordHash";
try { try {
@ -317,11 +300,6 @@ public final class Settings extends YamlConfiguration {
} }
} }
/**
* Method getDataSource.
*
* @return DataSourceType
*/
private static DataSourceType getDataSource() { private static DataSourceType getDataSource() {
String key = "DataSource.backend"; String key = "DataSource.backend";
try { try {
@ -368,20 +346,13 @@ public final class Settings extends YamlConfiguration {
*/ */
public static boolean save() { public static boolean save() {
try { try {
instance.save(SETTINGS_FILE); configFile.save(SETTINGS_FILE);
return true; return true;
} catch (Exception ex) { } catch (IOException ex) {
return false; return false;
} }
} }
/**
* Method checkLang.
*
* @param lang String
*
* @return String
*/
public static String checkLang(String lang) { public static String checkLang(String lang) {
if (new File(PLUGIN_FOLDER, "messages" + File.separator + "messages_" + lang + ".yml").exists()) { if (new File(PLUGIN_FOLDER, "messages" + File.separator + "messages_" + lang + ".yml").exists()) {
ConsoleLogger.info("Set Language to: " + lang); ConsoleLogger.info("Set Language to: " + lang);
@ -395,11 +366,6 @@ public final class Settings extends YamlConfiguration {
return "en"; return "en";
} }
/**
* Method switchAntiBotMod.
*
* @param mode boolean
*/
public static void switchAntiBotMod(boolean mode) { public static void switchAntiBotMod(boolean mode) {
if (mode) { if (mode) {
isKickNonRegisteredEnabled = true; isKickNonRegisteredEnabled = true;
@ -441,13 +407,6 @@ public final class Settings extends YamlConfiguration {
} }
} }
/**
* Method isEmailCorrect.
*
* @param email String
*
* @return boolean
*/
public static boolean isEmailCorrect(String email) { public static boolean isEmailCorrect(String email) {
if (!email.contains("@")) if (!email.contains("@"))
return false; return false;
@ -588,7 +547,7 @@ public final class Settings extends YamlConfiguration {
set("VeryGames.enableIpCheck", false); set("VeryGames.enableIpCheck", false);
changes = true; changes = true;
} }
if (getString("settings.restrictions.allowedNicknameCharacters").equals("[a-zA-Z0-9_?]*")) { if (configFile.getString("settings.restrictions.allowedNicknameCharacters").equals("[a-zA-Z0-9_?]*")) {
set("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_]*"); set("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_]*");
changes = true; changes = true;
} }
@ -676,10 +635,6 @@ public final class Settings extends YamlConfiguration {
set("DataSource.mySQLRealName", "realname"); set("DataSource.mySQLRealName", "realname");
changes = true; changes = true;
} }
if (!contains("DataSource.mySQLQueryCache")) {
set("DataSource.mySQLWebsite", false);
changes = true;
}
if (changes) { if (changes) {
plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me"); plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me");
@ -687,6 +642,15 @@ public final class Settings extends YamlConfiguration {
} }
} }
private static boolean contains(String path) {
return configFile.contains(path);
}
// public because it's used in AuthMe at one place
public void set(String path, Object value) {
configFile.set(path, value);
}
/** /**
* Saves current configuration (plus defaults) to disk. * Saves current configuration (plus defaults) to disk.
* <p/> * <p/>
@ -695,11 +659,13 @@ public final class Settings extends YamlConfiguration {
* @return True if saved successfully * @return True if saved successfully
*/ */
public final boolean saveDefaults() { public final boolean saveDefaults() {
options().copyDefaults(true); configFile.options()
options().copyHeader(true); .copyDefaults(true)
.copyHeader(true);
boolean success = save(); boolean success = save();
options().copyDefaults(false); configFile.options()
options().copyHeader(false); .copyDefaults(false)
.copyHeader(false);
return success; return success;
} }
} }

View File

@ -388,12 +388,13 @@ Protection:
# Enable some servers protection ( country based login, antibot ) # Enable some servers protection ( country based login, antibot )
enableProtection: false enableProtection: false
# Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes # Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes
# PLEASE USE QUOTES!
countries: countries:
- US - 'US'
- GB - 'GB'
# Countries blacklisted automatically ( without any needed to enable protection ) # Countries blacklisted automatically ( without any needed to enable protection )
countriesBlacklist: countriesBlacklist:
- A1 - 'A1'
# Do we need to enable automatic antibot system? # Do we need to enable automatic antibot system?
enableAntiBot: false enableAntiBot: false
# Max number of player allowed to login in 5 secs before enable AntiBot system automatically # Max number of player allowed to login in 5 secs before enable AntiBot system automatically

View File

@ -0,0 +1,77 @@
package fr.xephi.authme.output;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.logging.LogRecord;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Test for {@link ConsoleFilter}.
*/
public class ConsoleFilterTest {
private final ConsoleFilter filter = new ConsoleFilter();
private static final String SENSITIVE_COMMAND = "User issued server command: /login test test";
private static final String NORMAL_COMMAND = "User issued server command: /motd 2";
@Test
public void shouldReplaceSensitiveRecord() {
// given
LogRecord record = createRecord(SENSITIVE_COMMAND);
// when
boolean result = filter.isLoggable(record);
// then
assertThat(result, equalTo(true));
verify(record).setMessage("User issued an AuthMe command");
}
@Test
public void shouldNotFilterRegularCommand() {
// given
LogRecord record = createRecord(NORMAL_COMMAND);
// when
boolean result = filter.isLoggable(record);
// then
assertThat(result, equalTo(true));
verify(record, never()).setMessage("User issued an AuthMe command");
}
@Test
public void shouldManageRecordWithNullMessage() {
// given
LogRecord record = createRecord(null);
// when
boolean result = filter.isLoggable(record);
// then
assertThat(result, equalTo(true));
verify(record, never()).setMessage("User issued an AuthMe command");
}
/**
* Creates a mock of {@link LogRecord} and sets it to return the given message.
*
* @param message The message to set.
*
* @return Mock of LogRecord
*/
private static LogRecord createRecord(String message) {
LogRecord record = Mockito.mock(LogRecord.class);
when(record.getMessage()).thenReturn(message);
return record;
}
}

View File

@ -20,7 +20,8 @@ public class AdminPermissionTest {
// when/then // when/then
for (AdminPermission permission : AdminPermission.values()) { for (AdminPermission permission : AdminPermission.values()) {
if (!permission.getNode().startsWith(requiredPrefix)) { if (!permission.getNode().startsWith(requiredPrefix)) {
fail("The permission '" + permission + "' does not start with the required prefix '" + requiredPrefix + "'"); fail("The permission '" + permission + "' does not start with the required prefix '"
+ requiredPrefix + "'");
} }
} }
} }
@ -33,7 +34,8 @@ public class AdminPermissionTest {
// when/then // when/then
for (AdminPermission permission : AdminPermission.values()) { for (AdminPermission permission : AdminPermission.values()) {
if (!permission.getNode().contains(requiredBranch)) { if (!permission.getNode().contains(requiredBranch)) {
fail("The permission '" + permission + "' does not contain with the required branch '" + requiredBranch + "'"); fail("The permission '" + permission + "' does not contain with the required branch '"
+ requiredBranch + "'");
} }
} }
} }

View File

@ -3,18 +3,16 @@ AuthMe-Team:
Active staff: Active staff:
Xephi (Xephi59) - Leader, Main developer Xephi (Xephi59) - Leader, Main developer
DNx5 - Developer DNx5 - Developer
games647 - Developer ljacqu - Developer
TimVisee - Developer TimVisee - Developer
games647 - Developer
Gabriele C. (sgdc3) - Project Manager, Contributor Gabriele C. (sgdc3) - Project Manager, Contributor
Staff to contact: AuthMeBridge staff:
CryLegend - Contributor, AuthMeBridge Developer (Needs activation) CryLegend - Main developer, We need to contact him!
External Contributors: Retired staff:
Gnat008 - Contributor Maxetto - Ticket Manager, IT translator
Inactive staff:
Maxetto - Ticket Manager, Italian Translator, Basic Developer, Contributor (Inactive)
darkwarriors (d4rkwarriors) - Original AuthMeReloaded Author (Inactive) darkwarriors (d4rkwarriors) - Original AuthMeReloaded Author (Inactive)
Translators: Translators: