diff --git a/.gitignore b/.gitignore index 143f0c2..4698adc 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,5 @@ package-lock.json ### MINE ### frontend/src/api generated + +liquibase*.properties diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 5052774..8a10646 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -2,6 +2,7 @@ plugins { java id("org.springframework.boot") version "3.4.4" id("io.spring.dependency-management") version "1.1.7" +// id("com.github.johnrengelman.shadow") version "8.1.1" } group = "com.alttd.altitudeweb" @@ -25,16 +26,62 @@ repositories { dependencies { implementation(project(":open_api")) + implementation(project(":database")) implementation("org.springframework.boot:spring-boot-starter-web") - compileOnly("org.projectlombok:lombok") - runtimeOnly("org.mariadb.jdbc:mariadb-java-client") annotationProcessor("org.projectlombok:lombok") testImplementation("org.springframework.boot:spring-boot-starter-test") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") + implementation("com.mysql:mysql-connector-j:8.0.32") implementation("org.mybatis:mybatis:3.5.13") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") implementation("org.springframework.boot:spring-boot-configuration-processor") } tasks.withType { useJUnitPlatform() } + +tasks.bootJar { + mainClass.set("com.alttd.altitudeweb.AltitudeWebApplication") + archiveBaseName.set("altitudeweb") + archiveClassifier.set("") +} + + +//tasks.withType { +// mergeServiceFiles() +// dependencies { +// include(dependency("com.mysql:mysql-connector-j")) +// } +//} + +//tasks.withType { +// manifest { +// attributes["Main-Class"] = "com.alttd.altitudeweb.AltitudeWebApplication" +// } +// archiveBaseName.set("altitudeweb") +// archiveClassifier.set("") +// mergeServiceFiles() +// +// // Include everything +// from(sourceSets.main.get().output) +// +// // Include all project dependencies +// configurations = listOf(project.configurations.runtimeClasspath.get()) +// +// // Ensure MySQL is included (even though it should be part of runtimeClasspath already) +// dependencies { +// include(dependency("com.mysql:mysql-connector-j")) +// } +// +// // Enable zip64 mode for large JARs +// isZip64 = true +//} +// +//// Make the shadowJar task the default jar task +//tasks.named("jar") { +// enabled = false +//} +// +//tasks.named("assemble") { +// dependsOn("shadowJar") +//} diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/TeamApiController.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/TeamApiController.java index 718ddfe..c7cb218 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/TeamApiController.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/TeamApiController.java @@ -1,18 +1,39 @@ package com.alttd.altitudeweb.controllers; import com.alttd.altitudeweb.api.TeamApi; +import com.alttd.altitudeweb.database.Connection; +import com.alttd.altitudeweb.database.Databases; +import com.alttd.altitudeweb.database.luckperms.Player; +import com.alttd.altitudeweb.database.luckperms.TeamMemberMapper; +import com.alttd.altitudeweb.model.PlayerDto; import com.alttd.altitudeweb.model.TeamMemberDto; import com.alttd.altitudeweb.model.TeamMembersDto; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@Slf4j @RestController public class TeamApiController implements TeamApi { @Override public ResponseEntity getTeamMembers(String group) { TeamMembersDto teamMemberDtos = new TeamMembersDto(); - teamMemberDtos.add(new TeamMemberDto("test", "good")); + CompletableFuture> playerGroupFuture = new CompletableFuture<>(); + Connection.getConnection(Databases.LUCK_PERMS, configuration -> configuration.addMapper(TeamMemberMapper.class)) + .thenApply(connection -> { + connection.runQuery(sqlSession -> { + log.info("Loading team members for group {}", group); + List players = sqlSession.getMapper(TeamMemberMapper.class).getTeamMembers("group." + group); + playerGroupFuture.complete(players); + }); + return connection; + }); + List join = playerGroupFuture.join(); + join.forEach(player -> teamMemberDtos.add(new PlayerDto(player.username(), player.uuid().toString()))); return ResponseEntity.ok().body(teamMemberDtos); } } diff --git a/backend/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerGroup.java b/backend/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerGroup.java deleted file mode 100644 index ae9d30e..0000000 --- a/backend/src/main/java/com/alttd/altitudeweb/database/luckperms/PlayerGroup.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.alttd.altitudeweb.database.luckperms; - -public record PlayerGroup(String username, String groupName) {} diff --git a/backend/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java b/backend/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java deleted file mode 100644 index 67adaaa..0000000 --- a/backend/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.alttd.altitudeweb.database.luckperms; - -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -public interface TeamMemberMapper { - @Select(""" - SELECT players.username, #{groupName} AS group_name - FROM luckperms_user_permissions AS permissions - INNER JOIN luckperms_players AS players ON players.uuid = permissions.uuid - WHERE permission = 'group.'#{groupName}""") - List getTeamMembers(String groupName); -} diff --git a/database/build.gradle.kts b/database/build.gradle.kts new file mode 100644 index 0000000..34cf887 --- /dev/null +++ b/database/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("java") +} + +group = "com.alttd.altitudeweb" +version = "0.0.1-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + implementation(project(":open_api")) + compileOnly("org.projectlombok:lombok:1.18.38") + annotationProcessor("org.projectlombok:lombok:1.18.38") + implementation("org.mybatis:mybatis:3.5.13") + compileOnly("org.slf4j:slf4j-api:2.0.17") + compileOnly("org.slf4j:slf4j-simple:2.0.17") +} + +tasks.test { + useJUnitPlatform() +} diff --git a/database/src/main/java/com/alttd/altitudeweb/Main.java b/database/src/main/java/com/alttd/altitudeweb/Main.java new file mode 100644 index 0000000..cf6f067 --- /dev/null +++ b/database/src/main/java/com/alttd/altitudeweb/Main.java @@ -0,0 +1,6 @@ +package com.alttd.altitudeweb; + +public class Main { + public static void main(String[] args) { + } +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/database/Connection.java b/database/src/main/java/com/alttd/altitudeweb/database/Connection.java similarity index 97% rename from backend/src/main/java/com/alttd/altitudeweb/database/Connection.java rename to database/src/main/java/com/alttd/altitudeweb/database/Connection.java index 9551545..08dc74a 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/database/Connection.java +++ b/database/src/main/java/com/alttd/altitudeweb/database/Connection.java @@ -41,7 +41,7 @@ public class Connection { return loadDefaultDatabase(addMappers); } CompletableFuture settingsFuture = new CompletableFuture<>(); - getConnection(Databases.DEFAULT, (mapper -> mapper.addMapper(DatabaseSettings.class))).thenApply(connection -> { + getConnection(Databases.DEFAULT, (mapper -> mapper.addMapper(SettingsMapper.class))).thenApply(connection -> { connection.runQuery(session -> { DatabaseSettings loadedSettings = session.getMapper(SettingsMapper.class).getSettings(database.getInternalName()); settingsFuture.complete(loadedSettings); @@ -76,7 +76,7 @@ public class Connection { try (SqlSession session = sqlSessionFactory.openSession()) { consumer.accept(session); } catch (Exception e) { - log.error("Failed to run discord query", e); + log.error("Failed to run query", e); } }).start(); } diff --git a/backend/src/main/java/com/alttd/altitudeweb/database/Databases.java b/database/src/main/java/com/alttd/altitudeweb/database/Databases.java similarity index 100% rename from backend/src/main/java/com/alttd/altitudeweb/database/Databases.java rename to database/src/main/java/com/alttd/altitudeweb/database/Databases.java diff --git a/database/src/main/java/com/alttd/altitudeweb/database/luckperms/Player.java b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/Player.java new file mode 100644 index 0000000..0476ad4 --- /dev/null +++ b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/Player.java @@ -0,0 +1,7 @@ +package com.alttd.altitudeweb.database.luckperms; + +import java.util.UUID; + +public record Player(String username, UUID uuid) { + +} diff --git a/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java new file mode 100644 index 0000000..242a970 --- /dev/null +++ b/database/src/main/java/com/alttd/altitudeweb/database/luckperms/TeamMemberMapper.java @@ -0,0 +1,21 @@ +package com.alttd.altitudeweb.database.luckperms; + +import com.alttd.altitudeweb.type_handler.UUIDTypeHandler; +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.UUID; + +public interface TeamMemberMapper { + @ConstructorArgs({ + @Arg(column = "username", javaType = String.class), + @Arg(column = "uuid", javaType = UUID.class, typeHandler = UUIDTypeHandler.class) + }) + @Select(""" + SELECT players.username, players.uuid + FROM luckperms_user_permissions AS permissions + INNER JOIN luckperms_players AS players ON players.uuid = permissions.uuid + WHERE permission = #{groupPermission} + """) + List getTeamMembers(@Param("groupPermission") String groupPermission); +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/database/web_db/DatabaseSettings.java b/database/src/main/java/com/alttd/altitudeweb/database/web_db/DatabaseSettings.java similarity index 100% rename from backend/src/main/java/com/alttd/altitudeweb/database/web_db/DatabaseSettings.java rename to database/src/main/java/com/alttd/altitudeweb/database/web_db/DatabaseSettings.java diff --git a/backend/src/main/java/com/alttd/altitudeweb/database/web_db/SettingsMapper.java b/database/src/main/java/com/alttd/altitudeweb/database/web_db/SettingsMapper.java similarity index 61% rename from backend/src/main/java/com/alttd/altitudeweb/database/web_db/SettingsMapper.java rename to database/src/main/java/com/alttd/altitudeweb/database/web_db/SettingsMapper.java index 0aef6f1..454e0de 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/database/web_db/SettingsMapper.java +++ b/database/src/main/java/com/alttd/altitudeweb/database/web_db/SettingsMapper.java @@ -3,6 +3,6 @@ package com.alttd.altitudeweb.database.web_db; import org.apache.ibatis.annotations.Select; public interface SettingsMapper { - @Select("SELECT * FROM database_settings WHERE name = #{database}") + @Select("SELECT host, port, name, username, password FROM db_connection_settings WHERE name = #{database}") DatabaseSettings getSettings(String database); } diff --git a/database/src/main/java/com/alttd/altitudeweb/type_handler/UUIDTypeHandler.java b/database/src/main/java/com/alttd/altitudeweb/type_handler/UUIDTypeHandler.java new file mode 100644 index 0000000..3a423d5 --- /dev/null +++ b/database/src/main/java/com/alttd/altitudeweb/type_handler/UUIDTypeHandler.java @@ -0,0 +1,38 @@ +package com.alttd.altitudeweb.type_handler; + +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.UUID; + +@MappedTypes(UUID.class) +public class UUIDTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, parameter.toString()); + } + + @Override + public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException { + String uuid = rs.getString(columnName); + return uuid == null ? null : UUID.fromString(uuid); + } + + @Override + public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + String uuid = rs.getString(columnIndex); + return uuid == null ? null : UUID.fromString(uuid); + } + + @Override + public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + String uuid = cs.getString(columnIndex); + return uuid == null ? null : UUID.fromString(uuid); + } +} diff --git a/database/src/main/resources/create-db-settings-table.sql b/database/src/main/resources/create-db-settings-table.sql new file mode 100644 index 0000000..8195a75 --- /dev/null +++ b/database/src/main/resources/create-db-settings-table.sql @@ -0,0 +1,10 @@ +CREATE TABLE db_connection_settings +( + internal_name VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + password VARCHAR(255) NOT NULL, + host VARCHAR(255) NOT NULL, + port INT NOT NULL, + CONSTRAINT pk_internal_name PRIMARY KEY (internal_name) +); diff --git a/open_api/src/main/resources/api.yml b/open_api/src/main/resources/api.yml index 5a74d18..e9ea756 100644 --- a/open_api/src/main/resources/api.yml +++ b/open_api/src/main/resources/api.yml @@ -65,12 +65,6 @@ paths: $ref: "#/components/schemas/Error" components: schemas: - Player: - type: object - properties: - uuid: - type: string - example: 0c35e520-927e-4c6a-87ad-ff0739c22e9d PlayerHistory: type: object properties: @@ -89,19 +83,21 @@ components: TeamMembers: type: array items: - $ref: '#/components/schemas/TeamMember' - TeamMember: + $ref: '#/components/schemas/Player' + Player: type: object properties: name: type: string - description: The name of the team member - group: + description: The name of the player + example: a_name + uuid: type: string - description: The group to which the team member belongs + example: 0c35e520-927e-4c6a-87ad-ff0739c22e9d + description: The uuid of the team player required: - name - - group + - uuid Error: type: object properties: diff --git a/settings.gradle.kts b/settings.gradle.kts index 482e96b..b924f34 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,2 @@ rootProject.name = "AltitudeWeb" -include("open_api", "backend", "frontend") +include("open_api", "backend", "frontend", "database")