#472 Add translatable messages and unit tests
This commit is contained in:
@@ -72,7 +72,7 @@ public class RecoverEmailCommand extends PlayerCommand {
|
||||
if (recoveryCodeManager.isRecoveryCodeNeeded()) {
|
||||
// Process /email recovery addr@example.com
|
||||
if (arguments.size() == 1) {
|
||||
createAndSendRecoveryCode(playerName, email);
|
||||
createAndSendRecoveryCode(player, email);
|
||||
} else {
|
||||
// Process /email recovery addr@example.com 12394
|
||||
processRecoveryCode(player, arguments.get(1), email);
|
||||
@@ -82,15 +82,16 @@ public class RecoverEmailCommand extends PlayerCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private void createAndSendRecoveryCode(String name, String email) {
|
||||
String recoveryCode = recoveryCodeManager.generateCode(name);
|
||||
sendMailSsl.sendRecoveryCode(name, email, recoveryCode);
|
||||
private void createAndSendRecoveryCode(Player player, String email) {
|
||||
String recoveryCode = recoveryCodeManager.generateCode(player.getName());
|
||||
sendMailSsl.sendRecoveryCode(player.getName(), email, recoveryCode);
|
||||
commandService.send(player, MessageKey.RECOVERY_CODE_SENT);
|
||||
}
|
||||
|
||||
private void processRecoveryCode(Player player, String code, String email) {
|
||||
final String name = player.getName();
|
||||
if (!recoveryCodeManager.isCodeValid(name, code)) {
|
||||
player.sendMessage("The recovery code is not correct! Use /email recovery [email] to generate a new one");
|
||||
commandService.send(player, MessageKey.INCORRECT_RECOVERY_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,11 @@ public enum MessageKey {
|
||||
|
||||
KICK_FOR_ADMIN_REGISTER("kicked_admin_registered"),
|
||||
|
||||
INCOMPLETE_EMAIL_SETTINGS("incomplete_email_settings");
|
||||
INCOMPLETE_EMAIL_SETTINGS("incomplete_email_settings"),
|
||||
|
||||
RECOVERY_CODE_SENT("recovery_code_sent"),
|
||||
|
||||
INCORRECT_RECOVERY_CODE("recovery_code_incorrect");
|
||||
|
||||
private String key;
|
||||
private String[] tags;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package fr.xephi.authme.service;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
@@ -17,7 +18,7 @@ import static fr.xephi.authme.util.Utils.MILLIS_PER_HOUR;
|
||||
*/
|
||||
public class RecoveryCodeManager implements SettingsDependent {
|
||||
|
||||
private Map<String, TimedEntry> recoveryCodes = new ConcurrentHashMap<>();
|
||||
private Map<String, ExpiringEntry> recoveryCodes = new ConcurrentHashMap<>();
|
||||
|
||||
private int recoveryCodeLength;
|
||||
private long recoveryCodeExpirationMillis;
|
||||
@@ -27,24 +28,45 @@ public class RecoveryCodeManager implements SettingsDependent {
|
||||
reload(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether recovery codes are enabled or not
|
||||
*/
|
||||
public boolean isRecoveryCodeNeeded() {
|
||||
return recoveryCodeExpirationMillis > 0;
|
||||
return recoveryCodeLength > 0 && recoveryCodeExpirationMillis > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the recovery code for the given player.
|
||||
*
|
||||
* @param player the player to generate a code for
|
||||
* @return the generated code
|
||||
*/
|
||||
public String generateCode(String player) {
|
||||
String code = RandomString.generateHex(recoveryCodeLength);
|
||||
recoveryCodes.put(player, new TimedEntry(code, System.currentTimeMillis() + recoveryCodeExpirationMillis));
|
||||
recoveryCodes.put(player, new ExpiringEntry(code, System.currentTimeMillis() + recoveryCodeExpirationMillis));
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the supplied code is valid for the given player.
|
||||
*
|
||||
* @param player the player to check for
|
||||
* @param code the code to check
|
||||
* @return true if the code matches and has not expired, false otherwise
|
||||
*/
|
||||
public boolean isCodeValid(String player, String code) {
|
||||
TimedEntry entry = recoveryCodes.get(player);
|
||||
ExpiringEntry entry = recoveryCodes.get(player);
|
||||
if (entry != null) {
|
||||
return code != null && code.equals(entry.getCode());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the player's recovery code if present.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public void removeCode(String player) {
|
||||
recoveryCodes.remove(player);
|
||||
}
|
||||
@@ -55,17 +77,21 @@ public class RecoveryCodeManager implements SettingsDependent {
|
||||
recoveryCodeExpirationMillis = settings.getProperty(RECOVERY_CODE_HOURS_VALID) * MILLIS_PER_HOUR;
|
||||
}
|
||||
|
||||
private static final class TimedEntry {
|
||||
/**
|
||||
* Entry with an expiration.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static final class ExpiringEntry {
|
||||
|
||||
private final String code;
|
||||
private final long expiration;
|
||||
|
||||
TimedEntry(String code, long expiration) {
|
||||
ExpiringEntry(String code, long expiration) {
|
||||
this.code = code;
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
String getCode() {
|
||||
return System.currentTimeMillis() < expiration ? code : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class SecuritySettings implements SettingsHolder {
|
||||
public static final Property<Integer> TEMPBAN_MINUTES_BEFORE_RESET =
|
||||
newProperty("Security.tempban.minutesBeforeCounterReset", 480);
|
||||
|
||||
@Comment("Number of characters a recovery code should have")
|
||||
@Comment("Number of characters a recovery code should have (0 to disable)")
|
||||
public static final Property<Integer> RECOVERY_CODE_LENGTH =
|
||||
newProperty("Security.recoveryCode.length", 8);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user