#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
@@ -10,6 +10,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.EmailRecoveryData;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -242,9 +243,8 @@ public class CacheDataSource implements DataSource {
}
@Override
public String getRecoveryCode(String name) {
// TODO #472: can probably get it from the cached Auth?
return source.getRecoveryCode(name);
public EmailRecoveryData getEmailRecoveryData(String name) {
return source.getEmailRecoveryData(name);
}
@Override
@@ -1,5 +1,6 @@
package fr.xephi.authme.datasource;
import fr.xephi.authme.cache.auth.EmailRecoveryData;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.initialization.Reloadable;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -204,12 +205,12 @@ public interface DataSource extends Reloadable {
void setRecoveryCode(String name, String code, long expiration);
/**
* Get the recovery code of a user if available and not yet expired.
* Get the information necessary for performing a password recovery by email.
*
* @param name The name of the user
* @return The recovery code, or null if no current code available
* @return The data of the player, or null if player doesn't exist
*/
String getRecoveryCode(String name);
EmailRecoveryData getEmailRecoveryData(String name);
/**
* Remove the recovery code of a given user.
@@ -1,6 +1,7 @@
package fr.xephi.authme.datasource;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.EmailRecoveryData;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -474,7 +475,7 @@ public class FlatFile implements DataSource {
}
@Override
public String getRecoveryCode(String name) {
public EmailRecoveryData getEmailRecoveryData(String name) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@@ -4,6 +4,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.EmailRecoveryData;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -881,15 +882,16 @@ public class MySQL implements DataSource {
}
@Override
public String getRecoveryCode(String name) {
String sql = "SELECT " + col.RECOVERY_CODE + " FROM " + tableName
+ " WHERE " + col.NAME + " = ? AND " + col.RECOVERY_EXPIRATION + " > ?;";
public EmailRecoveryData getEmailRecoveryData(String name) {
String sql = "SELECT " + col.EMAIL + ", " + col.RECOVERY_CODE + ", " + col.RECOVERY_EXPIRATION
+ " FROM " + tableName
+ " WHERE " + col.NAME + " = ?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, name.toLowerCase());
pst.setLong(2, System.currentTimeMillis());
try (ResultSet rs = pst.executeQuery()) {
if (rs.next()) {
return rs.getString(1);
return new EmailRecoveryData(
rs.getString(col.EMAIL), rs.getString(col.RECOVERY_CODE), rs.getLong(col.RECOVERY_EXPIRATION));
}
}
} catch (SQLException e) {
@@ -2,6 +2,7 @@ package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.EmailRecoveryData;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
@@ -611,15 +612,16 @@ public class SQLite implements DataSource {
}
@Override
public String getRecoveryCode(String name) {
String sql = "SELECT " + col.RECOVERY_CODE + " FROM " + tableName
+ " WHERE " + col.NAME + " = ? AND " + col.RECOVERY_EXPIRATION + " > ?;";
public EmailRecoveryData getEmailRecoveryData(String name) {
String sql = "SELECT " + col.EMAIL + ", " + col.RECOVERY_CODE + ", " + col.RECOVERY_EXPIRATION
+ " FROM " + tableName
+ " WHERE " + col.NAME + " = ?;";
try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, name.toLowerCase());
pst.setLong(2, System.currentTimeMillis());
try (ResultSet rs = pst.executeQuery()) {
if (rs.next()) {
return rs.getString(1);
return new EmailRecoveryData(
rs.getString(col.EMAIL), rs.getString(col.RECOVERY_CODE), rs.getLong(col.RECOVERY_EXPIRATION));
}
}
} catch (SQLException e) {