Skip to content

Commit 2175b19

Browse files
committed
feat: Add OpeNLogin database converter
1 parent f8eed8c commit 2175b19

4 files changed

Lines changed: 158 additions & 1 deletion

File tree

authme-core/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import fr.xephi.authme.datasource.converter.LimboAuthConverter;
1212
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
1313
import fr.xephi.authme.datasource.converter.NLoginConverter;
14+
import fr.xephi.authme.datasource.converter.OpeNLoginConverter;
1415
import fr.xephi.authme.datasource.converter.SqliteToSql;
1516
import fr.xephi.authme.message.MessageKey;
1617
import fr.xephi.authme.output.ConsoleLoggerFactory;
@@ -84,6 +85,7 @@ private static Map<String, Class<? extends Converter>> getConverters() {
8485
.put("librelogin", LibreLoginConverter.class)
8586
.put("limboauth", LimboAuthConverter.class)
8687
.put("nlogin", NLoginConverter.class)
88+
.put("openlogin", OpeNLoginConverter.class)
8789
.put("sqlitetosql", SqliteToSql.class)
8890
.put("mysqltosqlite", MySqlToSqlite.class)
8991
.build();
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package fr.xephi.authme.datasource.converter;
2+
3+
import fr.xephi.authme.datasource.DataSource;
4+
5+
import java.io.File;
6+
import java.sql.Connection;
7+
import java.sql.DriverManager;
8+
import java.sql.SQLException;
9+
10+
/**
11+
* Base class for converters that read from an external plugin's SQLite database file.
12+
*/
13+
abstract class AbstractSqlitePluginConverter implements Converter {
14+
15+
private final DataSource dataSource;
16+
17+
AbstractSqlitePluginConverter(DataSource dataSource) {
18+
this.dataSource = dataSource;
19+
}
20+
21+
protected DataSource getDataSource() {
22+
return dataSource;
23+
}
24+
25+
/**
26+
* Opens a JDBC connection to the given SQLite database file.
27+
*
28+
* @param dbFile the SQLite database file
29+
* @return an open connection
30+
* @throws SQLException if the driver is unavailable or the connection cannot be established
31+
*/
32+
protected Connection openConnection(File dbFile) throws SQLException {
33+
try {
34+
Class.forName("org.sqlite.JDBC");
35+
} catch (ClassNotFoundException e) {
36+
throw new SQLException("SQLite JDBC driver not available", e);
37+
}
38+
return DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
39+
}
40+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package fr.xephi.authme.datasource.converter;
2+
3+
import fr.xephi.authme.ConsoleLogger;
4+
import fr.xephi.authme.data.auth.PlayerAuth;
5+
import fr.xephi.authme.datasource.DataSource;
6+
import fr.xephi.authme.output.ConsoleLoggerFactory;
7+
import fr.xephi.authme.security.crypts.HashedPassword;
8+
import org.bukkit.command.CommandSender;
9+
10+
import javax.inject.Inject;
11+
import java.io.File;
12+
import java.sql.Connection;
13+
import java.sql.PreparedStatement;
14+
import java.sql.ResultSet;
15+
import java.sql.SQLException;
16+
import java.util.Locale;
17+
18+
import static fr.xephi.authme.util.Utils.logAndSendMessage;
19+
20+
/**
21+
* Converts data from OpeNLogin to AuthMe.
22+
* <p>
23+
* OpeNLogin stores accounts in a SQLite file at {@code plugins/OpeNLogin/accounts.db}.
24+
* No shared database is required; the converter reads the file directly.
25+
* <p>
26+
* OpeNLogin uses BCrypt exclusively. Set {@code passwordHash} to {@code BCRYPT} in AuthMe's
27+
* {@code config.yml} before running the conversion.
28+
*/
29+
public class OpeNLoginConverter extends AbstractSqlitePluginConverter {
30+
31+
private static final String DB_PATH = "plugins/OpeNLogin/accounts.db";
32+
private static final String QUERY =
33+
"SELECT name, realname, password, address, lastlogin, regdate FROM openlogin";
34+
35+
private final ConsoleLogger logger = ConsoleLoggerFactory.get(OpeNLoginConverter.class);
36+
37+
@Inject
38+
OpeNLoginConverter(DataSource dataSource) {
39+
super(dataSource);
40+
}
41+
42+
@Override
43+
public void execute(CommandSender sender) {
44+
File dbFile = new File(DB_PATH);
45+
if (!dbFile.exists()) {
46+
logAndSendMessage(sender, "OpeNLogin conversion failed: database file not found at " + DB_PATH);
47+
return;
48+
}
49+
50+
try (Connection conn = openConnection(dbFile);
51+
PreparedStatement ps = conn.prepareStatement(QUERY);
52+
ResultSet rs = ps.executeQuery()) {
53+
54+
long imported = 0;
55+
long skipped = 0;
56+
while (rs.next()) {
57+
String name = rs.getString("name");
58+
if (name == null || name.isEmpty()) {
59+
continue;
60+
}
61+
name = name.toLowerCase(Locale.ROOT);
62+
63+
if (getDataSource().isAuthAvailable(name)) {
64+
++skipped;
65+
continue;
66+
}
67+
68+
String hash = rs.getString("password");
69+
if (hash == null || hash.isEmpty()) {
70+
logger.warning("No password for player '" + name + "', skipping");
71+
continue;
72+
}
73+
74+
String realName = rs.getString("realname");
75+
long lastLogin = rs.getLong("lastlogin");
76+
77+
PlayerAuth auth = PlayerAuth.builder()
78+
.name(name)
79+
.realName(realName != null && !realName.isEmpty() ? realName : name)
80+
.password(new HashedPassword(hash))
81+
.lastIp(rs.getString("address"))
82+
.registrationDate(rs.getLong("regdate"))
83+
.lastLogin(lastLogin > 0 ? lastLogin : null)
84+
.build();
85+
86+
getDataSource().saveAuth(auth);
87+
++imported;
88+
}
89+
90+
logAndSendMessage(sender, "OpeNLogin conversion: " + imported + " account(s) imported, "
91+
+ skipped + " skipped (already exist)");
92+
93+
} catch (SQLException e) {
94+
logAndSendMessage(sender, "OpeNLogin conversion failed: " + e.getMessage());
95+
logger.logException("OpeNLogin conversion error:", e);
96+
}
97+
}
98+
}

docs/converters.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Run a converter with `/authme converter <name>` (requires `authme.admin.converte
55

66
---
77

8-
AuthMeReloaded currently ships the **Auth+**, **LibreLogin**, **LimboAuth**, and **nLogin** converters, plus the built-in database migration helpers below.
8+
AuthMeReloaded currently ships the **Auth+**, **LibreLogin**, **LimboAuth**, **nLogin**, and **OpeNLogin** converters, plus the built-in database migration helpers below.
99

1010
---
1111

@@ -93,6 +93,23 @@ Migrates accounts from the **nLogin** plugin.
9393

9494
---
9595

96+
### OpeNLogin → `openlogin`
97+
98+
Migrates accounts from the **OpeNLogin** plugin.
99+
100+
**Requirement:** OpeNLogin must be (or have been) installed on the same server. The converter reads its SQLite database file directly — no shared database is required.
101+
102+
**Source file:** `plugins/OpeNLogin/accounts.db`
103+
104+
**Before running:**
105+
1. Set `passwordHash` to `BCRYPT` in AuthMe's `config.yml` — OpeNLogin uses BCrypt exclusively.
106+
107+
**Notes:**
108+
- OpeNLogin does not store email addresses or UUIDs; those fields will be empty for migrated accounts.
109+
- Players already present in AuthMe's database are skipped automatically.
110+
111+
---
112+
96113
### SQLite → SQL → `sqlitetosql`
97114

98115
Copies AuthMe data from a SQLite database into the configured SQL database.

0 commit comments

Comments
 (0)