-
Notifications
You must be signed in to change notification settings - Fork 512
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add max tries for /email code - Introduce a PasswordRecoveryService
- Loading branch information
1 parent
a64f758
commit 7d4bfcd
Showing
40 changed files
with
529 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
src/main/java/fr/xephi/authme/command/executable/email/ProcessCodeCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package fr.xephi.authme.command.executable.email; | ||
|
||
import fr.xephi.authme.command.PlayerCommand; | ||
import fr.xephi.authme.data.auth.PlayerAuth; | ||
import fr.xephi.authme.datasource.DataSource; | ||
import fr.xephi.authme.message.MessageKey; | ||
import fr.xephi.authme.service.CommonService; | ||
import fr.xephi.authme.service.PasswordRecoveryService; | ||
import fr.xephi.authme.service.RecoveryCodeService; | ||
import org.bukkit.entity.Player; | ||
|
||
import javax.inject.Inject; | ||
import java.util.List; | ||
|
||
/** | ||
* Command for submitting email recovery code. | ||
*/ | ||
public class ProcessCodeCommand extends PlayerCommand { | ||
|
||
@Inject | ||
private CommonService commonService; | ||
|
||
@Inject | ||
private DataSource dataSource; | ||
|
||
@Inject | ||
private RecoveryCodeService codeService; | ||
|
||
@Inject | ||
private PasswordRecoveryService recoveryService; | ||
|
||
@Override | ||
protected void runCommand(Player player, List<String> arguments) { | ||
String name = player.getName(); | ||
String code = arguments.get(0); | ||
|
||
if (codeService.hasTriesLeft(name)) { | ||
if (codeService.isCodeValid(name, code)) { | ||
PlayerAuth auth = dataSource.getAuth(name); | ||
String email = auth.getEmail(); | ||
if (email == null || "your@email.com".equalsIgnoreCase(email)) { | ||
commonService.send(player, MessageKey.INVALID_EMAIL); | ||
return; | ||
} | ||
|
||
recoveryService.generateAndSendNewPassword(player, email); | ||
codeService.removeCode(name); | ||
} else { | ||
commonService.send(player, MessageKey.INCORRECT_RECOVERY_CODE, | ||
Integer.toString(codeService.getTriesLeft(name))); | ||
} | ||
} else { | ||
codeService.removeCode(name); | ||
commonService.send(player, MessageKey.RECOVERY_TRIES_EXCEEDED); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
src/main/java/fr/xephi/authme/service/PasswordRecoveryService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package fr.xephi.authme.service; | ||
|
||
import fr.xephi.authme.datasource.DataSource; | ||
import fr.xephi.authme.initialization.Reloadable; | ||
import fr.xephi.authme.mail.EmailService; | ||
import fr.xephi.authme.message.MessageKey; | ||
import fr.xephi.authme.message.Messages; | ||
import fr.xephi.authme.security.PasswordSecurity; | ||
import fr.xephi.authme.security.crypts.HashedPassword; | ||
import fr.xephi.authme.settings.properties.SecuritySettings; | ||
import fr.xephi.authme.util.RandomStringUtils; | ||
import fr.xephi.authme.util.expiring.Duration; | ||
import fr.xephi.authme.util.expiring.ExpiringSet; | ||
import org.bukkit.entity.Player; | ||
|
||
import javax.annotation.PostConstruct; | ||
import javax.inject.Inject; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import static fr.xephi.authme.settings.properties.EmailSettings.RECOVERY_PASSWORD_LENGTH; | ||
|
||
/** | ||
* Manager for password recovery. | ||
*/ | ||
public class PasswordRecoveryService implements Reloadable { | ||
|
||
@Inject | ||
private CommonService commonService; | ||
|
||
@Inject | ||
private RecoveryCodeService codeService; | ||
|
||
@Inject | ||
private DataSource dataSource; | ||
|
||
@Inject | ||
private EmailService emailService; | ||
|
||
@Inject | ||
private PasswordSecurity passwordSecurity; | ||
|
||
@Inject | ||
private RecoveryCodeService recoveryCodeService; | ||
|
||
@Inject | ||
private Messages messages; | ||
|
||
private ExpiringSet<String> emailCooldown; | ||
|
||
@PostConstruct | ||
private void initEmailCooldownSet() { | ||
emailCooldown = new ExpiringSet<>( | ||
commonService.getProperty(SecuritySettings.EMAIL_RECOVERY_COOLDOWN_SECONDS), TimeUnit.SECONDS); | ||
} | ||
|
||
/** | ||
* Create a new recovery code and send it to the player | ||
* via email. | ||
* | ||
* @param player The player getting the code. | ||
* @param email The email to send the code to. | ||
*/ | ||
public void createAndSendRecoveryCode(Player player, String email) { | ||
if (!checkEmailCooldown(player)) { | ||
return; | ||
} | ||
|
||
String recoveryCode = recoveryCodeService.generateCode(player.getName()); | ||
boolean couldSendMail = emailService.sendRecoveryCode(player.getName(), email, recoveryCode); | ||
if (couldSendMail) { | ||
commonService.send(player, MessageKey.RECOVERY_CODE_SENT); | ||
emailCooldown.add(player.getName().toLowerCase()); | ||
} else { | ||
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE); | ||
} | ||
} | ||
|
||
/** | ||
* Generate a new password and send it to the player via | ||
* email. This will update the database with the new password. | ||
* | ||
* @param player The player recovering their password. | ||
* @param email The email to send the password to. | ||
*/ | ||
public void generateAndSendNewPassword(Player player, String email) { | ||
if (!checkEmailCooldown(player)) { | ||
return; | ||
} | ||
|
||
String name = player.getName(); | ||
String thePass = RandomStringUtils.generate(commonService.getProperty(RECOVERY_PASSWORD_LENGTH)); | ||
HashedPassword hashNew = passwordSecurity.computeHash(thePass, name); | ||
|
||
dataSource.updatePassword(name, hashNew); | ||
boolean couldSendMail = emailService.sendPasswordMail(name, email, thePass); | ||
if (couldSendMail) { | ||
commonService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE); | ||
emailCooldown.add(player.getName().toLowerCase()); | ||
} else { | ||
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE); | ||
} | ||
} | ||
|
||
/** | ||
* Check if a player is able to have emails sent. | ||
* | ||
* @param player The player to check. | ||
* @return True if the player is not on cooldown. | ||
*/ | ||
public boolean checkEmailCooldown(Player player) { | ||
Duration waitDuration = emailCooldown.getExpiration(player.getName().toLowerCase()); | ||
if (waitDuration.getDuration() > 0) { | ||
String durationText = messages.formatDuration(waitDuration); | ||
messages.send(player, MessageKey.EMAIL_COOLDOWN_ERROR, durationText); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
@Override | ||
public void reload() { | ||
emailCooldown.setExpiration( | ||
commonService.getProperty(SecuritySettings.EMAIL_RECOVERY_COOLDOWN_SECONDS), TimeUnit.SECONDS); | ||
} | ||
} |
Oops, something went wrong.