Compare commits

...

5 commits

Author SHA1 Message Date
9283b9e925
fix: create database in main class
All checks were successful
build / build (push) Successful in 1m35s
2025-04-25 20:13:25 -04:00
e0f3d7e914
feat: sqlite database support and generic database class 2025-04-25 20:06:37 -04:00
f93f21d2c6
fix: use correct visibility for CONFIG_FILE_PATH 2025-04-25 19:22:47 -04:00
147c8fe3af
feat: add basic database interface 2025-04-25 19:20:33 -04:00
3d9cfa0207
chore: add usage sections and notes to README.md 2025-04-25 19:16:49 -04:00
6 changed files with 278 additions and 3 deletions

View file

@ -7,9 +7,32 @@
</div> </div>
<hr> <hr>
> [!NOTE]
> Support for other mod loaders is not planned. PRs implementing such support will not be accepted, please fork this project instead.
> [!WARNING]
> This mod does not provide support for standard permission systems, and by default only verifies permissions by operator status (i.e. commands can only be run by operators).
## Supported versions
| Version | Support level |
| ------- | ------------- |
| 1.20.1 | ✅ Fully supported |
| * | ❌ Not supported |
## Installing ## Installing
Download the latest release from the releases tab or go to the [latest release directly](https://code.lilyvex.dev/lily/oauth-fabric/releases/latest), then put it in your Fabric server's `mods` directory. Download the latest release from the releases tab or go to the [latest release directly](https://code.lilyvex.dev/lily/oauth-fabric/releases/latest), you may optionally choose to build from source, then put it in your Fabric server's `mods` directory.
## Usage
On initial load, this mod will create a commented configuration file. Edit the created file to contain the correct credentials for your OAuth provider, then restart the server.
Players who are not registered will be kicked on join and given a link to the OAuth provider, where they can login to register for the server.
Each new login with create a new session which will expire after a set period of time (usually defined by your OAuth provider).
Use the `/oauth` command to see a list of all available commands.
## Building from source ## Building from source
@ -30,4 +53,4 @@ gradlew.bat build
## Contributing ## Contributing
Fork this repository and create a branch for your changes, then create a pull request for the `main` branch with a "why", "what", and "how" to explain your changes. Fork this repository and create a branch for your changes, then create a pull request for the `dev` branch with a "why", "what", and "how" to explain your changes.

View file

@ -5,6 +5,8 @@ import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import dev.lilyvex.oauthfabric.database.Database;
public class OAuthFabric implements ModInitializer { public class OAuthFabric implements ModInitializer {
public static final String MOD_ID = "oauth-fabric"; public static final String MOD_ID = "oauth-fabric";
@ -21,6 +23,9 @@ public class OAuthFabric implements ModInitializer {
OAuthFabricConfig oAuthFabricConfig = new OAuthFabricConfig(); OAuthFabricConfig oAuthFabricConfig = new OAuthFabricConfig();
oAuthFabricConfig.load(); oAuthFabricConfig.load();
Database database = new Database();
database.setDatabase(oAuthFabricConfig.getDatabase());
LOGGER.info("oauth-fabric: Initialized"); LOGGER.info("oauth-fabric: Initialized");
} }

View file

@ -27,7 +27,7 @@ public class OAuthFabricConfig {
private static final String DEFAULT_REDIRECT_URI = "mc.lilyvex.dev/oauth2"; private static final String DEFAULT_REDIRECT_URI = "mc.lilyvex.dev/oauth2";
private static final String DEFAULT_DATABASE = "sqlite"; private static final String DEFAULT_DATABASE = "sqlite";
public static final Path CONFIG_FILE_PATH = FabricLoader.getInstance().getConfigDir() private static final Path CONFIG_FILE_PATH = FabricLoader.getInstance().getConfigDir()
.resolve("oauth-fabric.toml") .resolve("oauth-fabric.toml")
.normalize(); .normalize();

View file

@ -0,0 +1,36 @@
package dev.lilyvex.oauthfabric.database;
public class Database implements IDatabase {
private IDatabase databaseClass;
public void setDatabase(String database) {
switch (database) {
case "sqlite":
databaseClass = new SQLite();
}
}
public void addUser(String uuid, String oauthId, String sessionToken) {
databaseClass.addUser(uuid, oauthId, sessionToken);
}
public void updateUser(String uuid, String oauthId, String sessionToken) {
databaseClass.updateUser(uuid, oauthId, sessionToken);
}
public void removeUser(String uuid) {
databaseClass.removeUser(uuid);
}
public boolean isRegisteredUser(String uuid) {
return databaseClass.isRegisteredUser(uuid);
}
public String getOauthId(String uuid) {
return databaseClass.getOauthId(uuid);
}
public String getSessionToken(String uuid) {
return databaseClass.getSessionToken(uuid);
}
}

View file

@ -0,0 +1,11 @@
package dev.lilyvex.oauthfabric.database;
public interface IDatabase {
public void addUser(String uuid, String oauthId, String sessionToken);
public void updateUser(String uuid, String oauthId, String sessionToken);
public void removeUser(String uuid);
public boolean isRegisteredUser(String uuid);
public String getOauthId(String uuid);
public String getSessionToken(String uuid);
}

View file

@ -0,0 +1,200 @@
package dev.lilyvex.oauthfabric.database;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loader.api.FabricLoader;
public class SQLite implements IDatabase {
private static final Logger LOGGER = LoggerFactory.getLogger("oauth-fabric");
private static final Path DATABASE_PATH = FabricLoader.getInstance().getConfigDir()
.resolve("oauth-fabric.db")
.normalize();
private static final String databaseUrl = "jdbc:sqlite:" + DATABASE_PATH;
private Connection connection = null;
private void createDatabase() throws SQLException {
try {
connection = DriverManager.getConnection(databaseUrl);
Statement statement = connection.createStatement();
statement.executeUpdate("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
uuid TEXT UNIQUE,
oauth_id TEXT UNIQUE,
session_token TEXT UNIQUE
)
""");
} catch (SQLException e) {
LOGGER.error("oauth-fabric: Unable to create SQLite database");
} finally {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
LOGGER.error("oauth-fabric: Could not close SQLite connection");
}
}
}
public void addUser(String uuid, String oauthId, String sessionToken) {
try {
createDatabase();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
connection = DriverManager.getConnection(databaseUrl);
PreparedStatement statement = connection.prepareStatement("""
INSERT INTO users (
uuid,
oauth_id,
session_token
) VALUES (
?,
?,
?
)
""");
statement.setString(1, uuid);
statement.setString(2, oauthId);
statement.setString(3, sessionToken);
statement.executeQuery();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void updateUser(String uuid, String oauthId, String sessionToken) {
try {
createDatabase();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
connection = DriverManager.getConnection(databaseUrl);
PreparedStatement statement = connection.prepareStatement("UPDATE users SET oauth_id = ?, session_token = ? WHERE uuid = ?");
statement.setString(1, oauthId);
statement.setString(2, sessionToken);
statement.setString(3, uuid);
statement.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void removeUser(String uuid) {
try {
createDatabase();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
connection = DriverManager.getConnection(databaseUrl);
PreparedStatement statement = connection.prepareStatement("DELETE FROM users WHERE uuid = ?");
statement.setString(1, uuid);
statement.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public boolean isRegisteredUser(String uuid) {
try {
createDatabase();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
connection = DriverManager.getConnection(databaseUrl);
PreparedStatement statement = connection.prepareStatement("SELECT * FROM users WHERE uuid = ?");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
int results = 0;
while (resultSet.next()) {
results++;
}
if (results > 0) {
return true;
}
return false;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public String getOauthId(String uuid) {
try {
createDatabase();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
connection = DriverManager.getConnection(databaseUrl);
PreparedStatement statement = connection.prepareStatement("SELECT * FROM users WHERE uuid = ?");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
String userOauthId = "";
while (resultSet.next()) {
userOauthId = resultSet.getString("oauth_id");
}
return userOauthId;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public String getSessionToken(String uuid) {
try {
createDatabase();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
connection = DriverManager.getConnection(databaseUrl);
PreparedStatement statement = connection.prepareStatement("SELECT * FROM users WHERE uuid = ?");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
String userSessionToken = "";
while (resultSet.next()) {
userSessionToken = resultSet.getString("session_token");
}
return userSessionToken;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}