diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 862c6dd7..01cccab1 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -261,7 +261,7 @@ public class AuthMe extends JavaPlugin { // Set up the permissions manager and command handler permsMan = initializePermissionsManager(); - ValidationService validationService = new ValidationService(newSettings); + ValidationService validationService = new ValidationService(newSettings, database, permsMan); commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings, ipAddressManager, pluginHooks, spawnLoader, antiBot, validationService); diff --git a/src/main/java/fr/xephi/authme/command/CommandService.java b/src/main/java/fr/xephi/authme/command/CommandService.java index d6861059..2fee46ad 100644 --- a/src/main/java/fr/xephi/authme/command/CommandService.java +++ b/src/main/java/fr/xephi/authme/command/CommandService.java @@ -222,4 +222,12 @@ public class CommandService { return validationService.validatePassword(password, username); } + public boolean validateEmail(String email) { + return validationService.validateEmail(email); + } + + public boolean isEmailFreeForRegistration(String email, CommandSender sender) { + return validationService.isEmailFreeForRegistration(email, sender); + } + } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java index 9e44fdab..0e7bcf35 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java @@ -6,12 +6,13 @@ import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; -import fr.xephi.authme.settings.properties.EmailSettings; -import fr.xephi.authme.util.Utils; import org.bukkit.command.CommandSender; import java.util.List; +/** + * Admin command for setting an email to an account. + */ public class SetEmailCommand implements ExecutableCommand { @Override @@ -22,7 +23,7 @@ public class SetEmailCommand implements ExecutableCommand { final String playerEmail = arguments.get(1); // Validate the email address - if (!Utils.isEmailCorrect(playerEmail, commandService.getSettings())) { + if (!commandService.validateEmail(playerEmail)) { commandService.send(sender, MessageKey.INVALID_EMAIL); return; } @@ -36,8 +37,7 @@ public class SetEmailCommand implements ExecutableCommand { if (auth == null) { commandService.send(sender, MessageKey.UNKNOWN_USER); return; - } else if (dataSource.countAuthsByEmail(playerEmail) - >= commandService.getProperty(EmailSettings.MAX_REG_PER_EMAIL)) { + } else if (!commandService.isEmailFreeForRegistration(playerEmail, sender)) { commandService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR); return; } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java index f2b66301..cd92ebf4 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java @@ -3,11 +3,13 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.PlayerCommand; import fr.xephi.authme.output.MessageKey; -import fr.xephi.authme.util.Utils; import org.bukkit.entity.Player; import java.util.List; +/** + * Command for setting an email to an account. + */ public class AddEmailCommand extends PlayerCommand { @Override @@ -15,9 +17,8 @@ public class AddEmailCommand extends PlayerCommand { String email = arguments.get(0); String emailConfirmation = arguments.get(1); - if (!Utils.isEmailCorrect(email, commandService.getSettings())) { - commandService.send(player, MessageKey.INVALID_EMAIL); - } else if (email.equals(emailConfirmation)) { + if (email.equals(emailConfirmation)) { + // Closer inspection of the mail address handled by the async task commandService.getManagement().performAddEmail(player, email); } else { commandService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE); diff --git a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java index 48a1c3f0..e488eac7 100644 --- a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java @@ -7,13 +7,16 @@ import fr.xephi.authme.process.Management; import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.EmailSettings; +import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.SecuritySettings; -import fr.xephi.authme.util.Utils; - import org.bukkit.entity.Player; import java.util.List; +import static fr.xephi.authme.settings.properties.EmailSettings.RECOVERY_PASSWORD_LENGTH; +import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION; + public class RegisterCommand extends PlayerCommand { @Override @@ -24,25 +27,27 @@ public class RegisterCommand extends PlayerCommand { return; } - if (arguments.isEmpty() || Settings.enablePasswordConfirmation && arguments.size() < 2) { + if (arguments.isEmpty() || commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && arguments.size() < 2) { commandService.send(player, MessageKey.USAGE_REGISTER); return; } final Management management = commandService.getManagement(); - if (Settings.emailRegistration && !Settings.getmailAccount.isEmpty()) { - if (Settings.doubleEmailCheck && arguments.size() < 2 || !arguments.get(0).equals(arguments.get(1))) { + if (commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION) + && !commandService.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) { + boolean emailDoubleCheck = commandService.getProperty(RegistrationSettings.ENABLE_CONFIRM_EMAIL); + if (emailDoubleCheck && arguments.size() < 2 || !arguments.get(0).equals(arguments.get(1))) { commandService.send(player, MessageKey.USAGE_REGISTER); return; } final String email = arguments.get(0); - if (!Utils.isEmailCorrect(email, commandService.getSettings())) { + if (!commandService.validateEmail(email)) { commandService.send(player, MessageKey.INVALID_EMAIL); return; } - final String thePass = RandomString.generate(Settings.getRecoveryPassLength); + final String thePass = RandomString.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH)); management.performRegister(player, thePass, email); return; } diff --git a/src/main/java/fr/xephi/authme/process/ProcessService.java b/src/main/java/fr/xephi/authme/process/ProcessService.java index 0489447a..fd08b7ba 100644 --- a/src/main/java/fr/xephi/authme/process/ProcessService.java +++ b/src/main/java/fr/xephi/authme/process/ProcessService.java @@ -213,4 +213,12 @@ public class ProcessService { return validationService.validatePassword(password, username); } + public boolean validateEmail(String email) { + return validationService.validateEmail(email); + } + + public boolean isEmailFreeForRegistration(String email, CommandSender sender) { + return validationService.isEmailFreeForRegistration(email, sender); + } + } diff --git a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java index 9f2451e7..282f8f09 100644 --- a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java +++ b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java @@ -7,9 +7,7 @@ import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.process.Process; import fr.xephi.authme.process.ProcessService; -import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; -import fr.xephi.authme.util.Utils; import org.bukkit.entity.Player; /** @@ -42,9 +40,9 @@ public class AsyncAddEmail implements Process { if (currentEmail != null && !"your@email.com".equals(currentEmail)) { service.send(player, MessageKey.USAGE_CHANGE_EMAIL); - } else if (!Utils.isEmailCorrect(email, service.getSettings())) { + } else if (!service.validateEmail(email)) { service.send(player, MessageKey.INVALID_EMAIL); - } else if (dataSource.countAuthsByEmail(email) >= service.getProperty(EmailSettings.MAX_REG_PER_EMAIL)) { + } else if (!service.isEmailFreeForRegistration(email, player)) { service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); } else { auth.setEmail(email); diff --git a/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java b/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java index 488ddca3..7489327b 100644 --- a/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java +++ b/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java @@ -6,9 +6,7 @@ import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.process.Process; import fr.xephi.authme.process.ProcessService; -import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; -import fr.xephi.authme.util.Utils; import org.bukkit.entity.Player; /** @@ -42,11 +40,11 @@ public class AsyncChangeEmail implements Process { if (currentEmail == null) { service.send(player, MessageKey.USAGE_ADD_EMAIL); - } else if (newEmail == null || !Utils.isEmailCorrect(newEmail, service.getSettings())) { + } else if (newEmail == null || !service.validateEmail(newEmail)) { service.send(player, MessageKey.INVALID_NEW_EMAIL); } else if (!oldEmail.equals(currentEmail)) { service.send(player, MessageKey.INVALID_OLD_EMAIL); - } else if (dataSource.countAuthsByEmail(newEmail) >= service.getProperty(EmailSettings.MAX_REG_PER_EMAIL)) { + } else if (!service.isEmailFreeForRegistration(newEmail, player)) { service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); } else { saveNewEmail(auth); diff --git a/src/main/java/fr/xephi/authme/settings/Settings.java b/src/main/java/fr/xephi/authme/settings/Settings.java index a8530bce..915c953a 100644 --- a/src/main/java/fr/xephi/authme/settings/Settings.java +++ b/src/main/java/fr/xephi/authme/settings/Settings.java @@ -39,7 +39,6 @@ public final class Settings { public static List forceRegisterCommandsAsConsole; public static HashAlgorithm getPasswordHash; public static Pattern nickPattern; - public static boolean useLogging = false; public static boolean isChatAllowed, isPermissionCheckEnabled, isForcedRegistrationEnabled, isTeleportToSpawnEnabled, isSessionsEnabled, isAllowRestrictedIp, @@ -50,8 +49,7 @@ public final class Settings { protectInventoryBeforeLogInEnabled, isStopEnabled, reloadSupport, rakamakUseIp, noConsoleSpam, removePassword, displayOtherAccounts, emailRegistration, multiverse, bungee, - banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange, - disableSocialSpy, useEssentialsMotd, + banUnsafeIp, sessionExpireOnIpChange, useEssentialsMotd, enableProtection, recallEmail, useWelcomeMessage, broadcastWelcomeMessage, forceRegKick, forceRegLogin, checkVeryGames, removeJoinMessage, removeLeaveMessage, delayJoinMessage, @@ -59,15 +57,13 @@ public final class Settings { kickPlayersBeforeStopping, allowAllCommandsIfRegIsOptional, customAttributes, isRemoveSpeedEnabled, preventOtherCase, keepCollisionsDisabled; public static String getNickRegex, getUnloggedinGroup, - unRegisteredGroup, - backupWindowsPath, getRegisteredGroup, + unRegisteredGroup, backupWindowsPath, getRegisteredGroup, rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld, spawnPriority, crazyloginFileName, sendPlayerTo; public static int getWarnMessageInterval, getSessionTimeout, getRegistrationTimeout, getMaxNickLength, getMinNickLength, - getPasswordMinLen, getMovementRadius, - getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength, - getMailPort, maxLoginTry, captchaLength, saltLength, + getPasswordMinLen, getMovementRadius, getNonActivatedGroup, passwordMaxLength, + maxLoginTry, captchaLength, saltLength, bCryptLog2Rounds, getMaxLoginPerIp, getMaxJoinPerIp; protected static FileConfiguration configFile; @@ -145,8 +141,6 @@ public final class Settings { noConsoleSpam = load(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE); removePassword = configFile.getBoolean("Security.console.removePassword", true); getmailAccount = load(EmailSettings.MAIL_ACCOUNT); - getMailPort = configFile.getInt("Email.mailPort", 465); - getRecoveryPassLength = configFile.getInt("Email.RecoveryPasswordLength", 8); displayOtherAccounts = configFile.getBoolean("settings.restrictions.displayOtherAccounts", true); maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5); captchaLength = configFile.getInt("Security.captcha.captchaLength", 5); @@ -156,10 +150,7 @@ public final class Settings { bungee = configFile.getBoolean("Hooks.bungeecord", false); getForcedWorlds = configFile.getStringList("settings.restrictions.ForceSpawnOnTheseWorlds"); banUnsafeIp = configFile.getBoolean("settings.restrictions.banUnsafedIP", false); - doubleEmailCheck = configFile.getBoolean("settings.registration.doubleEmailCheck", false); sessionExpireOnIpChange = configFile.getBoolean("settings.sessions.sessionExpireOnIpChange", true); - useLogging = configFile.getBoolean("Security.console.logConsole", false); - disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true); bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10); useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false); defaultWorld = configFile.getString("Purge.defaultWorld", "world"); diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java index c9b472c3..1eb4deb8 100644 --- a/src/main/java/fr/xephi/authme/util/Utils.java +++ b/src/main/java/fr/xephi/authme/util/Utils.java @@ -7,9 +7,7 @@ import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.events.AuthMeTeleportEvent; import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.properties.EmailSettings; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; @@ -21,7 +19,6 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.List; /** * Utility class for various operations used in the codebase. @@ -254,38 +251,12 @@ public final class Utils { } } - public static boolean isEmailCorrect(String email, NewSetting settings) { - if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) { - return false; - } - final String emailDomain = email.split("@")[1]; - - List whitelist = settings.getProperty(EmailSettings.DOMAIN_WHITELIST); - if (!CollectionUtils.isEmpty(whitelist)) { - return containsIgnoreCase(whitelist, emailDomain); - } - - List blacklist = settings.getProperty(EmailSettings.DOMAIN_BLACKLIST); - return CollectionUtils.isEmpty(blacklist) || !containsIgnoreCase(blacklist, emailDomain); - } - - private static boolean containsIgnoreCase(Collection coll, String needle) { - for (String entry : coll) { - if (entry.equalsIgnoreCase(needle)) { - return true; - } - } - return false; - } - public static String getUUIDorName(OfflinePlayer player) { - String uuidOrName; try { - uuidOrName = player.getUniqueId().toString(); + return player.getUniqueId().toString(); } catch (Exception ignore) { - uuidOrName = player.getName(); + return player.getName(); } - return uuidOrName; } public enum GroupType { diff --git a/src/main/java/fr/xephi/authme/util/ValidationService.java b/src/main/java/fr/xephi/authme/util/ValidationService.java index 1adbda71..7f8b78b7 100644 --- a/src/main/java/fr/xephi/authme/util/ValidationService.java +++ b/src/main/java/fr/xephi/authme/util/ValidationService.java @@ -1,9 +1,17 @@ package fr.xephi.authme.util; +import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; +import fr.xephi.authme.permission.PermissionsManager; +import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.settings.NewSetting; +import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.SecuritySettings; +import org.bukkit.command.CommandSender; + +import java.util.Collection; +import java.util.List; /** * Validation service. @@ -11,9 +19,13 @@ import fr.xephi.authme.settings.properties.SecuritySettings; public class ValidationService { private final NewSetting settings; + private final DataSource dataSource; + private final PermissionsManager permissionsManager; - public ValidationService(NewSetting settings) { + public ValidationService(NewSetting settings, DataSource dataSource, PermissionsManager permissionsManager) { this.settings = settings; + this.dataSource = dataSource; + this.permissionsManager = permissionsManager; } /** @@ -39,4 +51,33 @@ public class ValidationService { } return null; } + + public boolean validateEmail(String email) { + if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) { + return false; + } + final String emailDomain = email.split("@")[1]; + + List whitelist = settings.getProperty(EmailSettings.DOMAIN_WHITELIST); + if (!CollectionUtils.isEmpty(whitelist)) { + return containsIgnoreCase(whitelist, emailDomain); + } + + List blacklist = settings.getProperty(EmailSettings.DOMAIN_BLACKLIST); + return CollectionUtils.isEmpty(blacklist) || !containsIgnoreCase(blacklist, emailDomain); + } + + public boolean isEmailFreeForRegistration(String email, CommandSender sender) { + return permissionsManager.hasPermission(sender, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS) + || dataSource.countAuthsByEmail(email) < settings.getProperty(EmailSettings.MAX_REG_PER_EMAIL); + } + + private static boolean containsIgnoreCase(Collection coll, String needle) { + for (String entry : coll) { + if (entry.equalsIgnoreCase(needle)) { + return true; + } + } + return false; + } } diff --git a/src/test/java/fr/xephi/authme/command/CommandServiceTest.java b/src/test/java/fr/xephi/authme/command/CommandServiceTest.java index 645d3a37..6c7ed5e5 100644 --- a/src/test/java/fr/xephi/authme/command/CommandServiceTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandServiceTest.java @@ -246,4 +246,35 @@ public class CommandServiceTest { assertThat(result, equalTo(MessageKey.INVALID_PASSWORD_LENGTH)); verify(validationService).validatePassword(password, user); } + + @Test + public void shouldValidateEmail() { + // given + String email = "test@example.tld"; + given(validationService.validateEmail(email)).willReturn(true); + + // when + boolean result = commandService.validateEmail(email); + + // then + assertThat(result, equalTo(true)); + verify(validationService).validateEmail(email); + } + + @Test + public void shouldCheckIfEmailCanBeUsed() { + // given + String email = "mail@example.com"; + CommandSender sender = mock(CommandSender.class); + given(validationService.isEmailFreeForRegistration(email, sender)) + .willReturn(true); + + // when + boolean result = commandService.isEmailFreeForRegistration(email, sender); + + // then + assertThat(result, equalTo(true)); + verify(validationService).isEmailFreeForRegistration(email, sender); + } + } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java index 17dbddad..1ea41355 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java @@ -1,14 +1,15 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.process.Management; -import fr.xephi.authme.settings.NewSetting; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.junit.Before; import org.junit.Test; -import org.mockito.Mockito; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import java.util.ArrayList; import java.util.Arrays; @@ -21,19 +22,16 @@ import static org.mockito.Mockito.verify; /** * Test for {@link AddEmailCommand}. */ +@RunWith(MockitoJUnitRunner.class) public class AddEmailCommandTest { + @Mock private CommandService commandService; - @Before - public void setUpMocks() { - commandService = mock(CommandService.class); - } - @Test public void shouldRejectNonPlayerSender() { // given - CommandSender sender = Mockito.mock(BlockCommandSender.class); + CommandSender sender = mock(BlockCommandSender.class); AddEmailCommand command = new AddEmailCommand(); // when @@ -46,18 +44,34 @@ public class AddEmailCommandTest { @Test public void shouldForwardData() { // given - Player sender = Mockito.mock(Player.class); - AddEmailCommand command = new AddEmailCommand(); + Player sender = mock(Player.class); + String email = "mail@example"; + given(commandService.validateEmail(email)).willReturn(true); Management management = mock(Management.class); given(commandService.getManagement()).willReturn(management); - NewSetting settings = mock(NewSetting.class); - given(commandService.getSettings()).willReturn(settings); + AddEmailCommand command = new AddEmailCommand(); // when - command.executeCommand(sender, Arrays.asList("mail@example", "mail@example"), commandService); + command.executeCommand(sender, Arrays.asList(email, email), commandService); // then - verify(management).performAddEmail(sender, "mail@example"); + verify(management).performAddEmail(sender, email); + } + + @Test + public void shouldFailForConfirmationMismatch() { + // given + Player sender = mock(Player.class); + String email = "asdfasdf@example.com"; + given(commandService.validateEmail(email)).willReturn(true); + AddEmailCommand command = new AddEmailCommand(); + + // when + command.executeCommand(sender, Arrays.asList(email, "wrongConf"), commandService); + + // then + verify(commandService, never()).getManagement(); + verify(commandService).send(sender, MessageKey.CONFIRM_EMAIL_MESSAGE); } } diff --git a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java index 84b79726..72f5e0c0 100644 --- a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java @@ -3,7 +3,7 @@ package fr.xephi.authme.command.executable.register; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.process.Management; -import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; @@ -14,6 +14,7 @@ import org.junit.Test; import java.util.ArrayList; import java.util.Collections; +import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION; import static org.hamcrest.Matchers.containsString; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.argThat; @@ -31,7 +32,6 @@ public class RegisterCommandTest { @Before public void initializeAuthMeMock() { WrapperMock.createInstance(); - Settings.captchaLength = 10; commandService = mock(CommandService.class); } @@ -70,6 +70,8 @@ public class RegisterCommandTest { RegisterCommand command = new RegisterCommand(); Management management = mock(Management.class); given(commandService.getManagement()).willReturn(management); + given(commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION)).willReturn(false); + given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(false); // when command.executeCommand(sender, Collections.singletonList("password"), commandService); diff --git a/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java b/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java index 14d2e3e2..8e4acddf 100644 --- a/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java +++ b/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java @@ -15,9 +15,9 @@ import fr.xephi.authme.util.ValidationService; import org.bukkit.command.CommandSender; import org.junit.Before; import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -28,23 +28,38 @@ import static org.mockito.Mockito.verify; /** * Test for {@link ProcessService}. */ +@RunWith(MockitoJUnitRunner.class) public class ProcessServiceTest { private ProcessService processService; - private Map, Object> mocks; + @Mock + private ValidationService validationService; + @Mock + private NewSetting settings; + @Mock + private Messages messages; + @Mock + private IpAddressManager ipAddressManager; + @Mock + private PasswordSecurity passwordSecurity; + @Mock + private AuthMe authMe; + @Mock + private DataSource dataSource; + @Mock + private SpawnLoader spawnLoader; + @Mock + private PluginHooks pluginHooks; @Before public void setUpService() { - mocks = new HashMap<>(); - processService = new ProcessService(newMock(NewSetting.class), newMock(Messages.class), newMock(AuthMe.class), - newMock(DataSource.class), newMock(IpAddressManager.class), newMock(PasswordSecurity.class), - newMock(PluginHooks.class), newMock(SpawnLoader.class), newMock(ValidationService.class)); + processService = new ProcessService(settings, messages, authMe, dataSource, ipAddressManager, passwordSecurity, + pluginHooks, spawnLoader, validationService); } @Test public void shouldGetProperty() { // given - NewSetting settings = getMock(NewSetting.class); given(settings.getProperty(SecuritySettings.CAPTCHA_LENGTH)).willReturn(8); // when @@ -58,16 +73,15 @@ public class ProcessServiceTest { @Test public void shouldReturnSettings() { // given/when - NewSetting settings = processService.getSettings(); + NewSetting result = processService.getSettings(); // then - assertThat(settings, equalTo(getMock(NewSetting.class))); + assertThat(result, equalTo(settings)); } @Test public void shouldSendMessageToPlayer() { // given - Messages messages = getMock(Messages.class); CommandSender sender = mock(CommandSender.class); MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED; @@ -81,7 +95,6 @@ public class ProcessServiceTest { @Test public void shouldSendMessageWithReplacements() { // given - Messages messages = getMock(Messages.class); CommandSender sender = mock(CommandSender.class); MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED; String[] replacements = new String[]{"test", "toast"}; @@ -96,7 +109,6 @@ public class ProcessServiceTest { @Test public void shouldRetrieveMessage() { // given - Messages messages = getMock(Messages.class); MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED; String[] lines = new String[]{"First message line", "second line"}; given(messages.retrieve(key)).willReturn(lines); @@ -112,7 +124,6 @@ public class ProcessServiceTest { @Test public void shouldRetrieveSingleMessage() { // given - Messages messages = getMock(Messages.class); MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED; String text = "Test text"; given(messages.retrieveSingle(key)).willReturn(text); @@ -128,52 +139,51 @@ public class ProcessServiceTest { @Test public void shouldReturnAuthMeInstance() { // given / when - AuthMe authMe = processService.getAuthMe(); + AuthMe result = processService.getAuthMe(); // then - assertThat(authMe, equalTo(getMock(AuthMe.class))); + assertThat(result, equalTo(authMe)); } @Test public void shouldReturnPluginHooks() { // given / when - PluginHooks pluginHooks = processService.getPluginHooks(); + PluginHooks result = processService.getPluginHooks(); // then - assertThat(pluginHooks, equalTo(getMock(PluginHooks.class))); + assertThat(result, equalTo(pluginHooks)); } @Test public void shouldReturnIpAddressManager() { // given / when - IpAddressManager ipAddressManager = processService.getIpAddressManager(); + IpAddressManager result = processService.getIpAddressManager(); // then - assertThat(ipAddressManager, equalTo(getMock(IpAddressManager.class))); + assertThat(result, equalTo(ipAddressManager)); } @Test public void shouldReturnSpawnLoader() { // given / when - SpawnLoader spawnLoader = processService.getSpawnLoader(); + SpawnLoader result = processService.getSpawnLoader(); // then - assertThat(spawnLoader, equalTo(getMock(SpawnLoader.class))); + assertThat(result, equalTo(spawnLoader)); } @Test public void shouldReturnDatasource() { // given / when - DataSource dataSource = processService.getDataSource(); + DataSource result = processService.getDataSource(); // then - assertThat(dataSource, equalTo(getMock(DataSource.class))); + assertThat(result, equalTo(dataSource)); } @Test public void shouldComputeHash() { // given - PasswordSecurity passwordSecurity = getMock(PasswordSecurity.class); String password = "test123"; String username = "Username"; HashedPassword hashedPassword = new HashedPassword("hashedResult", "salt12342"); @@ -192,7 +202,6 @@ public class ProcessServiceTest { // given String user = "test-user"; String password = "passw0rd"; - ValidationService validationService = getMock(ValidationService.class); given(validationService.validatePassword(password, user)).willReturn(MessageKey.PASSWORD_MATCH_ERROR); // when @@ -203,17 +212,33 @@ public class ProcessServiceTest { verify(validationService).validatePassword(password, user); } - private T newMock(Class clazz) { - T mock = mock(clazz); - mocks.put(clazz, mock); - return mock; + @Test + public void shouldValidateEmail() { + // given + String email = "test@example.tld"; + given(validationService.validateEmail(email)).willReturn(true); + + // when + boolean result = processService.validateEmail(email); + + // then + assertThat(result, equalTo(true)); + verify(validationService).validateEmail(email); } - private T getMock(Class clazz) { - Object mock = mocks.get(clazz); - if (mock == null) { - throw new IllegalArgumentException("No mock of type " + clazz); - } - return clazz.cast(mock); + @Test + public void shouldCheckIfEmailCanBeUsed() { + // given + String email = "mail@example.com"; + CommandSender sender = mock(CommandSender.class); + given(validationService.isEmailFreeForRegistration(email, sender)) + .willReturn(true); + + // when + boolean result = processService.isEmailFreeForRegistration(email, sender); + + // then + assertThat(result, equalTo(true)); + verify(validationService).isEmailFreeForRegistration(email, sender); } } diff --git a/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java b/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java index 9f93a47d..3d6ccee7 100644 --- a/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java +++ b/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java @@ -6,8 +6,6 @@ import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.process.ProcessService; -import fr.xephi.authme.settings.NewSetting; -import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; import org.bukkit.entity.Player; import org.junit.BeforeClass; @@ -21,7 +19,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; /** * Test for {@link AsyncAddEmail}. @@ -46,14 +43,16 @@ public class AsyncAddEmailTest { @Test public void shouldAddEmail() { // given - AsyncAddEmail process = createProcess("my.mail@example.org"); + String email = "my.mail@example.org"; + AsyncAddEmail process = createProcess(email); given(player.getName()).willReturn("testEr"); given(playerCache.isAuthenticated("tester")).willReturn(true); PlayerAuth auth = mock(PlayerAuth.class); given(auth.getEmail()).willReturn(null); given(playerCache.getAuth("tester")).willReturn(auth); - given(dataSource.countAuthsByEmail("my.mail@example.org")).willReturn(1); given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(true); + given(service.validateEmail(email)).willReturn(true); + given(service.isEmailFreeForRegistration(email, player)).willReturn(true); // when process.run(); @@ -61,21 +60,24 @@ public class AsyncAddEmailTest { // then verify(dataSource).updateEmail(auth); verify(service).send(player, MessageKey.EMAIL_ADDED_SUCCESS); - verify(auth).setEmail("my.mail@example.org"); + verify(auth).setEmail(email); verify(playerCache).updatePlayer(auth); } @Test public void shouldReturnErrorWhenMailCannotBeSaved() { // given - AsyncAddEmail process = createProcess("my.mail@example.org"); + String email = "my.mail@example.org"; + AsyncAddEmail process = createProcess(email); given(player.getName()).willReturn("testEr"); given(playerCache.isAuthenticated("tester")).willReturn(true); PlayerAuth auth = mock(PlayerAuth.class); given(auth.getEmail()).willReturn(null); given(playerCache.getAuth("tester")).willReturn(auth); - given(dataSource.countAuthsByEmail("my.mail@example.org")).willReturn(0); + given(dataSource.countAuthsByEmail(email)).willReturn(0); given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(false); + given(service.validateEmail(email)).willReturn(true); + given(service.isEmailFreeForRegistration(email, player)).willReturn(true); // when process.run(); @@ -94,7 +96,6 @@ public class AsyncAddEmailTest { PlayerAuth auth = mock(PlayerAuth.class); given(auth.getEmail()).willReturn("another@mail.tld"); given(playerCache.getAuth("my_player")).willReturn(auth); - given(dataSource.countAuthsByEmail("some.mail@example.org")).willReturn(0); // when process.run(); @@ -107,13 +108,14 @@ public class AsyncAddEmailTest { @Test public void shouldNotAddMailIfItIsInvalid() { // given - AsyncAddEmail process = createProcess("invalid_mail"); + String email = "invalid_mail"; + AsyncAddEmail process = createProcess(email); given(player.getName()).willReturn("my_Player"); given(playerCache.isAuthenticated("my_player")).willReturn(true); PlayerAuth auth = mock(PlayerAuth.class); given(auth.getEmail()).willReturn(null); given(playerCache.getAuth("my_player")).willReturn(auth); - given(dataSource.countAuthsByEmail("invalid_mail")).willReturn(0); + given(service.validateEmail(email)).willReturn(false); // when process.run(); @@ -126,13 +128,15 @@ public class AsyncAddEmailTest { @Test public void shouldNotAddMailIfAlreadyUsed() { // given - AsyncAddEmail process = createProcess("player@mail.tld"); + String email = "player@mail.tld"; + AsyncAddEmail process = createProcess(email); given(player.getName()).willReturn("TestName"); given(playerCache.isAuthenticated("testname")).willReturn(true); PlayerAuth auth = mock(PlayerAuth.class); given(auth.getEmail()).willReturn(null); given(playerCache.getAuth("testname")).willReturn(auth); - given(dataSource.countAuthsByEmail("player@mail.tld")).willReturn(2); + given(service.validateEmail(email)).willReturn(true); + given(service.isEmailFreeForRegistration(email, player)).willReturn(false); // when process.run(); @@ -193,15 +197,12 @@ public class AsyncAddEmailTest { } /** - * Create an instance of {@link AsyncAddEmail} and save the mocks to this class' fields. + * Create an instance of {@link AsyncAddEmail} with the class' mocks. * * @param email The email to use * @return The created process */ private AsyncAddEmail createProcess(String email) { - NewSetting settings = mock(NewSetting.class); - when(service.getProperty(EmailSettings.MAX_REG_PER_EMAIL)).thenReturn(2); - when(service.getSettings()).thenReturn(settings); return new AsyncAddEmail(player, email, dataSource, playerCache, service); } diff --git a/src/test/java/fr/xephi/authme/process/email/AsyncChangeEmailTest.java b/src/test/java/fr/xephi/authme/process/email/AsyncChangeEmailTest.java index 1ccb9b67..a90ff9b2 100644 --- a/src/test/java/fr/xephi/authme/process/email/AsyncChangeEmailTest.java +++ b/src/test/java/fr/xephi/authme/process/email/AsyncChangeEmailTest.java @@ -5,7 +5,6 @@ import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.process.ProcessService; -import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; import org.bukkit.entity.Player; @@ -35,18 +34,19 @@ public class AsyncChangeEmailTest { private DataSource dataSource; @Mock private ProcessService service; - @Mock - private NewSetting settings; @Test public void shouldAddEmail() { // given - AsyncChangeEmail process = createProcess("old@mail.tld", "new@mail.tld"); + String newEmail = "new@mail.tld"; + AsyncChangeEmail process = createProcess("old@mail.tld", newEmail); given(player.getName()).willReturn("Bobby"); given(playerCache.isAuthenticated("bobby")).willReturn(true); PlayerAuth auth = authWithMail("old@mail.tld"); given(playerCache.getAuth("bobby")).willReturn(auth); given(dataSource.updateEmail(auth)).willReturn(true); + given(service.validateEmail(newEmail)).willReturn(true); + given(service.isEmailFreeForRegistration(newEmail, player)).willReturn(true); // when process.run(); @@ -60,12 +60,15 @@ public class AsyncChangeEmailTest { @Test public void shouldShowErrorIfSaveFails() { // given - AsyncChangeEmail process = createProcess("old@mail.tld", "new@mail.tld"); + String newEmail = "new@mail.tld"; + AsyncChangeEmail process = createProcess("old@mail.tld", newEmail); given(player.getName()).willReturn("Bobby"); given(playerCache.isAuthenticated("bobby")).willReturn(true); PlayerAuth auth = authWithMail("old@mail.tld"); given(playerCache.getAuth("bobby")).willReturn(auth); given(dataSource.updateEmail(auth)).willReturn(false); + given(service.validateEmail(newEmail)).willReturn(true); + given(service.isEmailFreeForRegistration(newEmail, player)).willReturn(true); // when process.run(); @@ -97,11 +100,13 @@ public class AsyncChangeEmailTest { @Test public void shouldRejectInvalidNewMail() { // given - AsyncChangeEmail process = createProcess("old@mail.tld", "bogus"); + String newEmail = "bogus"; + AsyncChangeEmail process = createProcess("old@mail.tld", newEmail); given(player.getName()).willReturn("Bobby"); given(playerCache.isAuthenticated("bobby")).willReturn(true); PlayerAuth auth = authWithMail("old@mail.tld"); given(playerCache.getAuth("bobby")).willReturn(auth); + given(service.validateEmail(newEmail)).willReturn(false); // when process.run(); @@ -115,11 +120,15 @@ public class AsyncChangeEmailTest { @Test public void shouldRejectInvalidOldEmail() { // given - AsyncChangeEmail process = createProcess("old@mail.tld", "new@mail.tld"); + String newEmail = "new@mail.tld"; + AsyncChangeEmail process = createProcess("old@mail.tld", newEmail); given(player.getName()).willReturn("Bobby"); given(playerCache.isAuthenticated("bobby")).willReturn(true); PlayerAuth auth = authWithMail("other@address.email"); given(playerCache.getAuth("bobby")).willReturn(auth); + given(service.validateEmail(newEmail)).willReturn(true); + given(service.isEmailFreeForRegistration(newEmail, player)).willReturn(true); + // when process.run(); @@ -133,12 +142,14 @@ public class AsyncChangeEmailTest { @Test public void shouldRejectAlreadyUsedEmail() { // given - AsyncChangeEmail process = createProcess("old@example.com", "new@example.com"); + String newEmail = "new@example.com"; + AsyncChangeEmail process = createProcess("old@example.com", newEmail); given(player.getName()).willReturn("Username"); given(playerCache.isAuthenticated("username")).willReturn(true); PlayerAuth auth = authWithMail("old@example.com"); given(playerCache.getAuth("username")).willReturn(auth); - given(dataSource.countAuthsByEmail("new@example.com")).willReturn(5); + given(service.validateEmail(newEmail)).willReturn(true); + given(service.isEmailFreeForRegistration(newEmail, player)).willReturn(false); // when process.run(); @@ -210,7 +221,6 @@ public class AsyncChangeEmailTest { private AsyncChangeEmail createProcess(String oldEmail, String newEmail) { given(service.getProperty(EmailSettings.MAX_REG_PER_EMAIL)).willReturn(5); - given(service.getSettings()).willReturn(settings); return new AsyncChangeEmail(player, oldEmail, newEmail, dataSource, playerCache, service); } } diff --git a/src/test/java/fr/xephi/authme/util/UtilsTest.java b/src/test/java/fr/xephi/authme/util/UtilsTest.java index 639946f6..a1e9a6a1 100644 --- a/src/test/java/fr/xephi/authme/util/UtilsTest.java +++ b/src/test/java/fr/xephi/authme/util/UtilsTest.java @@ -3,26 +3,23 @@ package fr.xephi.authme.util; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLoggerTestInitializer; import fr.xephi.authme.ReflectionTestUtils; -import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.Settings; - -import fr.xephi.authme.settings.properties.EmailSettings; import org.bukkit.entity.Player; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; /** * Test for the {@link Utils} class. @@ -30,7 +27,6 @@ import static org.mockito.Mockito.*; public class UtilsTest { private static AuthMe authMeMock; - private PermissionsManager permissionsManagerMock; /** * The Utils class initializes its fields in a {@code static} block which is only executed once during the JUnit @@ -51,9 +47,6 @@ public class UtilsTest { // before every test -- this is OK because it is retrieved via authMeMock. It is just crucial that authMeMock // remain the same object. reset(authMeMock); - - permissionsManagerMock = mock(PermissionsManager.class); - when(authMeMock.getPermissionsManager()).thenReturn(permissionsManagerMock); } @Test @@ -103,95 +96,6 @@ public class UtilsTest { assertThat(players, hasSize(2)); } - // ---------------- - // Tests for Utils#isEmailCorrect() - // ---------------- - @Test - public void shouldAcceptEmailWithEmptyLists() { - // given - NewSetting settings = mock(NewSetting.class); - given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections. emptyList()); - given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections. emptyList()); - - // when - boolean result = Utils.isEmailCorrect("test@example.org", settings); - - // then - assertThat(result, equalTo(true)); - } - - @Test - public void shouldAcceptEmailWithWhitelist() { - // given - NewSetting settings = mock(NewSetting.class); - given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)) - .willReturn(Arrays.asList("domain.tld", "example.com")); - given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections. emptyList()); - - // when - boolean result = Utils.isEmailCorrect("TesT@Example.com", settings); - - // then - assertThat(result, equalTo(true)); - } - - @Test - public void shouldRejectEmailNotInWhitelist() { - // given - NewSetting settings = mock(NewSetting.class); - given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)) - .willReturn(Arrays.asList("domain.tld", "example.com")); - given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections. emptyList()); - - // when - boolean result = Utils.isEmailCorrect("email@other-domain.abc", settings); - - // then - assertThat(result, equalTo(false)); - } - - @Test - public void shouldAcceptEmailNotInBlacklist() { - // given - NewSetting settings = mock(NewSetting.class); - given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections. emptyList()); - given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)) - .willReturn(Arrays.asList("Example.org", "a-test-name.tld")); - - // when - boolean result = Utils.isEmailCorrect("sample@valid-name.tld", settings); - - // then - assertThat(result, equalTo(true)); - } - - @Test - public void shouldRejectEmailInBlacklist() { - // given - NewSetting settings = mock(NewSetting.class); - given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections. emptyList()); - given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)) - .willReturn(Arrays.asList("Example.org", "a-test-name.tld")); - - // when - boolean result = Utils.isEmailCorrect("sample@a-Test-name.tld", settings); - - // then - assertThat(result, equalTo(false)); - } - - @Test - public void shouldRejectInvalidEmail() { - // given/when/then - assertThat(Utils.isEmailCorrect("invalidinput", mock(NewSetting.class)), equalTo(false)); - } - - @Test - public void shouldRejectDefaultEmail() { - // given/when/then - assertThat(Utils.isEmailCorrect("your@email.com", mock(NewSetting.class)), equalTo(false)); - } - // Note: This method is used through reflections public static Player[] onlinePlayersImpl() { return new Player[]{ diff --git a/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java b/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java index 0fd567f2..ed784510 100644 --- a/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java +++ b/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java @@ -1,14 +1,23 @@ package fr.xephi.authme.util; import com.google.common.base.Strings; +import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; +import fr.xephi.authme.permission.PermissionsManager; +import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.settings.NewSetting; +import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.SecuritySettings; +import org.bukkit.command.CommandSender; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import java.util.Arrays; +import java.util.Collections; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; @@ -19,19 +28,26 @@ import static org.mockito.Mockito.mock; /** * Test for {@link ValidationService}. */ +@RunWith(MockitoJUnitRunner.class) public class ValidationServiceTest { private ValidationService validationService; + @Mock + private NewSetting settings; + @Mock + private DataSource dataSource; + @Mock + private PermissionsManager permissionsManager; @Before public void createService() { - NewSetting settings = mock(NewSetting.class); given(settings.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX)).willReturn("[a-zA-Z]+"); given(settings.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)).willReturn(3); given(settings.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)).willReturn(20); given(settings.getProperty(SecuritySettings.UNSAFE_PASSWORDS)) .willReturn(Arrays.asList("unsafe", "other-unsafe")); - validationService = new ValidationService(settings); + given(settings.getProperty(EmailSettings.MAX_REG_PER_EMAIL)).willReturn(3); + validationService = new ValidationService(settings, dataSource, permissionsManager); } @Test @@ -89,4 +105,129 @@ public class ValidationServiceTest { assertThat(error, nullValue()); } + @Test + public void shouldAcceptEmailWithEmptyLists() { + // given + given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections.emptyList()); + given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections.emptyList()); + + // when + boolean result = validationService.validateEmail("test@example.org"); + + // then + assertThat(result, equalTo(true)); + } + + @Test + public void shouldAcceptEmailWithWhitelist() { + // given + given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)) + .willReturn(Arrays.asList("domain.tld", "example.com")); + given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections.emptyList()); + + // when + boolean result = validationService.validateEmail("TesT@Example.com"); + + // then + assertThat(result, equalTo(true)); + } + + @Test + public void shouldRejectEmailNotInWhitelist() { + // given + given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)) + .willReturn(Arrays.asList("domain.tld", "example.com")); + given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections.emptyList()); + + // when + boolean result = validationService.validateEmail("email@other-domain.abc"); + + // then + assertThat(result, equalTo(false)); + } + + @Test + public void shouldAcceptEmailNotInBlacklist() { + // given + given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections.emptyList()); + given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)) + .willReturn(Arrays.asList("Example.org", "a-test-name.tld")); + + // when + boolean result = validationService.validateEmail("sample@valid-name.tld"); + + // then + assertThat(result, equalTo(true)); + } + + @Test + public void shouldRejectEmailInBlacklist() { + // given + given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections.emptyList()); + given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)) + .willReturn(Arrays.asList("Example.org", "a-test-name.tld")); + + // when + boolean result = validationService.validateEmail("sample@a-Test-name.tld"); + + // then + assertThat(result, equalTo(false)); + } + + @Test + public void shouldRejectInvalidEmail() { + // given/when/then + assertThat(validationService.validateEmail("invalidinput"), equalTo(false)); + } + + @Test + public void shouldRejectDefaultEmail() { + // given/when/then + assertThat(validationService.validateEmail("your@email.com"), equalTo(false)); + } + + public void shouldAllowRegistration() { + // given + CommandSender sender = mock(CommandSender.class); + String email = "my.address@example.org"; + given(permissionsManager.hasPermission(sender, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) + .willReturn(false); + given(dataSource.countAuthsByEmail(email)).willReturn(2); + + // when + boolean result = validationService.isEmailFreeForRegistration(email, sender); + + // then + assertThat(result, equalTo(true)); + } + + public void shouldRejectEmailWithTooManyAccounts() { + // given + CommandSender sender = mock(CommandSender.class); + String email = "mail@example.org"; + given(permissionsManager.hasPermission(sender, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) + .willReturn(false); + given(dataSource.countAuthsByEmail(email)).willReturn(5); + + // when + boolean result = validationService.isEmailFreeForRegistration(email, sender); + + // then + assertThat(result, equalTo(false)); + } + + public void shouldAllowBypassForPresentPermission() { + // given + CommandSender sender = mock(CommandSender.class); + String email = "mail-address@example.com"; + given(permissionsManager.hasPermission(sender, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) + .willReturn(true); + given(dataSource.countAuthsByEmail(email)).willReturn(7); + + // when + boolean result = validationService.isEmailFreeForRegistration(email, sender); + + // then + assertThat(result, equalTo(true)); + } }