diff --git a/WebsiteBackend/src/de/steamwar/routes/AuditLog.kt b/WebsiteBackend/src/de/steamwar/routes/AuditLog.kt index cafd8d48..7ac08d5f 100644 --- a/WebsiteBackend/src/de/steamwar/routes/AuditLog.kt +++ b/WebsiteBackend/src/de/steamwar/routes/AuditLog.kt @@ -32,6 +32,7 @@ import io.ktor.server.routing.Route import io.ktor.server.routing.get import io.ktor.server.routing.route import kotlinx.serialization.Serializable +import org.jetbrains.exposed.v1.core.Alias import org.jetbrains.exposed.v1.core.JoinType import org.jetbrains.exposed.v1.core.SortOrder import org.jetbrains.exposed.v1.core.alias @@ -41,8 +42,10 @@ import org.jetbrains.exposed.v1.core.isNull import org.jetbrains.exposed.v1.core.less import org.jetbrains.exposed.v1.core.like import org.jetbrains.exposed.v1.core.or +import org.jetbrains.exposed.v1.jdbc.Query import org.jetbrains.exposed.v1.jdbc.andWhere import org.jetbrains.exposed.v1.jdbc.select +import org.jetbrains.exposed.v1.jdbc.selectAll import java.time.Instant fun Route.configureAuditLog() { @@ -127,34 +130,30 @@ data class PagedAuditLog(val rows: Long, val entries: List) { *AuditLogTable.columns.toTypedArray() ) - - actionText?.let { - query.andWhere { (AuditLogTable.actionText like "%$it%") } - } - - serverText?.let { - query.andWhere { (AuditLogTable.server like "%$it%") } - } - - fullText?.let { - query.andWhere { (AuditLogTable.actionText like "%$it%") or (AuditLogTable.server like "%$it%") } - } - - actor?.let { query.andWhere { AuditLogTable.actor inList actor } } - - actionType?.let { query.andWhere { AuditLogTable.action inList actionType } } - - timeGreater?.let { query.andWhere { AuditLogTable.time greater timeGreater } } - - timeLess?.let { query.andWhere { AuditLogTable.time less timeLess } } - - serverOwner?.let { query.andWhere { AuditLogTable.serverOwner inList serverOwner } } - - if (velocity == true) query.andWhere { AuditLogTable.serverOwner.isNull() } - PagedAuditLog( - query.count(), + AuditLogTable.selectAll().addAuditLogFilters( + actionText, + serverText, + fullText, + actor, + actionType, + timeGreater, + timeLess, + serverOwner, + velocity + ).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())) @@ -171,6 +170,36 @@ data class PagedAuditLog(val rows: Long, val entries: List) { }, ) } + + private fun Query.addAuditLogFilters( + actionText: String? = null, + serverText: String? = null, + fullText: String? = null, + actor: Set? = null, + actionType: Set? = null, + timeGreater: Instant? = null, + timeLess: Instant? = null, + serverOwner: Set? = null, + velocity: Boolean? = null, + ): Query { + actionText?.let { + andWhere { (AuditLogTable.actionText like "%$it%") } + } + serverText?.let { + andWhere { (AuditLogTable.server like "%$it%") } + } + fullText?.let { + andWhere { (AuditLogTable.actionText like "%$it%") or (AuditLogTable.server like "%$it%") } + } + actor?.let { andWhere { AuditLogTable.actor inList actor } } + actionType?.let { andWhere { AuditLogTable.action inList actionType } } + timeGreater?.let { andWhere { AuditLogTable.time greater timeGreater } } + timeLess?.let { andWhere { AuditLogTable.time less timeLess } } + serverOwner?.let { andWhere { AuditLogTable.serverOwner inList serverOwner } } + if (velocity == true) andWhere { AuditLogTable.serverOwner.isNull() } + + return this + } } } diff --git a/WebsiteBackend/src/de/steamwar/routes/Data.kt b/WebsiteBackend/src/de/steamwar/routes/Data.kt index 4c86d32f..fd27d028 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Data.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Data.kt @@ -25,6 +25,7 @@ import de.steamwar.plugins.SWAuthPrincipal import de.steamwar.plugins.SWPermissionCheck import de.steamwar.sql.SchematicType import de.steamwar.sql.SteamwarUser +import de.steamwar.sql.SteamwarUserTable import de.steamwar.sql.Team import de.steamwar.sql.UserPerm import de.steamwar.sql.internal.useDb @@ -36,6 +37,13 @@ import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.serialization.Serializable import org.bspfsystems.yamlconfiguration.file.YamlConfiguration +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.inList +import org.jetbrains.exposed.v1.core.like +import org.jetbrains.exposed.v1.jdbc.Query +import org.jetbrains.exposed.v1.jdbc.andWhere +import org.jetbrains.exposed.v1.jdbc.selectAll import java.io.File import java.net.InetSocketAddress import java.util.* @@ -44,8 +52,39 @@ import java.util.* data class ResponseSchematicType(val name: String, val db: String) @Serializable -data class ResponseUser(val name: String, val uuid: String) { - constructor(user: SteamwarUser) : this(user.userName, user.uuid.toString()) +data class ResponseUser( + val name: String, val uuid: String, val id: Int?, val perms: List?, val prefix: String? +) { + constructor(user: SteamwarUser, includeId: Boolean = false, includePerms: Boolean = false) : this( + user.userName, + user.uuid.toString(), + if (includeId) user.getId() else null, + if (includePerms) user.perms().map { it.name } else null, + if (includePerms) user.prefix().chatPrefix else null, + ) + + constructor(row: ResultRow, includeId: Boolean = false, includePerms: Boolean = false, prefixes: MutableSet = mutableSetOf()) : this( + row[SteamwarUserTable.username], + row[SteamwarUserTable.uuid], + if (includeId) row[SteamwarUserTable.id].value else null, + if (includePerms) UserPerm.getPerms(row[SteamwarUserTable.id].value).also { prefixes.addAll(it) }.map { it.name } else null, + if (includePerms) prefixes.firstOrNull { UserPerm.prefixes.containsKey(it) }?.let { UserPerm.prefixes[it]!!.chatPrefix } else null + ) +} + +@Serializable +data class ResponseUserList(val entries: List, val rows: Long) + +private fun Query.addUserFilter( + name: String? = null, + uuid: UUID? = null, + team: Set? = null, +): Query { + name?.let { andWhere { (SteamwarUserTable.username like "%$it%") } } + uuid?.let { andWhere { (SteamwarUserTable.uuid eq it.toString()) } } + team?.let { andWhere { (SteamwarUserTable.team inList team) } } + + return this } fun Route.configureDataRoutes() { @@ -57,18 +96,32 @@ fun Route.configureDataRoutes() { } get("/users") { val name = call.request.queryParameters["name"] + 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 includePerms = call.request.queryParameters["includePerms"]?.toBoolean() ?: false val includeId = call.request.queryParameters["includeId"]?.toBoolean() ?: false + + call.respond( + useDb { + ResponseUserList( + SteamwarUserTable.selectAll().addUserFilter(name, uuid, team).limit(limit) + .offset((page * limit).toLong()) + .map { ResponseUser(it, includeId, includePerms) }, + SteamwarUserTable.selectAll().addUserFilter(name, uuid, team).count() + ) + } + ) } get("/teams") { call.respond(Team.getAll().map { ResponseTeam(it) }) } get("/schematicTypes") { - call.respond(SchematicType.values().filter { !it.check() }.map { ResponseSchematicType(it.name(), it.toDB()) }) + call.respond(SchematicType.values().filter { !it.check() } + .map { ResponseSchematicType(it.name(), it.toDB()) }) } get("/gamemodes") { call.respond( @@ -102,11 +155,14 @@ fun Route.configureDataRoutes() { } get("/team") { call.respond( - listOf(UserPerm.PREFIX_ADMIN, UserPerm.PREFIX_DEVELOPER, UserPerm.PREFIX_MODERATOR, UserPerm.PREFIX_SUPPORTER, UserPerm.PREFIX_BUILDER) - .associateWith { SteamwarUser.getUsersWithPerm(it) } - .mapKeys { UserPerm.prefixes[it.key]!!.chatPrefix } - .mapValues { it.value.map { ResponseUser(it) } } - ) + listOf( + UserPerm.PREFIX_ADMIN, + UserPerm.PREFIX_DEVELOPER, + UserPerm.PREFIX_MODERATOR, + UserPerm.PREFIX_SUPPORTER, + UserPerm.PREFIX_BUILDER + ).associateWith { SteamwarUser.getUsersWithPerm(it) }.mapKeys { UserPerm.prefixes[it.key]!!.chatPrefix } + .mapValues { it.value.map { ResponseUser(it) } }) } get("/skin/{uuid}") { val uuid = call.parameters["uuid"]