#472 Require recovery code before resetting password

- /email recovery generates recovery code and resets password only if recovery code is also given
- Change data source method to return email and recovery code
This commit is contained in:
ljacqu
2016-09-10 14:27:26 +02:00
parent 3b723bbbe9
commit c5f5c0d2fd
12 changed files with 224 additions and 68 deletions
@@ -384,6 +384,7 @@ public class CommandInitializer {
.detailedDescription("Recover your account using an Email address by sending a mail containing " +
"a new password.")
.withArgument("email", "Email address", false)
.withArgument("code", "Recovery code", true)
.permission(PlayerPermission.RECOVER_EMAIL)
.executableCommand(RecoverEmailCommand.class)
.build();
@@ -1,7 +1,7 @@
package fr.xephi.authme.command.executable.email;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.EmailRecoveryData;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
@@ -17,6 +17,9 @@ import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.util.List;
/**
* Command for password recovery by email.
*/
public class RecoverEmailCommand extends PlayerCommand {
@Inject
@@ -49,22 +52,47 @@ public class RecoverEmailCommand extends PlayerCommand {
return;
}
PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
EmailRecoveryData recoveryData = dataSource.getEmailRecoveryData(playerName);
if (recoveryData == null) {
commandService.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
return;
}
if (!playerMail.equalsIgnoreCase(auth.getEmail()) || "your@email.com".equalsIgnoreCase(auth.getEmail())) {
final String email = recoveryData.getEmail();
if (email == null || !email.equalsIgnoreCase(playerMail) || "your@email.com".equalsIgnoreCase(email)) {
commandService.send(player, MessageKey.INVALID_EMAIL);
return;
}
if (arguments.size() == 1) {
// Process /email recover addr@example.com
createAndSendRecoveryCode(playerName, recoveryData);
} else {
// Process /email recover addr@example.com 12394
processRecoveryCode(player, arguments.get(1), recoveryData);
}
}
private void createAndSendRecoveryCode(String name, EmailRecoveryData recoveryData) {
// TODO #472: Add configurations
String recoveryCode = RandomString.generateHex(8);
long expiration = System.currentTimeMillis() + (3 * 60 * 60_000L); // 3 hours
dataSource.setRecoveryCode(name, recoveryCode, expiration);
sendMailSsl.sendRecoveryCode(recoveryData.getEmail(), recoveryCode);
}
private void processRecoveryCode(Player player, String code, EmailRecoveryData recoveryData) {
if (!code.equals(recoveryData.getRecoveryCode())) {
player.sendMessage("The recovery code is not correct! Use /email recovery [email] to generate a new one");
return;
}
final String name = player.getName();
String thePass = RandomString.generate(commandService.getProperty(EmailSettings.RECOVERY_PASSWORD_LENGTH));
HashedPassword hashNew = passwordSecurity.computeHash(thePass, playerName);
auth.setPassword(hashNew);
dataSource.updatePassword(auth);
sendMailSsl.sendPasswordMail(auth, thePass);
HashedPassword hashNew = passwordSecurity.computeHash(thePass, name);
dataSource.updatePassword(name, hashNew);
dataSource.removeRecoveryCode(name);
sendMailSsl.sendPasswordMail(name, recoveryData.getEmail(), thePass);
commandService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
}
}