From c11eaaee45d039cce8d7c2f52c9e20f626bd3d14 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 27 Aug 2024 21:34:18 +0200 Subject: [PATCH] Fixes... --- .../SQL/src/de/steamwar/sql/EventFight.java | 2 +- .../steamwar/velocitycore/EventStarter.java | 2 +- .../src/de/steamwar/plugins/Auth.kt | 23 +++ WebsiteBackend/src/de/steamwar/routes/Auth.kt | 74 ---------- WebsiteBackend/src/de/steamwar/routes/Data.kt | 3 - .../src/de/steamwar/routes/EventFights.kt | 41 +++--- .../src/de/steamwar/routes/Events.kt | 39 +++-- .../src/de/steamwar/routes/Routes.kt | 1 - .../src/de/steamwar/routes/Schematic.kt | 134 ++++-------------- .../src/de/steamwar/routes/Stats.kt | 19 +-- .../src/de/steamwar/routes/Teams.kt | 33 ----- WebsiteBackend/src/de/steamwar/routes/User.kt | 54 ------- .../src/de/steamwar/routes/UserPerms.kt | 66 +++------ 13 files changed, 118 insertions(+), 373 deletions(-) delete mode 100644 WebsiteBackend/src/de/steamwar/routes/Teams.kt delete mode 100644 WebsiteBackend/src/de/steamwar/routes/User.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventFight.java b/CommonCore/SQL/src/de/steamwar/sql/EventFight.java index cd7352b3..72497525 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/EventFight.java +++ b/CommonCore/SQL/src/de/steamwar/sql/EventFight.java @@ -96,7 +96,7 @@ public class EventFight implements Comparable { @Getter @Setter @Field(nullable = true) - private int spectatePort; + private Integer spectatePort; @Getter @Field(def = "0") private int ergebnis; diff --git a/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java b/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java index 17d4f537..15c16b64 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java @@ -62,7 +62,7 @@ public class EventStarter { //Don't start EventServer if not the event bungee String command; - if(VelocityCore.get().getConfig().isEventmode() || next.getSpectatePort() == 0) { + if(VelocityCore.get().getConfig().isEventmode() || next.getSpectatePort() == null) { ServerStarter starter = new ServerStarter().event(next); starter.callback(subserver -> { diff --git a/WebsiteBackend/src/de/steamwar/plugins/Auth.kt b/WebsiteBackend/src/de/steamwar/plugins/Auth.kt index bf26f6f4..6d90339a 100644 --- a/WebsiteBackend/src/de/steamwar/plugins/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/plugins/Auth.kt @@ -102,4 +102,27 @@ Message: ${cause.message} SWException.log(msg, cause.stackTraceToString()) call.response.headers.append("X-Caught", "1") } + + onCallRespond { call -> + if (call.response.status()?.isSuccess() == true) { + return@onCallRespond + } + + val msg = """ + URI: ${call.request.uri} + Method: ${call.request.httpMethod.value} + Response: ${call.response.status()?.value} + IP: ${call.request.headers["X-Forwarded-For"] ?: call.request.local.remoteHost} + UserAgent: ${call.request.headers["User-Agent"]} + """.trimIndent() + + val stack = """ + Headers: + ${call.request.headers.entries().joinToString("\n ") { "${it.key}: ${it.value}" }} + Body: + ${call.request.receiveChannel()} + """.trimIndent() + + SWException.log(msg, stack) + } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/Auth.kt index d230c4f4..52238c32 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Auth.kt @@ -78,80 +78,6 @@ fun Route.configureAuthRoutes() { mustAuth = true } - get { - val auth = call.principal() - - if(auth == null) { - call.respond(HttpStatusCode.InternalServerError) - return@get - } - - call.respond(Token.listUser(auth.user).map { ResponseToken(it) }) - } - - post { - val auth = call.principal() - - if(auth == null) { - call.respond(HttpStatusCode.InternalServerError) - return@post - } - - val request = call.receive() - - if(request.name.length > 32) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Name too long", "name_too_long")) - return@post - } - - if(request.name.length < 3) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Name too short", "name_too_short")) - return@post - } - - if(!auth.user.verifyPassword(request.password)) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid password", "invalid_password")) - return@post - } - - val token = Token.createToken(request.name, auth.user) - - call.respond(AuthTokenResponse(token)) - } - - route("/{id}") { - delete { - val auth = call.principal() - - if(auth == null) { - call.respond(HttpStatusCode.InternalServerError) - return@delete - } - - val id = call.parameters["id"]?.toIntOrNull() - - if(id == null) { - call.respond(HttpStatusCode.BadRequest) - return@delete - } - - val token = Token.get(id) - - if(token == null) { - call.respond(HttpStatusCode.NotFound) - return@delete - } - - if(token.owner != auth.user) { - call.respond(HttpStatusCode.Forbidden) - return@delete - } - - token.delete() - call.respond(HttpStatusCode.OK) - } - } - post("/logout") { val auth = call.principal() diff --git a/WebsiteBackend/src/de/steamwar/routes/Data.kt b/WebsiteBackend/src/de/steamwar/routes/Data.kt index fcf13b34..64039974 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Data.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Data.kt @@ -70,9 +70,6 @@ data class ResponseUser(val name: String, val uuid: String, val prefix: String, fun Route.configureDataRoutes() { route("/data") { - get { - call.respondText("Hello World!") - } route("/admin") { install(SWPermissionCheck) { mustAuth = true diff --git a/WebsiteBackend/src/de/steamwar/routes/EventFights.kt b/WebsiteBackend/src/de/steamwar/routes/EventFights.kt index 8112d87c..e95ea89d 100644 --- a/WebsiteBackend/src/de/steamwar/routes/EventFights.kt +++ b/WebsiteBackend/src/de/steamwar/routes/EventFights.kt @@ -118,16 +118,7 @@ fun Route.configureEventFightRoutes() { } route("/{fight}") { put { - val fightId = call.parameters["fight"]?.toIntOrNull() - if (fightId == null) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid fight ID")) - return@put - } - val fight = EventFight.get(fightId) - if (fight == null) { - call.respond(HttpStatusCode.NotFound, ResponseError("Fight not found")) - return@put - } + val fight = call.receiveFight() ?: return@put val updateFight = call.receiveNullable() if (updateFight == null) { call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body")) @@ -143,29 +134,35 @@ fun Route.configureEventFightRoutes() { if (updateFight.group != null) { if (updateFight.group == "null") { - Groups.resetGroup(fightId, true) + Groups.resetGroup(fight.fightID, true) } else { - Groups.setGroup(fightId, updateFight.group) + Groups.setGroup(fight.fightID, updateFight.group) } } fight.update(start, spielmodus, map, teamBlue, teamRed, spectatePort) call.respond(HttpStatusCode.OK, ResponseEventFight(fight)) } delete { - val fightId = call.parameters["fight"]?.toIntOrNull() - if (fightId == null) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid fight ID")) - return@delete - } - val fight = EventFight.get(fightId) - if (fight == null) { - call.respond(HttpStatusCode.NotFound, ResponseError("Fight not found")) - return@delete - } + val fight = call.receiveFight() ?: return@delete fight.delete() call.respond(HttpStatusCode.OK) } } } +} + +suspend fun ApplicationCall.receiveFight(fieldName: String = "fight"): EventFight? { + val fightId = parameters[fieldName]?.toIntOrNull() + if (fightId == null) { + respond(HttpStatusCode.BadRequest, ResponseError("Invalid fight ID")) + return null + } + + val fight = EventFight.get(fightId) + if (fight == null) { + respond(HttpStatusCode.NotFound, ResponseError("Fight not found")) + return null + } + return fight } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt index 987479c2..e351f3e4 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Events.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt @@ -154,16 +154,7 @@ fun Route.configureEventsRoute() { call.respond(EventFight.getEvent(event.eventID).map { ResponseEventFight(it) }) } get("/csv") { - val id = call.parameters["id"]?.toIntOrNull() - if (id == null) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID")) - return@get - } - val event = Event.get(id) - if (event == null) { - call.respond(HttpStatusCode.NotFound, ResponseError("Event not found")) - return@get - } + val event = call.receiveEvent() ?: return@get val fights = EventFight.getEvent(event.eventID) val csv = StringBuilder(); @@ -195,16 +186,8 @@ fun Route.configureEventsRoute() { call.respondText(csv.toString()) } put { - val id = call.parameters["id"]?.toIntOrNull() - if (id == null) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID")) - return@put - } - val event = Event.get(id) - if (event == null) { - call.respond(HttpStatusCode.NotFound, ResponseError("Event not found")) - return@put - } + val event = call.receiveEvent() ?: return@put + val updateEvent = call.receiveNullable() if (updateEvent == null) { call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body")) @@ -249,4 +232,20 @@ fun Route.configureEventsRoute() { } } } +} + +suspend fun ApplicationCall.receiveEvent(fieldName: String = "event"): Event? { + val eventId = parameters[fieldName]?.toIntOrNull() + if (eventId == null) { + respond(HttpStatusCode.BadRequest, ResponseError("Invalid event ID")) + return null + } + + val event = Event.get(eventId) + if (event == null) { + respond(HttpStatusCode.NotFound, ResponseError("Event not found")) + return null + } + + return event } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Routes.kt b/WebsiteBackend/src/de/steamwar/routes/Routes.kt index 85471d14..041d4b31 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Routes.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Routes.kt @@ -34,7 +34,6 @@ fun Application.configureRoutes() { configurePage() configureSchematic() configureAuthRoutes() - configureUser() } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index 3e21d374..b873b97d 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -74,27 +74,7 @@ data class UploadSchematic(val name: String, val content: String) fun Route.configureSchematic() { route("/download/{code}") { get { - val code = call.parameters["code"] ?: run { - call.respond(HttpStatusCode.BadRequest) - return@get - } - - val dl = NodeDownload.get(code) ?: run { - call.respond(HttpStatusCode.NotFound) - return@get - } - - dl.delete() - - if(dl.timestamp.toInstant().plus(Duration.of(5, ChronoUnit.MINUTES)).isBefore(Instant.now())) { - call.respond(HttpStatusCode.Gone) - return@get - } - - val node = SchematicNode.getSchematicNode(dl.nodeId) ?: run { - call.respond(HttpStatusCode.NotFound) - return@get - } + val node = call.receiveSchematic() ?: return@get val user = call.principal()?.user if(user != null && !node.accessibleByUser(user)) { @@ -112,36 +92,13 @@ fun Route.configureSchematic() { call.respondBytes(data.schemData().readAllBytes(), contentType = ContentType.Application.OctetStream, status = HttpStatusCode.OK) } get("/info") { - val code = call.parameters["code"] ?: run { - call.respond(HttpStatusCode.BadRequest) - return@get - } - - val dl = NodeDownload.get(code) ?: run { - call.respond(HttpStatusCode.NotFound) - return@get - } - - val node = SchematicNode.getSchematicNode(dl.nodeId) ?: run { - call.respond(HttpStatusCode.NotFound) - return@get - } + val node = call.receiveSchematic() ?: return@get call.respond(ResponseSchematic(node)) } } route("/schem") { install(SWPermissionCheck) - /*get { - val user = call.principal()!!.user - call.respond(ResponseSchematicList(SchematicNode.list(user, null).filter { it.name != "//copy" }.sortedWith { o1, o2 -> - if (o1.isDir || o2.isDir) { - o2.isDir.compareTo(o1.isDir) - } else { - o1.name.compareTo(o2.name) - } - }.map { ResponseSchematic(it) }, listOf())) - }*/ post { val file = call.receive() @@ -166,64 +123,33 @@ fun Route.configureSchematic() { call.respond(ResponseSchematic(node)) } - /* - route("/{id}") { - get { - val user = call.principal()!!.user - val parentId = call.parameters["id"]?.toIntOrNull() - if(parentId == null) { - call.respond(HttpStatusCode.BadRequest) - return@get - } - - val parent = SchematicNode.getSchematicNode(parentId) - - if(parent == null) { - call.respond(HttpStatusCode.NotFound) - return@get - } - - if(!parent.accessibleByUser(user)) { - call.respond(HttpStatusCode.Forbidden) - return@get - } - - call.respond(ResponseSchematicLong(parent, parent.generateBreadcrumbs(user))) - } - - get("/list") { - val user = call.principal()!!.user - val parentId = call.parameters["id"]?.toIntOrNull() - if(parentId == null) { - call.respond(HttpStatusCode.BadRequest) - return@get - } - - val parent = SchematicNode.getSchematicNode(parentId) - - if(parent == null) { - call.respond(HttpStatusCode.NotFound) - return@get - } - - if(!parent.isDir) { - call.respond(HttpStatusCode.BadRequest) - return@get - } - - if(!parent.accessibleByUser(user)) { - call.respond(HttpStatusCode.Forbidden) - return@get - } - - call.respond(ResponseSchematicList(SchematicNode.list(user, parent.id).filter { it.name != "//copy" }.sortedWith { o1, o2 -> - if (o1.isDir || o2.isDir) { - o2.isDir.compareTo(o1.isDir) - } else { - o1.name.compareTo(o2.name) - } - }.map { ResponseSchematic(it) }, parent.generateBreadcrumbsMap(user).map { ResponseBreadcrumb(it.key, it.value) })) - } - }*/ } } + +suspend fun ApplicationCall.receiveSchematic(fieldName: String = "code", delete: Boolean = false): SchematicNode? { + val code = parameters[fieldName] ?: run { + respond(HttpStatusCode.BadRequest) + return null + } + + val dl = NodeDownload.get(code) ?: run { + respond(HttpStatusCode.NotFound) + return null + } + + if(dl.timestamp.toInstant().plus(Duration.of(5, ChronoUnit.MINUTES)).isBefore(Instant.now())) { + respond(HttpStatusCode.Gone) + return null + } + + if (delete) { + dl.delete() + } + + val node = SchematicNode.getSchematicNode(dl.nodeId) ?: run { + respond(HttpStatusCode.NotFound) + return null + } + + return node +} diff --git a/WebsiteBackend/src/de/steamwar/routes/Stats.kt b/WebsiteBackend/src/de/steamwar/routes/Stats.kt index de3ee2e3..0c4e571b 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Stats.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Stats.kt @@ -59,28 +59,17 @@ fun Route.configureStats() { call.respond(list.map { Fight(it.first, it.second, it.third) }) } - route("/user/{id}") { - install(SWPermissionCheck) { - userCheck { - val user = it.call.request.getUser() - val auth = it.call.principal() - - if (user == null || auth == null) { - return@userCheck false - } - - return@userCheck user.id == auth.user.id || auth.user.hasPerm(UserPerm.MODERATION) - } - } + route("/user") { + install(SWPermissionCheck) get { - val user = call.request.getUser() + val user = call.authentication.principal() if (user == null) { call.respond(HttpStatusCode.NotFound, "User not found") return@get } - call.respond(UserStats(user)) + call.respond(UserStats(user.user)) } } } diff --git a/WebsiteBackend/src/de/steamwar/routes/Teams.kt b/WebsiteBackend/src/de/steamwar/routes/Teams.kt deleted file mode 100644 index b6c5f436..00000000 --- a/WebsiteBackend/src/de/steamwar/routes/Teams.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2024 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.routes - -import de.steamwar.sql.Team -import io.ktor.server.application.* -import io.ktor.server.response.* -import io.ktor.server.routing.* - -fun Route.configureTeamRoutes() { - route("/team") { - get { - call.respond(Team.getAll().map { ResponseTeam(it) }) - } - } -} \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/User.kt b/WebsiteBackend/src/de/steamwar/routes/User.kt deleted file mode 100644 index 9571a90e..00000000 --- a/WebsiteBackend/src/de/steamwar/routes/User.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2024 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.routes - -import de.steamwar.plugins.SWPermissionCheck -import de.steamwar.plugins.getUser -import de.steamwar.sql.UserPerm -import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.request.* -import io.ktor.server.response.* -import io.ktor.server.routing.* - -fun Route.configureUser() { - route("/user") { - route("/{id}") { - route("/admin") { - install(SWPermissionCheck) { - permission = UserPerm.ADMINISTRATION - } - - put("/password") { - val user = call.request.getUser() ?: return@put call.respond(HttpStatusCode.NotFound) - val password = call.receiveText() - - if (password.isEmpty()) { - call.respond(HttpStatusCode.BadRequest, "Password too short") - return@put - } - - user.setPassword(password) - call.respond(HttpStatusCode.OK) - } - } - } - } -} \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt b/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt index dd6244e2..2befc916 100644 --- a/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt +++ b/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt @@ -23,7 +23,6 @@ import de.steamwar.plugins.SWPermissionCheck import de.steamwar.plugins.getUser import de.steamwar.sql.SteamwarUser import de.steamwar.sql.UserPerm -import de.steamwar.sql.UserPerm.Prefix import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* @@ -42,7 +41,6 @@ data class RespondUserPermsPrefix(val prefix: RespondPrefix, val perms: List? { + val user = request.getUser() + if (user == null) { + respond(HttpStatusCode.BadRequest) + return null + } + + val perm = parameters[fieldName] + val permission = UserPerm.entries.find { it.name == perm } + if (perm == null || perm.startsWith("PREFIX_") == isPrefix || permission == null) { + respond(HttpStatusCode.BadRequest) + return null + } + + return user to permission } \ No newline at end of file