Compare commits

...
5 Commits
Author SHA1 Message Date
Michael Burgess 6f74026514 Use raw JDBC parameter string instead of ssl boolean flag
build / build (push) Failing after 14s
2026-08-06 19:45:09 -04:00
Andreas Troelsen eb77193fbd Release 1.0. 2022-07-30 15:58:05 +02:00
Andreas Troelsen 2c65d88c62 Link to releases/actions in README.
After the first release we should be able to link to the `/latest` URL
just fine, so we'll just prep it now. We don't really want to maintain
an "official" test builds channel on Discord, so that's out as well.
2022-07-30 15:58:05 +02:00
Andreas Troelsen 627205d39a Qualify getTables() with catalog and schema.
Without these qualifiers, the tables returned by the metadata object
will include tables from _all_ databases in the database instance, which
is definitely not something we want. Not only does this pose a potential
performance impact, it can also return very false positives, which then
result in an (inaptly named) SQLSyntaxErrorException when the subsequent
query to the potentially non-existent table fails.

To reproduce the issue:

- Create two new, empty databases in a fresh MySQL/MariaDB instance.
- Point the extension at one of them.
- Spin up the server, let the extension initialize the database.
- Stop the server.
- Point the extension at the other database.
- Spin the server back up and watch it crash.

By qualifying the `getTables()` call with the catalog and schema of the
underlying connection object, we limit the search to _just_ that catalog
and schema, which is what we wanted all along. According to the method
documentation, the args are _patterns_, where `%` matches substrings and
`_` matches "any character". So by being hyper-specific, we shouldn't
get any more false positives. In testing on MySQL and MariaDB, only the
`catalog` value is non-null (matches the database name), while `schema`
remains null.
2022-07-30 15:58:05 +02:00
Andreas Troelsen 3f7796772e Upgrade Mockito to 3.12.2.
This fixes an issue with the mock maker not running properly on recent
versions of the JVM, and it also matches the version in the base plugin.
2022-07-30 12:10:50 +02:00
8 changed files with 26 additions and 19 deletions
+6 -2
View File
@@ -9,8 +9,12 @@ It hooks into MobArena's command handler to provide commands for querying and ma
## Getting Started ## Getting Started
Download a copy of the latest MobArenaStats build and place it in your server's `plugins` folder. Download a copy of MobArenaStats from one of these release channels:
You can grab a build from the _Artifacts_ section of the latest run of the [build workflow](https://github.com/mobarena/MobArenaStats/actions/workflows/build.yml) in GitHub Actions, or you can join the MobArena Discord server and grab one from the `#test-builds` channel.
- Stable (recommended): [Latest release](https://github.com/mobarena/MobArenaStats/releases/latest)
- Dev (experimental): [Latest build](https://github.com/mobarena/MobArenaStats/actions/workflows/build.yml)
Place the jar-file in your server's `plugins` folder like you would any other plugin.
Start your server and let the plugin load. Start your server and let the plugin load.
It will generate a default `config.yml` file and set up a default SQLite data store. It will generate a default `config.yml` file and set up a default SQLite data store.
+2 -2
View File
@@ -6,7 +6,7 @@
<groupId>org.mobarena</groupId> <groupId>org.mobarena</groupId>
<artifactId>mobarena-stats</artifactId> <artifactId>mobarena-stats</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0</version>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -86,7 +86,7 @@
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId> <artifactId>mockito-junit-jupiter</artifactId>
<version>3.11.2</version> <version>3.12.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@@ -70,8 +70,10 @@ class SchemaMigrator {
// (available via the underlying JDBC connection object) to find // (available via the underlying JDBC connection object) to find
// out if the schema migrations table exists. // out if the schema migrations table exists.
Connection connection = handle.getConnection(); Connection connection = handle.getConnection();
String catalog = connection.getCatalog();
String schema = connection.getSchema();
DatabaseMetaData meta = connection.getMetaData(); DatabaseMetaData meta = connection.getMetaData();
try (ResultSet tables = meta.getTables(null, null, "schema_migrations", null)) { try (ResultSet tables = meta.getTables(catalog, schema, "schema_migrations", null)) {
while (tables.next()) { while (tables.next()) {
String name = tables.getString("TABLE_NAME"); String name = tables.getString("TABLE_NAME");
if (name.equals("schema_migrations")) { if (name.equals("schema_migrations")) {
@@ -29,11 +29,11 @@ public class MariadbStatsStore {
String host = config.getString("host", "localhost"); String host = config.getString("host", "localhost");
int port = config.getInt("port", 3306); int port = config.getInt("port", 3306);
String database = config.getString("database", "mobarena_stats"); String database = config.getString("database", "mobarena_stats");
boolean ssl = config.getBoolean("ssl", false); String ssl = config.getString("ssl", "");
String params = "useSSL=" + ssl; String url = "jdbc:mariadb://" + host + ":" + port + "/" + database;
return "jdbc:mariadb://" + host + ":" + port + "/" + database + "?" + params; return ssl.isEmpty() ? url : url + "?" + ssl;
} }
} }
@@ -27,11 +27,11 @@ public class MysqlStatsStore {
String host = config.getString("host", "localhost"); String host = config.getString("host", "localhost");
int port = config.getInt("port", 3306); int port = config.getInt("port", 3306);
String database = config.getString("database", "mobarena_stats"); String database = config.getString("database", "mobarena_stats");
boolean ssl = config.getBoolean("ssl", false); String ssl = config.getString("ssl", "");
String params = "useSSL=" + ssl; String url = "jdbc:mysql://" + host + ":" + port + "/" + database;
return "jdbc:mysql://" + host + ":" + port + "/" + database + "?" + params; return ssl.isEmpty() ? url : url + "?" + ssl;
} }
} }
+3 -2
View File
@@ -38,14 +38,15 @@ store:
# - database: name of the database (must exist!) # - database: name of the database (must exist!)
# - username: username of a valid database user # - username: username of a valid database user
# - password: password of a valid database user # - password: password of a valid database user
# - ssl: whether to use SSL for database connections # - ssl: extra JDBC connection parameters, appended to the URL as-is
# (e.g. 'verifyServerCertificate=false&sslmode=required')
# #
#host: localhost #host: localhost
#port: 3306 #port: 3306
#database: '' #database: ''
#username: '' #username: ''
#password: '' #password: ''
#ssl: false #ssl: ''
#-------------------------------------------------------------------- #--------------------------------------------------------------------
#-------------------------------------------------------------------- #--------------------------------------------------------------------
@@ -16,7 +16,7 @@ class MariadbStatsStoreTest {
String result = MariadbStatsStore.getUrl(config); String result = MariadbStatsStore.getUrl(config);
String expected = "jdbc:mariadb://localhost:3306/mobarena_stats?useSSL=false"; String expected = "jdbc:mariadb://localhost:3306/mobarena_stats";
assertThat(result, equalTo(expected)); assertThat(result, equalTo(expected));
} }
@@ -26,11 +26,11 @@ class MariadbStatsStoreTest {
config.set("host", "stats.example.com"); config.set("host", "stats.example.com");
config.set("port", 1337); config.set("port", 1337);
config.set("database", "mastats"); config.set("database", "mastats");
config.set("ssl", true); config.set("ssl", "verifyServerCertificate=false&sslmode=required");
String result = MariadbStatsStore.getUrl(config); String result = MariadbStatsStore.getUrl(config);
String expected = "jdbc:mariadb://stats.example.com:1337/mastats?useSSL=true"; String expected = "jdbc:mariadb://stats.example.com:1337/mastats?verifyServerCertificate=false&sslmode=required";
assertThat(result, equalTo(expected)); assertThat(result, equalTo(expected));
} }
@@ -16,7 +16,7 @@ class MysqlStatsStoreTest {
String result = MysqlStatsStore.getUrl(config); String result = MysqlStatsStore.getUrl(config);
String expected = "jdbc:mysql://localhost:3306/mobarena_stats?useSSL=false"; String expected = "jdbc:mysql://localhost:3306/mobarena_stats";
assertThat(result, equalTo(expected)); assertThat(result, equalTo(expected));
} }
@@ -26,11 +26,11 @@ class MysqlStatsStoreTest {
config.set("host", "stats.example.com"); config.set("host", "stats.example.com");
config.set("port", 1337); config.set("port", 1337);
config.set("database", "mastats"); config.set("database", "mastats");
config.set("ssl", true); config.set("ssl", "verifyServerCertificate=false&sslmode=required");
String result = MysqlStatsStore.getUrl(config); String result = MysqlStatsStore.getUrl(config);
String expected = "jdbc:mysql://stats.example.com:1337/mastats?useSSL=true"; String expected = "jdbc:mysql://stats.example.com:1337/mastats?verifyServerCertificate=false&sslmode=required";
assertThat(result, equalTo(expected)); assertThat(result, equalTo(expected));
} }