2025-04-23 22:47:02 -04:00
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 = " <No default secret> " ;
private static final String DEFAULT_REDIRECT_URI = " mc.lilyvex.dev/oauth2 " ;
private static final String DEFAULT_DATABASE = " sqlite " ;
public 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 ;
2025-04-24 13:07:50 -04:00
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 ;
}
2025-04-23 22:47:02 -04:00
public void load ( ) {
2025-04-24 13:07:50 -04:00
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 ) ;
2025-04-23 22:47:02 -04:00
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. " ) ;
}
}
}