#1023 Create LoginSecurity converter
This commit is contained in:
parent
a0fbb6a78a
commit
2021113732
@ -316,7 +316,7 @@ public class CommandInitializer {
|
|||||||
.description("Converter command")
|
.description("Converter command")
|
||||||
.detailedDescription("Converter command for AuthMeReloaded.")
|
.detailedDescription("Converter command for AuthMeReloaded.")
|
||||||
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / "
|
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / "
|
||||||
+ "royalauth / vauth / sqliteToSql / mysqlToSqlite", false)
|
+ "royalauth / vauth / sqliteToSql / mysqlToSqlite / loginsecurity", false)
|
||||||
.permission(AdminPermission.CONVERTER)
|
.permission(AdminPermission.CONVERTER)
|
||||||
.executableCommand(ConverterCommand.class)
|
.executableCommand(ConverterCommand.class)
|
||||||
.register();
|
.register();
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.converter.Converter;
|
import fr.xephi.authme.datasource.converter.Converter;
|
||||||
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
||||||
|
import fr.xephi.authme.datasource.converter.LoginSecurityConverter;
|
||||||
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
|
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
|
||||||
import fr.xephi.authme.datasource.converter.RakamakConverter;
|
import fr.xephi.authme.datasource.converter.RakamakConverter;
|
||||||
import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
||||||
@ -85,6 +86,7 @@ public class ConverterCommand implements ExecutableCommand {
|
|||||||
.put("vauth", VAuthConverter.class)
|
.put("vauth", VAuthConverter.class)
|
||||||
.put("sqlitetosql", SqliteToSql.class)
|
.put("sqlitetosql", SqliteToSql.class)
|
||||||
.put("mysqltosqlite", MySqlToSqlite.class)
|
.put("mysqltosqlite", MySqlToSqlite.class)
|
||||||
|
.put("loginsecurity", LoginSecurityConverter.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,162 @@
|
|||||||
|
package fr.xephi.authme.datasource.converter;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.ConverterSettings;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.util.Utils.logAndSendMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts data from LoginSecurity to AuthMe.
|
||||||
|
*/
|
||||||
|
public class LoginSecurityConverter implements Converter {
|
||||||
|
|
||||||
|
private final File dataFolder;
|
||||||
|
private final DataSource dataSource;
|
||||||
|
|
||||||
|
private final boolean useSqlite;
|
||||||
|
private final String mySqlHost;
|
||||||
|
private final String mySqlDatabase;
|
||||||
|
private final String mySqlUser;
|
||||||
|
private final String mySqlPassword;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LoginSecurityConverter(@DataFolder File dataFolder, DataSource dataSource, Settings settings) {
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
|
||||||
|
useSqlite = settings.getProperty(ConverterSettings.LOGINSECURITY_USE_SQLITE);
|
||||||
|
mySqlHost = settings.getProperty(ConverterSettings.LOGINSECURITY_MYSQL_HOST);
|
||||||
|
mySqlDatabase = settings.getProperty(ConverterSettings.LOGINSECURITY_MYSQL_DATABASE);
|
||||||
|
mySqlUser = settings.getProperty(ConverterSettings.LOGINSECURITY_MYSQL_USER);
|
||||||
|
mySqlPassword = settings.getProperty(ConverterSettings.LOGINSECURITY_MYSQL_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandSender sender) {
|
||||||
|
try (Connection connection = createConnectionOrInformSender(sender)) {
|
||||||
|
if (connection != null) {
|
||||||
|
performConversion(sender, connection);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
sender.sendMessage("Failed to convert from SQLite. Please see the log for more info");
|
||||||
|
ConsoleLogger.logException("Could not fetch or migrate data:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void performConversion(CommandSender sender, Connection connection) throws SQLException {
|
||||||
|
try (Statement statement = connection.createStatement()) {
|
||||||
|
statement.execute(
|
||||||
|
"SELECT * from ls_players LEFT JOIN ls_locations ON ls_locations.id = ls_players.id");
|
||||||
|
try (ResultSet resultSet = statement.getResultSet()) {
|
||||||
|
migrateData(sender, resultSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void migrateData(CommandSender sender, ResultSet resultSet) throws SQLException {
|
||||||
|
List<String> skippedPlayers = new ArrayList<>();
|
||||||
|
long successfulSaves = 0;
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String name = resultSet.getString("last_name");
|
||||||
|
if (dataSource.isAuthAvailable(name)) {
|
||||||
|
skippedPlayers.add(name);
|
||||||
|
} else {
|
||||||
|
PlayerAuth auth = buildAuthFromLoginSecurity(name, resultSet);
|
||||||
|
dataSource.saveAuth(auth);
|
||||||
|
++successfulSaves;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logAndSendMessage(sender, "Migrated " + successfulSaves + " accounts successfully from LoginSecurity");
|
||||||
|
if (!skippedPlayers.isEmpty()) {
|
||||||
|
logAndSendMessage(sender, "Skipped conversion for players which were already in AuthMe: "
|
||||||
|
+ String.join(", ", skippedPlayers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlayerAuth buildAuthFromLoginSecurity(String name, ResultSet resultSet) throws SQLException {
|
||||||
|
return PlayerAuth.builder()
|
||||||
|
.name(name)
|
||||||
|
.realName(name)
|
||||||
|
.password(resultSet.getString("password"), null)
|
||||||
|
.ip(resultSet.getString("ip_address"))
|
||||||
|
.lastLogin(resultSet.getLong("last_login"))
|
||||||
|
// TODO #792: Register date
|
||||||
|
.locX(resultSet.getDouble("x"))
|
||||||
|
.locY(resultSet.getDouble("y"))
|
||||||
|
.locZ(resultSet.getDouble("z"))
|
||||||
|
.locWorld(resultSet.getString("world"))
|
||||||
|
.locYaw(resultSet.getFloat("yaw"))
|
||||||
|
.locPitch(resultSet.getFloat("pitch"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Connection createConnectionOrInformSender(CommandSender sender) {
|
||||||
|
Connection connection;
|
||||||
|
if (useSqlite) {
|
||||||
|
File sqliteDatabase = new File(dataFolder.getParentFile(), "LoginSecurity/LoginSecurity.db");
|
||||||
|
if (!sqliteDatabase.exists()) {
|
||||||
|
sender.sendMessage("The file '" + sqliteDatabase.getPath() + "' does not exist");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
connection = createSqliteConnection("plugins/LoginSecurity/LoginSecurity.db");
|
||||||
|
} else {
|
||||||
|
if (mySqlDatabase.isEmpty() || mySqlUser.isEmpty()) {
|
||||||
|
sender.sendMessage("The LoginSecurity database or username is not configured in AuthMe's config.yml");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
connection = createMySqlConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection == null) {
|
||||||
|
sender.sendMessage("Could not connect to LoginSecurity using Sqlite = "
|
||||||
|
+ useSqlite + ", see log for more info");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Connection createSqliteConnection(String path) {
|
||||||
|
try {
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return DriverManager.getConnection(
|
||||||
|
"jdbc:sqlite:" + path, "trump", "donald");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
ConsoleLogger.logException("Could not connect to SQLite database", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Connection createMySqlConnection() {
|
||||||
|
try {
|
||||||
|
return DriverManager.getConnection(
|
||||||
|
"jdbc:mysql://" + mySqlHost + "/" + mySqlDatabase, mySqlUser, mySqlPassword);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
ConsoleLogger.logException("Could not connect to SQLite database", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,6 +24,26 @@ public final class ConverterSettings implements SettingsHolder {
|
|||||||
public static final Property<String> CRAZYLOGIN_FILE_NAME =
|
public static final Property<String> CRAZYLOGIN_FILE_NAME =
|
||||||
newProperty("Converter.CrazyLogin.fileName", "accounts.db");
|
newProperty("Converter.CrazyLogin.fileName", "accounts.db");
|
||||||
|
|
||||||
|
@Comment("LoginSecurity: convert from SQLite; if false we use MySQL")
|
||||||
|
public static final Property<Boolean> LOGINSECURITY_USE_SQLITE =
|
||||||
|
newProperty("Converter.loginSecurity.useSqlite", true);
|
||||||
|
|
||||||
|
@Comment("LoginSecurity MySQL: database host")
|
||||||
|
public static final Property<String> LOGINSECURITY_MYSQL_HOST =
|
||||||
|
newProperty("Converter.loginSecurity.mySql.host", "");
|
||||||
|
|
||||||
|
@Comment("LoginSecurity MySQL: database name")
|
||||||
|
public static final Property<String> LOGINSECURITY_MYSQL_DATABASE =
|
||||||
|
newProperty("Converter.loginSecurity.mySql.database", "");
|
||||||
|
|
||||||
|
@Comment("LoginSecurity MySQL: database user")
|
||||||
|
public static final Property<String> LOGINSECURITY_MYSQL_USER =
|
||||||
|
newProperty("Converter.loginSecurity.mySql.user", "");
|
||||||
|
|
||||||
|
@Comment("LoginSecurity MySQL: password for database user")
|
||||||
|
public static final Property<String> LOGINSECURITY_MYSQL_PASSWORD =
|
||||||
|
newProperty("Converter.loginSecurity.mySql.password", "");
|
||||||
|
|
||||||
private ConverterSettings() {
|
private ConverterSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@ public final class TestHelper {
|
|||||||
|
|
||||||
public static final String SOURCES_FOLDER = "src/main/java/";
|
public static final String SOURCES_FOLDER = "src/main/java/";
|
||||||
public static final String TEST_SOURCES_FOLDER = "src/test/java/";
|
public static final String TEST_SOURCES_FOLDER = "src/test/java/";
|
||||||
|
public static final String TEST_RESOURCES_FOLDER = "src/test/resources/";
|
||||||
public static final String PROJECT_ROOT = "/fr/xephi/authme/";
|
public static final String PROJECT_ROOT = "/fr/xephi/authme/";
|
||||||
|
|
||||||
private TestHelper() {
|
private TestHelper() {
|
||||||
|
|||||||
@ -0,0 +1,79 @@
|
|||||||
|
package fr.xephi.authme.datasource.converter;
|
||||||
|
|
||||||
|
import ch.jalu.injector.testing.BeforeInjecting;
|
||||||
|
import ch.jalu.injector.testing.DelayedInjectionRunner;
|
||||||
|
import ch.jalu.injector.testing.InjectDelayed;
|
||||||
|
import fr.xephi.authme.TestHelper;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.ConverterSettings;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.AuthMeMatchers.equalToHash;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link LoginSecurityConverter}.
|
||||||
|
*/
|
||||||
|
@RunWith(DelayedInjectionRunner.class)
|
||||||
|
public class LoginSecurityConverterTest {
|
||||||
|
|
||||||
|
@InjectDelayed
|
||||||
|
private LoginSecurityConverter converter;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DataSource dataSource;
|
||||||
|
@Mock
|
||||||
|
private Settings settings;
|
||||||
|
@DataFolder
|
||||||
|
private File dataFolder = new File("."); // not used but required for injection
|
||||||
|
|
||||||
|
@BeforeInjecting
|
||||||
|
public void initMocks() {
|
||||||
|
TestHelper.setupLogger();
|
||||||
|
given(settings.getProperty(ConverterSettings.LOGINSECURITY_USE_SQLITE)).willReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldConvertFromSqlite() throws SQLException {
|
||||||
|
// given
|
||||||
|
Connection connection = converter.createSqliteConnection(
|
||||||
|
TestHelper.TEST_RESOURCES_FOLDER + TestHelper.PROJECT_ROOT + "datasource/converter/LoginSecurity.db");
|
||||||
|
CommandSender sender = mock(CommandSender.class);
|
||||||
|
|
||||||
|
// when
|
||||||
|
converter.performConversion(sender, connection);
|
||||||
|
|
||||||
|
// then
|
||||||
|
ArgumentCaptor<PlayerAuth> captor = ArgumentCaptor.forClass(PlayerAuth.class);
|
||||||
|
verify(dataSource, times(3)).saveAuth(captor.capture());
|
||||||
|
assertThat(captor.getAllValues().get(0).getNickname(), equalTo("player1"));
|
||||||
|
assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1"));
|
||||||
|
assertThat(captor.getAllValues().get(0).getLastLogin(), equalTo(1494242093652L));
|
||||||
|
assertThat(captor.getAllValues().get(0).getPassword(), equalToHash("$2a$10$E1Ri7XKeIIBv4qVaiPplgepT7QH9xGFh3hbHfcmCjq7hiW.UBTiGK"));
|
||||||
|
assertThat(captor.getAllValues().get(0).getIp(), equalTo("127.0.0.1"));
|
||||||
|
|
||||||
|
assertThat(captor.getAllValues().get(1).getNickname(), equalTo("player2"));
|
||||||
|
assertThat(captor.getAllValues().get(1).getLastLogin(), equalTo(1494242174589L));
|
||||||
|
assertThat(captor.getAllValues().get(1).getIp(), equalTo("127.4.5.6"));
|
||||||
|
|
||||||
|
assertThat(captor.getAllValues().get(2).getRealName(), equalTo("Player3"));
|
||||||
|
assertThat(captor.getAllValues().get(2).getPassword(), equalToHash("$2a$10$WFui8KSXMLDOVXKFpCLyPukPi4M82w1cv/rNojsAnwJjba3pp8sba"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user