Format code

This commit is contained in:
2026-05-16 23:08:09 +02:00
parent 81dd8045f2
commit d110df924e
562 changed files with 11025 additions and 10059 deletions
@@ -74,7 +74,8 @@ data class CacheConfig(val lastUpdate: MutableMap<String, Long>) {
fun isOutdated(uuid: String): Boolean {
return config.lastUpdate[uuid]?.let {
it < Instant.now().minus(1, ChronoUnit.DAYS).toEpochMilli()
} ?: true
}
?: true
}
}
}
@@ -58,7 +58,7 @@ val SWPermissionCheck = createRouteScopedPlugin("SWAuth", ::SWAuthConfig) {
pluginConfig.apply {
on(AuthenticationChecked) { call ->
if (call.request.httpMethod in allowedMethods) {
if(mustAuth) {
if (mustAuth) {
val token = call.principal<SWAuthPrincipal>()
if (token == null) {
@@ -52,7 +52,8 @@ fun Application.configurePlugins() {
global {
rateLimiter(limit = 60, refillPeriod = 60.seconds)
requestKey {
it.request.headers["X-Forwarded-For"] ?: it.request.local.remoteHost
it.request.headers["X-Forwarded-For"]
?: it.request.local.remoteHost
}
requestWeight { applicationCall, _ ->
if (!applicationCall.request.headers.contains("X-Forwarded-For")) {
@@ -100,10 +101,12 @@ fun Application.configurePlugins() {
cookie.maxAgeInSeconds = 60 * 60 * 24 * 7
cookie.httpOnly = true
cookie.secure = true
transform(SessionTransportTransformerEncrypt(
config.sessionEncryptSecret.toByteArray(),
config.sessionSignSecret.toByteArray()
))
transform(
SessionTransportTransformerEncrypt(
config.sessionEncryptSecret.toByteArray(),
config.sessionSignSecret.toByteArray()
)
)
}
}
install(ContentNegotiation) {
@@ -25,5 +25,6 @@ import io.ktor.server.request.*
import java.util.*
fun ApplicationRequest.getUser(key: String = "id"): SteamwarUser? {
return SteamwarUser.get(call.parameters[key]?.let { catchException { UUID.fromString(it) } } ?: return null)
return SteamwarUser.get(call.parameters[key]?.let { catchException { UUID.fromString(it) } }
?: return null)
}
@@ -56,9 +56,12 @@ fun Route.configureAuditLog() {
val serverOwner = call.request.queryParameters.getAll("serverOwner")?.map { it.toInt() }?.toSet()
val velocity = call.request.queryParameters["velocity"]?.toBoolean()
val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 0
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: 100
val sorting = call.request.queryParameters["sorting"] ?: "DESC"
val page = call.request.queryParameters["page"]?.toIntOrNull()
?: 0
val limit = call.request.queryParameters["limit"]?.toIntOrNull()
?: 100
val sorting = call.request.queryParameters["sorting"]
?: "DESC"
call.respond(
PagedAuditLog.filter(
@@ -97,41 +100,30 @@ data class PagedAuditLog(val rows: Long, val entries: List<AuditLogEntry>) {
page: Int = 0,
limit: Int = 100,
sorting: String = "DESC"
) = useDb {
val actorTable = SteamwarUserTable.alias("actor")
val serverOwnerTable = SteamwarUserTable.alias("serverOwner")
) =
useDb {
val actorTable = SteamwarUserTable.alias("actor")
val serverOwnerTable = SteamwarUserTable.alias("serverOwner")
val query = AuditLogTable.join(
actorTable,
JoinType.INNER,
onColumn = actorTable[SteamwarUserTable.id],
otherColumn = AuditLogTable.actor
)
.join(
serverOwnerTable,
JoinType.LEFT,
onColumn = serverOwnerTable[SteamwarUserTable.id],
otherColumn = AuditLogTable.serverOwner
)
.select(
actorTable[SteamwarUserTable.username], serverOwnerTable[SteamwarUserTable.username],
*AuditLogTable.columns.toTypedArray()
val query = AuditLogTable.join(
actorTable,
JoinType.INNER,
onColumn = actorTable[SteamwarUserTable.id],
otherColumn = AuditLogTable.actor
)
.join(
serverOwnerTable,
JoinType.LEFT,
onColumn = serverOwnerTable[SteamwarUserTable.id],
otherColumn = AuditLogTable.serverOwner
)
.select(
actorTable[SteamwarUserTable.username], serverOwnerTable[SteamwarUserTable.username],
*AuditLogTable.columns.toTypedArray()
)
PagedAuditLog(
AuditLogTable.selectAll().addAuditLogFilters(
actionText,
serverText,
fullText,
actor,
actionType,
timeGreater,
timeLess,
serverOwner,
velocity
).count(),
query
.addAuditLogFilters(
PagedAuditLog(
AuditLogTable.selectAll().addAuditLogFilters(
actionText,
serverText,
fullText,
@@ -141,23 +133,35 @@ data class PagedAuditLog(val rows: Long, val entries: List<AuditLogEntry>) {
timeLess,
serverOwner,
velocity
)
.limit(limit)
.offset((page * limit).toLong())
.orderBy(AuditLogTable.time, SortOrder.valueOf(sorting.uppercase()))
.map {
AuditLogEntry(
it[AuditLogTable.id].value,
it[AuditLogTable.time].toEpochMilli(),
it[AuditLogTable.server],
it[serverOwnerTable[SteamwarUserTable.username]],
it[actorTable[SteamwarUserTable.username]],
it[AuditLogTable.action],
it[AuditLogTable.actionText]
).count(),
query
.addAuditLogFilters(
actionText,
serverText,
fullText,
actor,
actionType,
timeGreater,
timeLess,
serverOwner,
velocity
)
},
)
}
.limit(limit)
.offset((page * limit).toLong())
.orderBy(AuditLogTable.time, SortOrder.valueOf(sorting.uppercase()))
.map {
AuditLogEntry(
it[AuditLogTable.id].value,
it[AuditLogTable.time].toEpochMilli(),
it[AuditLogTable.server],
it[serverOwnerTable[SteamwarUserTable.username]],
it[actorTable[SteamwarUserTable.username]],
it[AuditLogTable.action],
it[AuditLogTable.actionText]
)
},
)
}
private fun Query.addAuditLogFilters(
actionText: String? = null,
@@ -55,7 +55,8 @@ fun Route.configureAuth() {
SteamwarUser.clear()
val user = SteamwarUser.get(request.name)
val valid = user?.verifyPassword(request.password) ?: false
val valid = user?.verifyPassword(request.password)
?: false
if (!valid) {
call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username or password", "invalid"))
+21 -11
View File
@@ -95,11 +95,15 @@ fun Route.configureDataRoutes() {
val uuid = call.request.queryParameters["uuid"]?.let { catchException { UUID.fromString(it) } }
val team = call.request.queryParameters.getAll("team")?.map { it.toInt() }?.toSet()
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: 100
val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 0
val limit = call.request.queryParameters["limit"]?.toIntOrNull()
?: 100
val page = call.request.queryParameters["page"]?.toIntOrNull()
?: 0
val includePerms = call.request.queryParameters["includePerms"]?.toBoolean() ?: false
val includeId = call.request.queryParameters["includeId"]?.toBoolean() ?: false
val includePerms = call.request.queryParameters["includePerms"]?.toBoolean()
?: false
val includeId = call.request.queryParameters["includeId"]?.toBoolean()
?: false
call.respond(
useDb {
@@ -145,7 +149,12 @@ fun Route.configureDataRoutes() {
call.respond(server)
} catch (e: Exception) {
e.printStackTrace()
call.respond(HttpStatusCode.InternalServerError, ResponseError(e.message ?: "Unknown error"))
call.respond(
HttpStatusCode.InternalServerError, ResponseError(
e.message
?: "Unknown error"
)
)
return@get
}
}
@@ -182,9 +191,10 @@ fun Route.configureDataRoutes() {
}
}
inline fun <T> catchException(yield: () -> T): T? = try {
yield()
} catch (e: Exception) {
e.printStackTrace()
null
}
inline fun <T> catchException(yield: () -> T): T? =
try {
yield()
} catch (e: Exception) {
e.printStackTrace()
null
}
@@ -89,11 +89,13 @@ data class CreateEventFight(
fun Route.configureEventFightRoutes() {
route("/fights") {
get {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
call.respond(EventFight.getEvent(event.eventID).map { ResponseEventFight(it) })
}
post {
val event = call.receiveEvent() ?: return@post
val event = call.receiveEvent()
?: return@post
val fight = call.receiveNullable<CreateEventFight>()
if (fight == null) {
@@ -117,19 +119,26 @@ fun Route.configureEventFightRoutes() {
}
route("/{fight}") {
put {
val fight = call.receiveFight() ?: return@put
val fight = call.receiveFight()
?: return@put
val updateFight = call.receiveNullable<UpdateEventFight>()
if (updateFight == null) {
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body"))
return@put
}
val teamBlue = updateFight.blueTeam ?: fight.teamBlue
val teamRed = updateFight.redTeam ?: fight.teamRed
val start = updateFight.start?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: fight.startTime
val spielmodus = updateFight.spielmodus ?: fight.spielmodus
val map = updateFight.map ?: fight.map
val spectatePort = updateFight.spectatePort ?: fight.spectatePort
val teamBlue = updateFight.blueTeam
?: fight.teamBlue
val teamRed = updateFight.redTeam
?: fight.teamRed
val start = updateFight.start?.let { Timestamp.from(Instant.ofEpochMilli(it)) }
?: fight.startTime
val spielmodus = updateFight.spielmodus
?: fight.spielmodus
val map = updateFight.map
?: fight.map
val spectatePort = updateFight.spectatePort
?: fight.spectatePort
if (updateFight.group != null) {
if (updateFight.group == -1) {
@@ -147,7 +156,8 @@ fun Route.configureEventFightRoutes() {
call.respond(HttpStatusCode.OK, ResponseEventFight(fight))
}
delete {
val fight = call.receiveFight() ?: return@delete
val fight = call.receiveFight()
?: return@delete
fight.delete()
call.respond(HttpStatusCode.OK)
}
@@ -43,33 +43,48 @@ data class UpdateEventGroup(
fun Route.configureEventGroups() {
route("/groups") {
get {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
call.respond(EventGroup.get(event).map { ResponseGroups(it) })
}
post {
val event = call.receiveEvent() ?: return@post
val event = call.receiveEvent()
?: return@post
val createEventGroup = call.receive<CreateEventGroup>()
val group = EventGroup.create(event, createEventGroup.name, createEventGroup.type)
call.respond(ResponseGroups(group))
}
route("/{group}") {
get {
val group = call.receiveEventGroup() ?: return@get
val group = call.receiveEventGroup()
?: return@get
call.respond(ResponseGroups(group))
}
put {
val group = call.receiveEventGroup() ?: return@put
val group = call.receiveEventGroup()
?: return@put
val updateEventGroup = call.receive<UpdateEventGroup>()
val name = updateEventGroup.name ?: group.name
val type = updateEventGroup.type ?: group.type
val pointsPerWin = updateEventGroup.pointsPerWin ?: group.pointsPerWin
val pointsPerLoss = updateEventGroup.pointsPerLoss ?: group.pointsPerLoss
val pointsPerDraw = updateEventGroup.pointsPerDraw ?: group.pointsPerDraw
val name = updateEventGroup.name
?: group.name
val type = updateEventGroup.type
?: group.type
val pointsPerWin = updateEventGroup.pointsPerWin
?: group.pointsPerWin
val pointsPerLoss = updateEventGroup.pointsPerLoss
?: group.pointsPerLoss
val pointsPerDraw = updateEventGroup.pointsPerDraw
?: group.pointsPerDraw
group.update(name, type, pointsPerWin, pointsPerLoss, pointsPerDraw)
call.respond(ResponseGroups(EventGroup.byId(group.getId()).orElse(null) ?: return@put))
call.respond(
ResponseGroups(
EventGroup.byId(group.getId()).orElse(null)
?: return@put
)
)
}
delete {
val group = call.receiveEventGroup() ?: return@delete
val group = call.receiveEventGroup()
?: return@delete
group.delete()
call.respond(HttpStatusCode.NoContent)
}
@@ -30,11 +30,13 @@ import java.util.*
fun Route.configureEventRefereesRouting() {
route("/referees") {
get {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) })
}
put {
val event = call.receiveEvent() ?: return@put
val event = call.receiveEvent()
?: return@put
val referees = call.receive<List<String>>()
referees.forEach {
Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId())
@@ -42,7 +44,8 @@ fun Route.configureEventRefereesRouting() {
call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) })
}
delete {
val event = call.receiveEvent() ?: return@delete
val event = call.receiveEvent()
?: return@delete
val referees = call.receive<List<String>>()
referees.forEach {
Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId())
@@ -41,18 +41,23 @@ data class UpdateFromRelation(val fromType: EventRelation.FromType, val fromId:
fun Route.configureEventRelations() {
route("/relations") {
get {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
call.respond(EventRelation.get(event).map { ResponseRelation(it) })
}
post {
val create = call.receive<CreateEventRelation>()
val fight = EventFight.byId(create.fightId) ?: return@post call.respond(HttpStatusCode.NotFound)
val fight = EventFight.byId(create.fightId)
?: return@post call.respond(HttpStatusCode.NotFound)
when (create.fromType) {
EventRelation.FromType.FIGHT -> EventFight.byId(create.fromId) ?: return@post call.respond(HttpStatusCode.BadRequest)
EventRelation.FromType.GROUP -> EventGroup.byId(create.fromId) ?: return@post call.respond(HttpStatusCode.BadRequest)
EventRelation.FromType.FIGHT -> EventFight.byId(create.fromId)
?: return@post call.respond(HttpStatusCode.BadRequest)
EventRelation.FromType.GROUP -> EventGroup.byId(create.fromId)
?: return@post call.respond(HttpStatusCode.BadRequest)
}
val relation = EventRelation.create(fight, create.team, create.fromType, create.fromId, create.fromPlace)
@@ -61,19 +66,26 @@ fun Route.configureEventRelations() {
}
route("/{relation}") {
get {
val relation = call.receiveEventRelation() ?: return@get
val relation = call.receiveEventRelation()
?: return@get
call.respond(ResponseRelation(relation))
}
put {
val relation = call.receiveEventRelation() ?: return@put
val relation = call.receiveEventRelation()
?: return@put
val update = call.receive<UpdateEventRelation>()
update.from?.let {
when(it.fromType) {
EventRelation.FromType.FIGHT -> relation.setFromFight(EventFight.byId(it.fromId) ?: return@put call.respond(HttpStatusCode.BadRequest),
when (it.fromType) {
EventRelation.FromType.FIGHT -> relation.setFromFight(
EventFight.byId(it.fromId)
?: return@put call.respond(HttpStatusCode.BadRequest),
it.fromPlace
)
EventRelation.FromType.GROUP -> relation.setFromGroup(EventGroup.byId(it.fromId).orElse(null) ?: return@put call.respond(HttpStatusCode.BadRequest),
EventRelation.FromType.GROUP -> relation.setFromGroup(
EventGroup.byId(it.fromId).orElse(null)
?: return@put call.respond(HttpStatusCode.BadRequest),
it.fromPlace
)
}
@@ -84,7 +96,8 @@ fun Route.configureEventRelations() {
call.respond(ResponseRelation(EventRelation.get(relation.id)))
}
delete {
val relation = call.receiveEventRelation() ?: return@delete
val relation = call.receiveEventRelation()
?: return@delete
relation.delete()
call.respond(HttpStatusCode.NoContent)
}
@@ -29,11 +29,13 @@ import io.ktor.server.routing.*
fun Route.configureEventTeams() {
route("/teams") {
get {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
call.respond(TeamTeilnahme.getTeams(event.eventID).map { ResponseTeam(it) })
}
put {
val event = call.receiveEvent() ?: return@put
val event = call.receiveEvent()
?: return@put
val team = call.receive<List<Int>>()
team.forEach {
TeamTeilnahme.teilnehmen(it, event.eventID)
@@ -41,7 +43,8 @@ fun Route.configureEventTeams() {
call.respond(HttpStatusCode.NoContent)
}
delete {
val event = call.receiveEvent() ?: return@delete
val event = call.receiveEvent()
?: return@delete
val team = call.receive<List<Int>>()
team.forEach {
TeamTeilnahme.notTeilnehmen(it, event.eventID)
@@ -162,13 +162,15 @@ fun Route.configureEventsRoute() {
}
route("/{id}") {
get {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
call.respond(
ExtendedResponseEvent(event)
)
}
get("/csv") {
val event = call.receiveEvent() ?: return@get
val event = call.receiveEvent()
?: return@get
val fights = EventFight.getEvent(event.eventID)
val csv = StringBuilder();
@@ -200,23 +202,30 @@ fun Route.configureEventsRoute() {
call.respondText(csv.toString())
}
put {
val event = call.receiveEvent() ?: return@put
val event = call.receiveEvent()
?: return@put
val updateEvent = call.receiveNullable<UpdateEvent>()
if (updateEvent == null) {
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body"))
return@put
}
val eventName = updateEvent.name ?: event.eventName
val deadline = updateEvent.deadline?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: event.deadline
val start = updateEvent.start?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: event.start
val end = updateEvent.end?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: event.end
val maxTeamMembers = updateEvent.maxTeamMembers ?: event.maximumTeamMembers
val eventName = updateEvent.name
?: event.eventName
val deadline = updateEvent.deadline?.let { Timestamp.from(Instant.ofEpochMilli(it)) }
?: event.deadline
val start = updateEvent.start?.let { Timestamp.from(Instant.ofEpochMilli(it)) }
?: event.start
val end = updateEvent.end?.let { Timestamp.from(Instant.ofEpochMilli(it)) }
?: event.end
val maxTeamMembers = updateEvent.maxTeamMembers
?: event.maximumTeamMembers
val schemType =
if (updateEvent.schemType == "null") null else updateEvent.schemType?.let { SchematicType.fromDB(it) }
?: event.schematicType
val publicSchemsOnly = updateEvent.publicSchemsOnly ?: event.publicSchemsOnly()
val publicSchemsOnly = updateEvent.publicSchemsOnly
?: event.publicSchemsOnly()
if (updateEvent.addReferee != null) {
updateEvent.addReferee.forEach {
+49 -24
View File
@@ -149,7 +149,8 @@ fun Route.configurePage() {
permission = UserPerm.MODERATION
}
get {
val branch = call.request.queryParameters["branch"] ?: "master"
val branch = call.request.queryParameters["branch"]
?: "master"
call.respond(filesInDirectory("/src/content", branch) {
it.endsWith(".md") || it.endsWith(".json")
@@ -157,16 +158,18 @@ fun Route.configurePage() {
}
post {
val req = call.receive<CreatePageRequest>()
if(req.path.startsWith("src/content/")) {
if (req.path.startsWith("src/content/")) {
call.respond(HttpStatusCode.BadRequest, "Invalid path")
return@post
}
val res = client.post("repos/SteamWar/Website/contents/src/content/${req.path}") {
contentType(ContentType.Application.Json)
setBody(CreateGiteaPageRequest(
"Create page ${req.path}",
Base64.getEncoder().encodeToString((
if (req.path.endsWith(".md")) """
setBody(
CreateGiteaPageRequest(
"Create page ${req.path}",
Base64.getEncoder().encodeToString(
(
if (req.path.endsWith(".md")) """
---
title: ${req.title?.removeSuffix(".md") ?: "Enter Title"}
description: Enter Description
@@ -178,10 +181,15 @@ fun Route.configurePage() {
# ${req.path}
""" else "{}"
).trimIndent().toByteArray()),
call.request.queryParameters["branch"] ?: "master",
Identity(call.principal<SWAuthPrincipal>()!!.user.userName, "admin-tool@steamwar.de"
)))
).trimIndent().toByteArray()
),
call.request.queryParameters["branch"]
?: "master",
Identity(
call.principal<SWAuthPrincipal>()!!.user.userName, "admin-tool@steamwar.de"
)
)
)
}
call.respond(res.status)
}
@@ -219,10 +227,13 @@ fun Route.configurePage() {
}
route("{id}") {
get {
val id = call.parameters["id"]?.toIntOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest, "Invalid id")
val path = pathPageIdMap.entries.find { it.value == id }?.key ?: return@get call.respond(HttpStatusCode.NotFound, "Page not found")
val id = call.parameters["id"]?.toIntOrNull()
?: return@get call.respond(HttpStatusCode.BadRequest, "Invalid id")
val path = pathPageIdMap.entries.find { it.value == id }?.key
?: return@get call.respond(HttpStatusCode.NotFound, "Page not found")
val branch = call.request.queryParameters["branch"] ?: "master"
val branch = call.request.queryParameters["branch"]
?: "master"
val res = client.get("repos/SteamWar/Website/contents/$path?ref=$branch")
val fileJson = Json.parseToJsonElement(res.bodyAsText())
if (fileJson is JsonArray) {
@@ -235,8 +246,10 @@ fun Route.configurePage() {
delete {
val data = call.receive<DeletePageRequest>()
val path = pathPageIdMap.entries.find { it.value == call.parameters["id"]?.toIntOrNull() }?.key ?: return@delete call.respond(HttpStatusCode.NotFound, "Page not found")
val branch = call.request.queryParameters["branch"] ?: "master"
val path = pathPageIdMap.entries.find { it.value == call.parameters["id"]?.toIntOrNull() }?.key
?: return@delete call.respond(HttpStatusCode.NotFound, "Page not found")
val branch = call.request.queryParameters["branch"]
?: "master"
@Serializable
data class DeleteGiteaPageRequest(val sha: String, val message: String, val branch: String, val author: Identity)
@@ -253,11 +266,17 @@ fun Route.configurePage() {
data class UpdateGiteaPageRequest(val content: String, val sha: String, val message: String, val branch: String, val author: Identity)
val data = call.receive<UpdatePageRequest>()
val path = pathPageIdMap.entries.find { it.value == call.parameters["id"]?.toIntOrNull() }?.key ?: return@put call.respond(HttpStatusCode.NotFound, "Page not found")
val path = pathPageIdMap.entries.find { it.value == call.parameters["id"]?.toIntOrNull() }?.key
?: return@put call.respond(HttpStatusCode.NotFound, "Page not found")
val res = client.put("repos/SteamWar/Website/contents/$path") {
contentType(ContentType.Application.Json)
setBody(UpdateGiteaPageRequest(data.content, data.sha, data.message, (call.request.queryParameters["branch"] ?: "master"), Identity(call.principal<SWAuthPrincipal>()!!.user.userName, "admin-tool@steamwar.de")))
setBody(
UpdateGiteaPageRequest(
data.content, data.sha, data.message, (call.request.queryParameters["branch"]
?: "master"), Identity(call.principal<SWAuthPrincipal>()!!.user.userName, "admin-tool@steamwar.de")
)
)
}
call.respond(res.status)
@@ -265,7 +284,8 @@ fun Route.configurePage() {
}
route("images") {
get {
val branch = call.request.queryParameters["branch"] ?: "master"
val branch = call.request.queryParameters["branch"]
?: "master"
call.respond(filesInDirectory("/src/images", branch))
}
@@ -274,12 +294,17 @@ fun Route.configurePage() {
client.post("repos/SteamWar/Website/contents/src/images/${req.name}") {
contentType(ContentType.Application.Json)
setBody(CreateGiteaPageRequest(
"Add Image ${req.name}",
req.data,
call.request.queryParameters["branch"] ?: "master",
Identity(call.principal<SWAuthPrincipal>()!!.user.userName, "admin-tool@steamwar.de"
)))
setBody(
CreateGiteaPageRequest(
"Add Image ${req.name}",
req.data,
call.request.queryParameters["branch"]
?: "master",
Identity(
call.principal<SWAuthPrincipal>()!!.user.userName, "admin-tool@steamwar.de"
)
)
)
}
call.respond(HttpStatusCode.Created)
@@ -72,25 +72,28 @@ val nbt = Nbt()
fun Route.configureSchematic() {
route("/download/{code}") {
get {
val node = call.receiveSchematic() ?: return@get
val node = call.receiveSchematic()
?: return@get
val user = call.principal<SWAuthPrincipal>()?.user
if(user != null && !node.accessibleByUser(user)) {
if (user != null && !node.accessibleByUser(user)) {
call.respond(HttpStatusCode.Forbidden)
SWException.log("User ${user.userName} tried to download schematic ${node.name} without permission", user.id.toString())
return@get
}
val data = NodeData.getLatest(node) ?: run {
call.respond(HttpStatusCode.InternalServerError)
return@get
}
val data = NodeData.getLatest(node)
?: run {
call.respond(HttpStatusCode.InternalServerError)
return@get
}
call.response.header("Content-Disposition", "attachment; filename=\"${node.name}${data.nodeFormat.fileEnding}\"")
call.respondBytes(data.schemData(false).readAllBytes(), contentType = ContentType.Application.OctetStream, status = HttpStatusCode.OK)
}
get("/info") {
val node = call.receiveSchematic() ?: return@get
val node = call.receiveSchematic()
?: return@get
call.respond(ResponseSchematic(node))
}
@@ -103,18 +106,22 @@ fun Route.configureSchematic() {
val schemName = file.name.substringBeforeLast(".")
if (SchematicNode.invalidSchemName(arrayOf(schemName))) {
call.respond(HttpStatusCode.BadRequest, ResponseError(
error = "INVALID_NAME"
))
call.respond(
HttpStatusCode.BadRequest, ResponseError(
error = "INVALID_NAME"
)
)
return@post
}
val schemType = file.name.substringAfterLast(".")
if (schemType != "schem" && schemType != "schematic") {
call.respond(HttpStatusCode.BadRequest, ResponseError(
error = "INVALID_SUFFIX"
))
call.respond(
HttpStatusCode.BadRequest, ResponseError(
error = "INVALID_SUFFIX"
)
)
return@post
}
@@ -149,39 +156,47 @@ fun Route.configureSchematic() {
.value
if (fawe.equals("2.12.3-SNAPSHOT")) {
SWException.log("Schematic with Bugged Version Uploaded", """
SWException.log(
"Schematic with Bugged Version Uploaded", """
Schematic=$schemName
User=${user.userName}
Id=${user.id}
""".trimIndent())
""".trimIndent()
)
}
} catch (_: Exception) {}
} catch (_: Exception) {
}
}
NodeData.saveFromStream(node, content.inputStream(), version)
call.respond(ResponseSchematic(node))
} catch (e: Exception) {
call.respond(HttpStatusCode.BadRequest, ResponseError(
error = e.message ?: "GENERIC", code = "UPLOAD_ERROR"
))
call.respond(
HttpStatusCode.BadRequest, ResponseError(
error = e.message
?: "GENERIC", code = "UPLOAD_ERROR"
)
)
}
}
}
}
suspend fun ApplicationCall.receiveSchematic(fieldName: String = "code", delete: Boolean = false): SchematicNode? {
val code = parameters[fieldName] ?: run {
respond(HttpStatusCode.BadRequest)
return null
}
val code = parameters[fieldName]
?: run {
respond(HttpStatusCode.BadRequest)
return null
}
val dl = NodeDownload.get(code) ?: run {
respond(HttpStatusCode.NotFound)
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())) {
if (dl.timestamp.toInstant().plus(Duration.of(5, ChronoUnit.MINUTES)).isBefore(Instant.now())) {
respond(HttpStatusCode.Gone)
return null
}
@@ -190,10 +205,11 @@ suspend fun ApplicationCall.receiveSchematic(fieldName: String = "code", delete:
dl.delete()
}
val node = SchematicNode.getSchematicNode(dl.nodeId) ?: run {
respond(HttpStatusCode.NotFound)
return null
}
val node = SchematicNode.getSchematicNode(dl.nodeId)
?: run {
respond(HttpStatusCode.NotFound)
return null
}
return node
}
+11 -6
View File
@@ -31,11 +31,15 @@ import kotlinx.serialization.Serializable
@Serializable
data class UserStats(val eventFightParticipation: Int, val eventParticipation: Int, val acceptedSchematics: Int, val fights: Int, val playtime: Double) {
constructor(user: SteamwarUser): this(
getEventFightParticipation(user) ?: 0,
getEventParticipation(user) ?: 0,
getAcceptedSchematics(user) ?: 0,
getFightCount(user) ?: 0,
constructor(user: SteamwarUser) : this(
getEventFightParticipation(user)
?: 0,
getEventParticipation(user)
?: 0,
getAcceptedSchematics(user)
?: 0,
getFightCount(user)
?: 0,
user.getOnlinetime() / 3600.0
)
}
@@ -43,7 +47,8 @@ data class UserStats(val eventFightParticipation: Int, val eventParticipation: I
fun Route.configureStats() {
route("/stats") {
get("/ranked/{gamemode}") {
val gamemode = call.parameters["gamemode"] ?: return@get call.respond(HttpStatusCode.NotFound)
val gamemode = call.parameters["gamemode"]
?: return@get call.respond(HttpStatusCode.NotFound)
@Serializable
data class RankedUser(val name: String, val elo: Int)
@@ -84,7 +84,8 @@ fun Route.configureUserPerms() {
)
}
put("/prefix/{prefix}") {
val (user, prefix) = call.receivePermission("prefix", isPrefix = true) ?: return@put
val (user, prefix) = call.receivePermission("prefix", isPrefix = true)
?: return@put
user.perms().filter { it.name.startsWith("PREFIX_") }.forEach {
UserPerm.removePerm(user, it)
@@ -94,7 +95,8 @@ fun Route.configureUserPerms() {
call.respond(HttpStatusCode.Accepted)
}
put("/{perm}") {
val (user, permission) = call.receivePermission() ?: return@put
val (user, permission) = call.receivePermission()
?: return@put
if (!user.hasPerm(permission)) {
UserPerm.addPerm(user, permission)
@@ -104,7 +106,8 @@ fun Route.configureUserPerms() {
call.respond(HttpStatusCode.NoContent)
}
delete("/{perm}") {
val (user, permission) = call.receivePermission() ?: return@delete
val (user, permission) = call.receivePermission()
?: return@delete
if (user.hasPerm(permission)) {
UserPerm.removePerm(user, permission)
@@ -22,8 +22,10 @@ package de.steamwar.sql
import de.steamwar.sql.internal.SQLConfig
import java.util.logging.Logger
class SQLConfigImpl: SQLConfig {
override fun getLogger(): Logger = Logger.getGlobal()
class SQLConfigImpl : SQLConfig {
override fun getLogger(): Logger =
Logger.getGlobal()
override fun maxConnections(): Int = 1
override fun maxConnections(): Int =
1
}
@@ -21,7 +21,7 @@ package de.steamwar.sql
import java.io.File
class SQLWrapperImpl: SQLWrapper<String> {
class SQLWrapperImpl : SQLWrapper<String> {
override fun getSchemTypesFolder(): File {
return File("/configs/GameModes")
}
+29 -24
View File
@@ -30,24 +30,26 @@ private val getNum: (ResultSet) -> Int? = {
private const val eventFightParticipation =
"SELECT FightPlayer.UserID, COUNT(UserID) as num FROM FightPlayer INNER JOIN Fight on FightPlayer.FightID = Fight.FightID WHERE Fight.Server LIKE '%vs%' AND FightPlayer.UserID = ? GROUP BY FightPlayer.UserID"
fun getEventFightParticipation(user: SteamwarUser) = useDb {
exec(
eventFightParticipation, args = listOf(
IntegerColumnType() to user.getId()
)
) { getNum(it) }
}
fun getEventFightParticipation(user: SteamwarUser) =
useDb {
exec(
eventFightParticipation, args = listOf(
IntegerColumnType() to user.getId()
)
) { getNum(it) }
}
private const val eventParticipation =
"SELECT FightPlayer.UserID, COUNT(DISTINCT EventID) as num FROM FightPlayer INNER JOIN Fight F on FightPlayer.FightID = F.FightID INNER JOIN EventFight EF on F.FightID = EF.Fight WHERE F.FightID = FightPlayer.FightID AND FightPlayer.FightID = EF.Fight AND F.Server LIKE '%vs%' AND FightPlayer.UserID = ? GROUP BY FightPlayer.UserID"
fun getEventParticipation(user: SteamwarUser) = useDb {
exec(
eventParticipation, args = listOf(
IntegerColumnType() to user.getId()
)
) { getNum(it) }
}
fun getEventParticipation(user: SteamwarUser) =
useDb {
exec(
eventParticipation, args = listOf(
IntegerColumnType() to user.getId()
)
) { getNum(it) }
}
private const val acceptedSchematics =
"SELECT NodeOwner, COUNT(DISTINCT NodeId) AS num FROM SchematicNode WHERE NodeType != 'normal' AND NodeType IS NOT NULL AND NodeType NOT LIKE 'c%' AND NodeOwner = ?"
@@ -60,19 +62,22 @@ private val fightCount = "SELECT COUNT(*) AS num FROM FightPlayer WHERE UserID =
fun getFightCount(user: SteamwarUser) =
useDb { exec(fightCount, args = listOf(IntegerColumnType() to user.getId())) { getNum(it) } }
fun getRankedList(gamemode: String): List<Pair<String, Int>> = useDb {
emptyList()
}
fun getRankedList(gamemode: String): List<Pair<String, Int>> =
useDb {
emptyList()
}
private const val fightList =
"SELECT DATE(StartTime) AS Datum, GameMode AS Modus, COUNT(*) AS Anzahl FROM Fight WHERE DATE(StartTime) >= DATE(NOW()) - INTERVAL 1 WEEK GROUP BY Datum, GameMode ORDER BY Datum ASC"
fun getFightList(): List<Triple<String, String, Int>> = useDb {
exec(fightList) {
val list = mutableListOf<Triple<String, String, Int>>()
while (it.next()) {
list.add(Triple(it.getString("Datum"), it.getString("Modus"), it.getInt("Anzahl")))
fun getFightList(): List<Triple<String, String, Int>> =
useDb {
exec(fightList) {
val list = mutableListOf<Triple<String, String, Int>>()
while (it.next()) {
list.add(Triple(it.getString("Datum"), it.getString("Modus"), it.getInt("Anzahl")))
}
list
}
list
}
} ?: emptyList()
?: emptyList()
+1 -1
View File
@@ -24,7 +24,7 @@
</encoder>
</appender>
<property name="LOG_FILE" value="api" />
<property name="LOG_FILE" value="api"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/${LOG_FILE}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">