package dev.lilyvex.oauthfabric; import com.electronwill.nightconfig.core.CommentedConfig; import com.electronwill.nightconfig.core.io.ParsingException; import com.electronwill.nightconfig.core.io.ParsingMode; import com.electronwill.nightconfig.toml.TomlParser; import com.electronwill.nightconfig.toml.TomlWriter; import net.fabricmc.loader.api.FabricLoader; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OAuthFabricConfig { private static final Logger LOGGER = LoggerFactory.getLogger("oauth-fabric"); private static final String DEFAULT_PROVIDER = "auth.lilyvex.dev"; private static final String DEFAULT_CLIENT_ID = "minecraft"; private static final String DEFAULT_CLIENT_SECRET = ""; private static final String DEFAULT_REDIRECT_URI = "mc.lilyvex.dev/oauth2"; private static final String DEFAULT_DATABASE = "sqlite"; private static final Path CONFIG_FILE_PATH = FabricLoader.getInstance().getConfigDir() .resolve("oauth-fabric.toml") .normalize(); private final CommentedConfig config = CommentedConfig.inMemory(); // URL to the OAuth provider (e.g. accounts.google.com, discord.com/oauth2) private String provider; // ID of the OAuth client. This is usually defined when creating the OAuth application. private String client_id; // Client secret private String client_secret; // URI to redirect to. Ensure that this URI is listed in the allowed redirect URIs section // of your OAuth provider. private String redirect_uri; // Which database to use (SQLite is currently the only supported database). private String database; public String getProvider() { return provider; } public String getClientId() { return client_id; } public String getClientSecret() { return client_secret; } public String getRedirectUri() { return redirect_uri; } public String getDatabase() { return database; } public void load() { this.config.setComment("provider", "URL to the OAuth provider (e.g. accounts.google.com, discord.com/oauth2)"); this.config.set("provider", DEFAULT_PROVIDER); this.config.setComment("client_id", "ID of the OAuth client. This is usually defined when creating the OAuth application."); this.config.set("client_id", DEFAULT_CLIENT_ID); this.config.setComment("client_secret", ""); this.config.set("client_secret", DEFAULT_CLIENT_SECRET); this.config.setComment("redirect_uri", "URI to redirect to. Ensure that this URI is listed in the allowed redirect URIs section of your OAuth provider."); this.config.set("redirect_uri", DEFAULT_REDIRECT_URI); this.config.setComment("database", "Which database to use (SQLite is currently the only supported database)."); this.config.set("database", DEFAULT_DATABASE); try { this.loadFromFile(true); } catch (IOException e) { throw new RuntimeException(e); } LOGGER.info("oauth-fabric: Configuration loaded."); } private void loadFromFile(boolean firstAttempt) throws IOException { try (var reader = Files.newBufferedReader(CONFIG_FILE_PATH)) { new TomlParser().parse(reader, this.config, ParsingMode.REPLACE); } catch (NoSuchFileException | FileNotFoundException e) { if (!firstAttempt) { throw e; } this.copyDefaultFile(); this.loadFromFile(true); } catch (ParsingException e) { if (!firstAttempt) { throw e; } var backupPath = CONFIG_FILE_PATH.resolveSibling("oauth-fabric.toml.old").toAbsolutePath().normalize(); LOGGER.error("oauth-fabric: Failed to parse configuration file, THIS IS BAD.", e); LOGGER.error("oauth-fabric: Copying the corrupt file to \"{}\".", backupPath); Files.copy(CONFIG_FILE_PATH, backupPath, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); this.copyDefaultFile(); this.loadFromFile(false); } } private void copyDefaultFile() throws IOException { Files.createDirectories(CONFIG_FILE_PATH.getParent()); try (var writer = Files.newBufferedWriter(CONFIG_FILE_PATH, StandardCharsets.UTF_8)) { new TomlWriter().write(this.config.unmodifiable(), writer); } catch (NoSuchFileException | FileNotFoundException e) { LOGGER.error("oauth-fabric: Failed to write default configuration file."); } } }