forked from TuxCoding/FastLogin
Share the same force login mangement for less duplicate code
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
@@ -12,19 +13,20 @@ import java.sql.Statement;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class AuthStorage {
|
||||
|
||||
private static final String PREMIUM_TABLE = "premium";
|
||||
|
||||
private final FastLoginCore<?> core;
|
||||
private final FastLoginCore<?, ?, ?> core;
|
||||
private final HikariDataSource dataSource;
|
||||
|
||||
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||
private final Calendar calendar = Calendar.getInstance(Locale.US);
|
||||
|
||||
public AuthStorage(FastLoginCore<?> core, String driver, String host, int port, String databasePath
|
||||
public AuthStorage(FastLoginCore<?, ?, ?> core, String driver, String host, int port, String databasePath
|
||||
, String user, String pass) {
|
||||
this.core = core;
|
||||
|
||||
@@ -32,9 +34,20 @@ public class AuthStorage {
|
||||
databaseConfig.setUsername(user);
|
||||
databaseConfig.setPassword(pass);
|
||||
databaseConfig.setDriverClassName(driver);
|
||||
databaseConfig.setThreadFactory(core.getThreadFactory());
|
||||
|
||||
databasePath = databasePath.replace("{pluginDir}", core.getDataFolder().getAbsolutePath());
|
||||
ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder()
|
||||
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
|
||||
//Hikari create daemons by default
|
||||
.setDaemon(true);
|
||||
|
||||
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
|
||||
if (platformThreadFactory != null) {
|
||||
threadFactoryBuilder.setThreadFactory(platformThreadFactory);
|
||||
}
|
||||
|
||||
databaseConfig.setThreadFactory(threadFactoryBuilder.build());
|
||||
|
||||
databasePath = databasePath.replace("{pluginDir}", core.getPlugin().getDataFolder().getAbsolutePath());
|
||||
|
||||
String jdbcUrl = "jdbc:";
|
||||
if (driver.contains("sqlite")) {
|
||||
@@ -134,7 +147,7 @@ public class AuthStorage {
|
||||
return crackedProfile;
|
||||
}
|
||||
} catch (SQLException sqlEx) {
|
||||
core.getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
||||
} finally {
|
||||
closeQuietly(con);
|
||||
closeQuietly(loadStmt);
|
||||
@@ -165,7 +178,7 @@ public class AuthStorage {
|
||||
return playerProfile;
|
||||
}
|
||||
} catch (SQLException sqlEx) {
|
||||
core.getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
||||
} finally {
|
||||
closeQuietly(con);
|
||||
closeQuietly(loadStmt);
|
||||
@@ -226,7 +239,7 @@ public class AuthStorage {
|
||||
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
core.getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex);
|
||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex);
|
||||
} finally {
|
||||
closeQuietly(con);
|
||||
closeQuietly(updateStmt);
|
||||
@@ -246,7 +259,7 @@ public class AuthStorage {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (Exception closeEx) {
|
||||
core.getLogger().log(Level.SEVERE, "Failed to close connection", closeEx);
|
||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to close connection", closeEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,25 +12,31 @@ import com.github.games647.fastlogin.core.importer.Importer;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @param <P> Player class
|
||||
* @param <C> CommandSender
|
||||
* @param <T> Plugin class
|
||||
*/
|
||||
public abstract class FastLoginCore<P> {
|
||||
public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
|
||||
public static <K, V> ConcurrentMap<K, V> buildCache(int expireAfterWrite, int maxSize) {
|
||||
CompatibleCacheBuilder<Object, Object> builder = CompatibleCacheBuilder.newBuilder();
|
||||
@@ -64,21 +70,62 @@ public abstract class FastLoginCore<P> {
|
||||
|
||||
private final ConcurrentMap<String, Object> pendingLogins = FastLoginCore.buildCache(5, 0);
|
||||
private final Set<UUID> pendingConfirms = Sets.newHashSet();
|
||||
private final SharedConfig sharedConfig;
|
||||
private final T plugin;
|
||||
|
||||
private SharedConfig sharedConfig;
|
||||
private MojangApiConnector apiConnector;
|
||||
private AuthStorage storage;
|
||||
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
|
||||
private AuthPlugin<P> authPlugin;
|
||||
|
||||
public FastLoginCore(Map<String, Object> config) {
|
||||
this.sharedConfig = new SharedConfig(config);
|
||||
public FastLoginCore(T plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void setApiConnector() {
|
||||
|
||||
public void load() {
|
||||
saveDefaultFile("messages.yml");
|
||||
saveDefaultFile("config.yml");
|
||||
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("config.yml")));
|
||||
sharedConfig = new SharedConfig(plugin.loadYamlFile(reader));
|
||||
reader.close();
|
||||
|
||||
reader = Files.newBufferedReader(new File(plugin.getDataFolder(), "config.yml").toPath());
|
||||
sharedConfig.getConfigValues().putAll(plugin.loadYamlFile(reader));
|
||||
reader.close();
|
||||
|
||||
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("messages.yml")));
|
||||
reader = Files.newBufferedReader(new File(plugin.getDataFolder(), "messages.yml").toPath());
|
||||
Map<String, Object> messageConfig = plugin.loadYamlFile(reader);
|
||||
reader.close();
|
||||
|
||||
reader = Files.newBufferedReader(new File(plugin.getDataFolder(), "messages.yml").toPath());
|
||||
messageConfig.putAll(plugin.loadYamlFile(reader));
|
||||
for (Entry<String, Object> entry : messageConfig.entrySet()) {
|
||||
String message = plugin.translateColorCodes('&', (String) entry.getValue());
|
||||
if (!message.isEmpty()) {
|
||||
localeMessages.put(entry.getKey(), message);
|
||||
}
|
||||
}
|
||||
|
||||
reader.close();
|
||||
} catch (IOException ioEx) {
|
||||
plugin.getLogger().log(Level.INFO, "Failed to load yaml files", ioEx);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> ipAddresses = sharedConfig.get("ip-addresses");
|
||||
int requestLimit = sharedConfig.get("mojang-request-limit");
|
||||
this.apiConnector = makeApiConnector(getLogger(), ipAddresses, requestLimit);
|
||||
this.apiConnector = plugin.makeApiConnector(plugin.getLogger(), ipAddresses, requestLimit);
|
||||
}
|
||||
|
||||
public MojangApiConnector getApiConnector() {
|
||||
@@ -89,20 +136,21 @@ public abstract class FastLoginCore<P> {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public abstract File getDataFolder();
|
||||
public T getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public abstract Logger getLogger();
|
||||
|
||||
public abstract ThreadFactory getThreadFactory();
|
||||
public void sendLocaleMessage(String key, C receiver) {
|
||||
String message = localeMessages.get(key);
|
||||
if (message != null) {
|
||||
plugin.sendMessage(receiver, message);
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage(String key) {
|
||||
return localeMessages.get(key);
|
||||
}
|
||||
|
||||
public abstract void loadMessages();
|
||||
|
||||
public abstract MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests);
|
||||
|
||||
public boolean setupDatabase() {
|
||||
String driver = sharedConfig.get("driver");
|
||||
String host = sharedConfig.get("host", "");
|
||||
@@ -117,27 +165,27 @@ public abstract class FastLoginCore<P> {
|
||||
storage.createTables();
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
getLogger().log(Level.SEVERE, "Failed to setup database. Disabling plugin...", ex);
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to setup database. Disabling plugin...", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean importDatabase(ImportPlugin plugin, boolean sqlite, AuthStorage storage, String host, String database
|
||||
public boolean importDatabase(ImportPlugin importPlugin, boolean sqlite, AuthStorage storage, String host, String database
|
||||
, String username, String pass) {
|
||||
if (sqlite && (plugin == ImportPlugin.BPA || plugin == ImportPlugin.ELDZI)) {
|
||||
if (sqlite && (importPlugin == ImportPlugin.BPA || importPlugin == ImportPlugin.ELDZI)) {
|
||||
throw new IllegalArgumentException("These plugins doesn't support flat file databases");
|
||||
}
|
||||
|
||||
Importer importer;
|
||||
try {
|
||||
importer = plugin.getImporter().newInstance();
|
||||
importer = importPlugin.getImporter().newInstance();
|
||||
} catch (Exception ex) {
|
||||
getLogger().log(Level.SEVERE, "Couldn't not setup importer class", ex);
|
||||
plugin.getLogger().log(Level.SEVERE, "Couldn't not setup importer class", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (sqlite && plugin == ImportPlugin.AUTO_IN) {
|
||||
if (sqlite && importPlugin == ImportPlugin.AUTO_IN) {
|
||||
//load sqlite driver
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
|
||||
@@ -154,9 +202,9 @@ public abstract class FastLoginCore<P> {
|
||||
return true;
|
||||
}
|
||||
} catch (ClassNotFoundException ex) {
|
||||
getLogger().log(Level.SEVERE, "Cannot find SQL driver. Do you removed it?", ex);
|
||||
plugin.getLogger().log(Level.SEVERE, "Cannot find SQL driver. Do you removed it?", ex);
|
||||
} catch (SQLException ex) {
|
||||
getLogger().log(Level.SEVERE, "Couldn't import data. Aborting...", ex);
|
||||
plugin.getLogger().log(Level.SEVERE, "Couldn't import data. Aborting...", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -190,6 +238,28 @@ public abstract class FastLoginCore<P> {
|
||||
this.authPlugin = authPlugin;
|
||||
}
|
||||
|
||||
public void saveDefaultFile(String fileName) {
|
||||
if (!plugin.getDataFolder().exists()) {
|
||||
plugin.getDataFolder().mkdir();
|
||||
}
|
||||
|
||||
File configFile = new File(plugin.getDataFolder(), fileName);
|
||||
if (!configFile.exists()) {
|
||||
InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
|
||||
try {
|
||||
Files.copy(in, configFile.toPath());
|
||||
} catch (IOException ioExc) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error saving default " + fileName, ioExc);
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (storage != null) {
|
||||
storage.close();
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import com.github.games647.fastlogin.core.AuthStorage;
|
||||
import com.github.games647.fastlogin.core.PlayerProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public abstract class ForceLoginMangement<P extends C, C, L extends LoginSession, T extends PlatformPlugin<C>>
|
||||
implements Runnable {
|
||||
|
||||
protected final FastLoginCore<P, C, T> core;
|
||||
protected final P player;
|
||||
|
||||
protected L session;
|
||||
|
||||
public ForceLoginMangement(FastLoginCore<P, C, T> core, P player) {
|
||||
this.core = core;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isOnline(player) || session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AuthStorage storage = core.getStorage();
|
||||
|
||||
PlayerProfile playerProfile = session.getProfile();
|
||||
try {
|
||||
if (isOnlineMode()) {
|
||||
//premium player
|
||||
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
|
||||
if (authPlugin == null) {
|
||||
//maybe only bungeecord plugin
|
||||
onForceActionSuccess(session);
|
||||
} else {
|
||||
boolean success = false;
|
||||
if (isOnline(player)) {
|
||||
if (core.getConfig().get("autoLogin", true)) {
|
||||
if (session.needsRegistration()) {
|
||||
success = forceRegister(player);
|
||||
} else {
|
||||
success = forceLogin(player);
|
||||
}
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
//update only on success to prevent corrupt data
|
||||
if (playerProfile != null) {
|
||||
playerProfile.setUuid(session.getUuid());
|
||||
//save cracked players too
|
||||
playerProfile.setPremium(true);
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
|
||||
onForceActionSuccess(session);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//cracked player
|
||||
if (playerProfile != null) {
|
||||
playerProfile.setUuid(null);
|
||||
playerProfile.setPremium(false);
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
core.getPlugin().getLogger().log(Level.INFO, "ERROR ON FORCE LOGIN", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean forceRegister(P player) {
|
||||
core.getPlugin().getLogger().log(Level.FINE, "Register player {0}", getName(player));
|
||||
|
||||
String generatedPassword = core.getPasswordGenerator().getRandomPassword(player);
|
||||
boolean success = core.getAuthPluginHook().forceRegister(player, generatedPassword);
|
||||
|
||||
String message = core.getMessage("auto-register");
|
||||
if (success && message != null) {
|
||||
message = message.replace("%password", generatedPassword);
|
||||
core.getPlugin().sendMessage(player, message);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean forceLogin(P player) {
|
||||
core.getPlugin().getLogger().log(Level.FINE, "Logging player {0} in", getName(player));
|
||||
boolean success = core.getAuthPluginHook().forceLogin(player);
|
||||
|
||||
if (success) {
|
||||
core.sendLocaleMessage("auto-login", player);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public abstract void onForceActionSuccess(LoginSession session);
|
||||
|
||||
public abstract String getName(P player);
|
||||
|
||||
public abstract boolean isOnline(P player);
|
||||
|
||||
public abstract boolean isOnlineMode();
|
||||
}
|
||||
@@ -7,12 +7,12 @@ import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public abstract class JoinManagement<T, S extends LoginSource> {
|
||||
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
|
||||
protected final FastLoginCore<T> core;
|
||||
protected final AuthPlugin<T> authHook;
|
||||
protected final FastLoginCore<P, C, ?> core;
|
||||
protected final AuthPlugin<P> authHook;
|
||||
|
||||
public JoinManagement(FastLoginCore<T> core, AuthPlugin<T> authHook) {
|
||||
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
|
||||
this.core = core;
|
||||
this.authHook = authHook;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
|
||||
try {
|
||||
if (profile.getUserId() == -1) {
|
||||
if (core.getPendingLogins().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
|
||||
core.getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
|
||||
core.getPlugin().getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
|
||||
|
||||
//first login request failed so make a cracked session
|
||||
startCrackedSession(source, profile, username);
|
||||
@@ -39,7 +39,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
|
||||
|
||||
UUID premiumUUID = null;
|
||||
if (config.get("nameChangeCheck", false) || config.get("autoRegister", false)) {
|
||||
core.getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
|
||||
core.getPlugin().getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
|
||||
premiumUUID = core.getApiConnector().getPremiumUUID(username);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
|
||||
startCrackedSession(source, profile, username);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
core.getLogger().log(Level.SEVERE, "Failed to check premium state", ex);
|
||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to check premium state", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
|
||||
PlayerProfile profile = core.getStorage().loadProfile(premiumUUID);
|
||||
if (profile != null) {
|
||||
//uuid exists in the database
|
||||
core.getLogger().log(Level.FINER, "Player {0} changed it's username", premiumUUID);
|
||||
core.getPlugin().getLogger().log(Level.FINER, "Player {0} changed it's username", premiumUUID);
|
||||
|
||||
//update the username to the new one in the database
|
||||
profile.setPlayerName(username);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public interface PlatformPlugin<C> {
|
||||
|
||||
String getName();
|
||||
|
||||
File getDataFolder();
|
||||
|
||||
Logger getLogger();
|
||||
|
||||
Map<String, Object> loadYamlFile(Reader reader);
|
||||
|
||||
void sendMessage(C receiver, String message);
|
||||
|
||||
ThreadFactory getThreadFactory();
|
||||
|
||||
String translateColorCodes(char colorChar, String rawMessage);
|
||||
|
||||
MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests);
|
||||
}
|
||||
Reference in New Issue
Block a user