(fix) Umbau zu SCS

**Backend:**
- Vervollständigen Sie alle Repository-Implementierungen
- Implementieren Sie die Authentifizierung und Autorisierung
- Fügen Sie Validierung für alle API-Endpunkte hinzu
This commit is contained in:
stefan
2025-07-19 18:31:32 +02:00
parent 8c1ddb6cb2
commit 83d0d81193
22 changed files with 134 additions and 152 deletions
+1 -1
View File
@@ -86,7 +86,7 @@ Alle Endpunkte verwenden das gleiche Pattern:
```kotlin
// Validierung durchführen
val validationErrors = ApiValidationUtils.validateXxx(...)
val validationErrors = ApiValidationUtils.validateXxx('...')
if (!ApiValidationUtils.isValid(validationErrors)) {
call.respond(
@@ -39,4 +39,4 @@ fun Application.configureApiKeyAuth() {
/**
* Principal für die API-Key-Authentifizierung.
*/
class ApiKeyPrincipal(val apiKey: String) : Principal
class ApiKeyPrincipal(val apiKey: String)
@@ -3,8 +3,6 @@ package at.mocode.gateway.auth
import at.mocode.enums.BerechtigungE
import at.mocode.members.domain.service.JwtService
import at.mocode.shared.config.AppConfig
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
@@ -47,7 +45,7 @@ fun Application.configureJwtAuth(jwtService: JwtService) {
/**
* Prüft, ob der aktuelle Benutzer die angegebene Berechtigung hat.
* Muss innerhalb einer authenticate("jwt")-Block verwendet werden.
* Muss innerhalb eines authenticate("jwt")-Block verwendet werden.
*
* @param permission Die erforderliche Berechtigung
* @param onFailure Funktion, die bei fehlender Berechtigung aufgerufen wird
@@ -64,9 +62,13 @@ suspend fun ApplicationCall.requirePermission(
return
}
val permissions = principal.getClaim("permissions", Array<String>::class)
?.map { try { BerechtigungE.valueOf(it) } catch (e: Exception) { null } }
?.filterNotNull() ?: emptyList()
val permissions = principal.getClaim("permissions", Array<String>::class)?.mapNotNull {
try {
BerechtigungE.valueOf(it)
} catch (e: Exception) {
null
}
} ?: emptyList()
if (permissions.contains(permission) || permissions.contains(BerechtigungE.SYSTEM_ADMIN)) {
onSuccess()
@@ -77,7 +79,7 @@ suspend fun ApplicationCall.requirePermission(
/**
* Prüft, ob der aktuelle Benutzer eine der angegebenen Berechtigungen hat.
* Muss innerhalb einer authenticate("jwt")-Block verwendet werden.
* Muss innerhalb eines authenticate("jwt")-Block verwendet werden.
*
* @param permissions Die erforderlichen Berechtigungen (eine davon ist ausreichend)
* @param onFailure Funktion, die bei fehlender Berechtigung aufgerufen wird
@@ -94,9 +96,13 @@ suspend fun ApplicationCall.requireAnyPermission(
return
}
val userPermissions = principal.getClaim("permissions", Array<String>::class)
?.map { try { BerechtigungE.valueOf(it) } catch (e: Exception) { null } }
?.filterNotNull() ?: emptyList()
val userPermissions = principal.getClaim("permissions", Array<String>::class)?.mapNotNull {
try {
BerechtigungE.valueOf(it)
} catch (_: Exception) {
null
}
} ?: emptyList()
if (userPermissions.contains(BerechtigungE.SYSTEM_ADMIN) ||
permissions.any { userPermissions.contains(it) }) {
@@ -5,7 +5,6 @@ import at.mocode.members.domain.service.AuthenticationService
import at.mocode.members.domain.service.JwtService
import at.mocode.validation.ApiValidationUtils
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
@@ -1,21 +1,21 @@
package at.mocode.events.infrastructure.api
import at.mocode.dto.base.ApiResponse
import at.mocode.events.application.usecase.*
import at.mocode.events.domain.repository.VeranstaltungRepository
import at.mocode.enums.SparteE
import at.mocode.events.application.usecase.CreateVeranstaltungUseCase
import at.mocode.events.application.usecase.DeleteVeranstaltungUseCase
import at.mocode.events.application.usecase.GetVeranstaltungUseCase
import at.mocode.events.application.usecase.UpdateVeranstaltungUseCase
import at.mocode.events.domain.repository.VeranstaltungRepository
import at.mocode.serializers.UuidSerializer
import at.mocode.validation.ApiValidationUtils
import at.mocode.validation.ValidationError
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuidFrom
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.datetime.LocalDate
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
/**
@@ -100,7 +100,7 @@ class VeranstaltungController(
} else {
call.respond(HttpStatusCode.NotFound, ApiResponse.error<Any>("Event not found"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid event ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, ApiResponse.error<Any>("Failed to retrieve event: ${e.message}"))
@@ -228,7 +228,7 @@ class VeranstaltungController(
}
call.respond(statusCode, ApiResponse.error<Any>(response.error?.message ?: "Failed to update event"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid event ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid request data: ${e.message}"))
@@ -249,7 +249,7 @@ class VeranstaltungController(
val forceDelete = if (forceParam != null) {
try {
forceParam.toBoolean()
} catch (e: Exception) {
} catch (_: Exception) {
return@delete call.respond(
HttpStatusCode.BadRequest,
ApiResponse.error<Any>("Invalid force parameter. Must be true or false")
@@ -275,7 +275,7 @@ class VeranstaltungController(
}
call.respond(statusCode, ApiResponse.error<Any>(response.error?.message ?: "Failed to delete event"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid event ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, ApiResponse.error<Any>("Failed to delete event: ${e.message}"))
@@ -3,7 +3,6 @@ package at.mocode.events.infrastructure.repository
import at.mocode.enums.SparteE
import at.mocode.events.domain.model.Veranstaltung
import at.mocode.events.domain.repository.VeranstaltungRepository
import at.mocode.events.infrastructure.repository.VeranstaltungTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
@@ -143,7 +142,7 @@ class VeranstaltungRepositoryImpl : VeranstaltungRepository {
val sparten = if (spartenJson.isNotBlank()) {
try {
Json.decodeFromString<List<SparteE>>(spartenJson)
} catch (e: Exception) {
} catch (_: Exception) {
emptyList()
}
} else {
@@ -1,21 +1,21 @@
package at.mocode.horses.infrastructure.api
import at.mocode.horses.application.usecase.*
import at.mocode.horses.domain.repository.HorseRepository
import at.mocode.dto.base.BaseDto
import at.mocode.dto.base.ApiResponse
import at.mocode.enums.PferdeGeschlechtE
import at.mocode.horses.application.usecase.CreateHorseUseCase
import at.mocode.horses.application.usecase.DeleteHorseUseCase
import at.mocode.horses.application.usecase.GetHorseUseCase
import at.mocode.horses.application.usecase.UpdateHorseUseCase
import at.mocode.horses.domain.repository.HorseRepository
import at.mocode.validation.ApiValidationUtils
import at.mocode.validation.ValidationError
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuidFrom
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
/**
* REST API controller for horse registry operations.
@@ -66,10 +66,10 @@ class HorseController(
val geschlecht = call.request.queryParameters["geschlecht"]?.let {
try {
PferdeGeschlechtE.valueOf(it)
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
return@get call.respond(
HttpStatusCode.BadRequest,
ApiResponse.error<Any>("Invalid geschlecht value. Valid values: ${PferdeGeschlechtE.values().joinToString(", ")}")
ApiResponse.error<Any>("Invalid geschlecht value. Valid values: ${PferdeGeschlechtE.entries.joinToString(", ")}")
)
}
}
@@ -101,7 +101,7 @@ class HorseController(
} else {
call.respond(HttpStatusCode.NotFound, ApiResponse.error<Any>("Horse not found"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid horse ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, ApiResponse.error<Any>("Failed to retrieve horse: ${e.message}"))
@@ -270,7 +270,7 @@ class HorseController(
} else {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Update failed: ${response.errors.joinToString(", ")}"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid horse ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, ApiResponse.error<Any>("Failed to update horse: ${e.message}"))
@@ -296,7 +296,7 @@ class HorseController(
} else {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Delete failed: ${response.errors.joinToString(", ")}"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid horse ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, ApiResponse.error<Any>("Failed to delete horse: ${e.message}"))
@@ -319,7 +319,7 @@ class HorseController(
} else {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Soft delete failed: ${response.errors.joinToString(", ")}"))
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, ApiResponse.error<Any>("Invalid horse ID format"))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, ApiResponse.error<Any>("Failed to soft delete horse: ${e.message}"))
@@ -3,12 +3,9 @@ package at.mocode.horses.infrastructure.repository
import at.mocode.enums.PferdeGeschlechtE
import at.mocode.horses.domain.model.DomPferd
import at.mocode.horses.domain.repository.HorseRepository
import at.mocode.horses.infrastructure.repository.HorseTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.statements.UpdateBuilder
@@ -1,16 +1,12 @@
package at.mocode.masterdata.infrastructure.api
import at.mocode.dto.base.BaseDto
import at.mocode.dto.base.ApiResponse
import at.mocode.masterdata.application.usecase.CreateCountryUseCase
import at.mocode.masterdata.application.usecase.GetCountryUseCase
import at.mocode.masterdata.domain.model.LandDefinition
import at.mocode.validation.ApiValidationUtils
import at.mocode.validation.ValidationError
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuidFrom
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@@ -95,7 +91,7 @@ class CountryController(
val orderBySortierung = if (orderBySortierungParam != null) {
try {
orderBySortierungParam.toBoolean()
} catch (e: Exception) {
} catch (_: Exception) {
return@get call.respond(
HttpStatusCode.BadRequest,
ApiResponse.error<List<CountryDto>>("Invalid orderBySortierung parameter. Must be true or false")
@@ -1,6 +1,5 @@
package at.mocode.members.domain.repository
import at.mocode.members.domain.model.DomBerechtigung
import at.mocode.members.domain.model.DomRolleBerechtigung
import com.benasher44.uuid.Uuid
@@ -8,8 +8,6 @@ import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString
/**
* Service für die Erstellung und Validierung von JWT-Tokens.
@@ -114,7 +112,7 @@ actual class JwtService(private val userAuthorizationService: UserAuthorizationS
val permissions = payload.permissions.mapNotNull { permString ->
try {
BerechtigungE.valueOf(permString)
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
null
}
}
@@ -127,7 +125,7 @@ actual class JwtService(private val userAuthorizationService: UserAuthorizationS
issuedAt = Instant.fromEpochSeconds(payload.iat),
expiresAt = Instant.fromEpochSeconds(payload.exp)
)
} catch (e: Exception) {
} catch (_: Exception) {
null
}
}
@@ -162,6 +160,6 @@ actual class JwtService(private val userAuthorizationService: UserAuthorizationS
bytes[i] = hexPair.toInt(16).toByte()
}
return Uuid(bytes)
return uuidOf(bytes)
}
}
@@ -78,17 +78,17 @@ class AuthenticationService(
* @return RegisterResult mit dem Ergebnis der Registrierung
*/
suspend fun registerUser(username: String, email: String, password: String, personId: Uuid): RegisterResult {
// Prüfen, ob Benutzername bereits existiert
// Prüfen, ob der Benutzername bereits existiert
if (userRepository.findByUsername(username) != null) {
return RegisterResult.Failure("Benutzername wird bereits verwendet")
}
// Prüfen, ob E-Mail bereits existiert
// Prüfen, ob eine E-Mail bereits existiert
if (userRepository.findByEmail(email) != null) {
return RegisterResult.Failure("E-Mail-Adresse wird bereits verwendet")
}
// Prüfen, ob Person bereits einen Benutzer hat
// Prüfen, ob eine Person bereits einen Benutzer hat
if (userRepository.findByPersonId(personId) != null) {
return RegisterResult.Failure("Diese Person hat bereits einen Benutzeraccount")
}
@@ -71,7 +71,7 @@ actual class JwtService(private val userAuthorizationService: UserAuthorizationS
val permissions = permissionStrings.mapNotNull { permString ->
try {
BerechtigungE.valueOf(permString)
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
null
}
}
@@ -84,7 +84,7 @@ actual class JwtService(private val userAuthorizationService: UserAuthorizationS
issuedAt = Instant.fromEpochMilliseconds(jwt.issuedAt.time),
expiresAt = Instant.fromEpochMilliseconds(jwt.expiresAt.time)
)
} catch (e: Exception) {
} catch (_: Exception) {
null
}
}
@@ -7,9 +7,9 @@ import at.mocode.members.infrastructure.table.BerechtigungTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlinx.datetime.TimeZone
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
@@ -73,34 +73,34 @@ class BerechtigungRepositoryImpl : BerechtigungRepository {
}
override suspend fun findById(berechtigungId: Uuid): DomBerechtigung? = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.id eq berechtigungId }
BerechtigungTable.selectAll().where { BerechtigungTable.id eq berechtigungId }
.map(::rowToDomBerechtigung)
.singleOrNull()
}
override suspend fun findByTyp(berechtigungTyp: BerechtigungE): DomBerechtigung? = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.berechtigungTyp eq berechtigungTyp }
BerechtigungTable.selectAll().where { BerechtigungTable.berechtigungTyp eq berechtigungTyp }
.map(::rowToDomBerechtigung)
.singleOrNull()
}
override suspend fun findByName(name: String): List<DomBerechtigung> = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.name like "%$name%" }
BerechtigungTable.selectAll().where { BerechtigungTable.name like "%$name%" }
.map(::rowToDomBerechtigung)
}
override suspend fun findByRessource(ressource: String): List<DomBerechtigung> = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.ressource eq ressource }
BerechtigungTable.selectAll().where { BerechtigungTable.ressource eq ressource }
.map(::rowToDomBerechtigung)
}
override suspend fun findByAktion(aktion: String): List<DomBerechtigung> = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.aktion eq aktion }
BerechtigungTable.selectAll().where { BerechtigungTable.aktion eq aktion }
.map(::rowToDomBerechtigung)
}
override suspend fun findAllActive(): List<DomBerechtigung> = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.istAktiv eq true }
BerechtigungTable.selectAll().where { BerechtigungTable.istAktiv eq true }
.map(::rowToDomBerechtigung)
}
@@ -138,7 +138,7 @@ class BerechtigungRepositoryImpl : BerechtigungRepository {
}
override suspend fun existsByTyp(berechtigungTyp: BerechtigungE): Boolean = DatabaseFactory.dbQuery {
BerechtigungTable.select { BerechtigungTable.berechtigungTyp eq berechtigungTyp }
BerechtigungTable.selectAll().where { BerechtigungTable.berechtigungTyp eq berechtigungTyp }
.count() > 0
}
}
@@ -2,7 +2,6 @@ package at.mocode.members.infrastructure.repository
import at.mocode.members.domain.model.DomPerson
import at.mocode.members.domain.repository.PersonRepository
import at.mocode.members.infrastructure.repository.PersonTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
@@ -21,25 +20,25 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
class PersonRepositoryImpl : PersonRepository {
override suspend fun findById(id: Uuid): DomPerson? = DatabaseFactory.dbQuery {
PersonTable.select { PersonTable.id eq id }
PersonTable.selectAll().where { PersonTable.id eq id }
.map { rowToDomPerson(it) }
.singleOrNull()
}
override suspend fun findByOepsSatzNr(oepsSatzNr: String): DomPerson? = DatabaseFactory.dbQuery {
PersonTable.select { PersonTable.oepsSatzNr eq oepsSatzNr }
PersonTable.selectAll().where { PersonTable.oepsSatzNr eq oepsSatzNr }
.map { rowToDomPerson(it) }
.singleOrNull()
}
override suspend fun findByStammVereinId(vereinId: Uuid): List<DomPerson> = DatabaseFactory.dbQuery {
PersonTable.select { PersonTable.stammVereinId eq vereinId }
PersonTable.selectAll().where { PersonTable.stammVereinId eq vereinId }
.map { rowToDomPerson(it) }
}
override suspend fun findByName(searchTerm: String, limit: Int): List<DomPerson> = DatabaseFactory.dbQuery {
val searchPattern = "%$searchTerm%"
PersonTable.select {
PersonTable.selectAll().where {
(PersonTable.nachname like searchPattern) or
(PersonTable.vorname like searchPattern)
}
@@ -48,7 +47,7 @@ class PersonRepositoryImpl : PersonRepository {
}
override suspend fun findAllActive(limit: Int, offset: Int): List<DomPerson> = DatabaseFactory.dbQuery {
PersonTable.select { PersonTable.istAktiv eq true }
PersonTable.selectAll().where { PersonTable.istAktiv eq true }
.limit(limit, offset.toLong())
.map { rowToDomPerson(it) }
}
@@ -58,7 +57,7 @@ class PersonRepositoryImpl : PersonRepository {
val existingPerson = findById(person.personId)
if (existingPerson == null) {
// Insert new person
// Insert a new person
PersonTable.insert { stmt ->
stmt[PersonTable.id] = person.personId
stmt[PersonTable.oepsSatzNr] = person.oepsSatzNr
@@ -128,12 +127,12 @@ class PersonRepositoryImpl : PersonRepository {
}
override suspend fun existsByOepsSatzNr(oepsSatzNr: String): Boolean = DatabaseFactory.dbQuery {
PersonTable.select { PersonTable.oepsSatzNr eq oepsSatzNr }
PersonTable.selectAll().where { PersonTable.oepsSatzNr eq oepsSatzNr }
.count() > 0
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
PersonTable.select { PersonTable.istAktiv eq true }
PersonTable.selectAll().where { PersonTable.istAktiv eq true }
.count()
}
@@ -74,53 +74,50 @@ class PersonRolleRepositoryImpl : PersonRolleRepository {
}
override suspend fun findById(personRolleId: Uuid): DomPersonRolle? = DatabaseFactory.dbQuery {
PersonRolleTable.select { PersonRolleTable.id eq personRolleId }
PersonRolleTable.selectAll().where { PersonRolleTable.id eq personRolleId }
.map(::rowToDomPersonRolle)
.singleOrNull()
}
override suspend fun findByPersonId(personId: Uuid, nurAktive: Boolean): List<DomPersonRolle> = DatabaseFactory.dbQuery {
val query = if (nurAktive) {
PersonRolleTable.select {
(PersonRolleTable.personId eq personId) and (PersonRolleTable.istAktiv eq true)
}
PersonRolleTable.selectAll()
.where { (PersonRolleTable.personId eq personId) and (PersonRolleTable.istAktiv eq true) }
} else {
PersonRolleTable.select { PersonRolleTable.personId eq personId }
PersonRolleTable.selectAll().where { PersonRolleTable.personId eq personId }
}
query.map(::rowToDomPersonRolle)
}
override suspend fun findByRolleId(rolleId: Uuid, nurAktive: Boolean): List<DomPersonRolle> = DatabaseFactory.dbQuery {
val query = if (nurAktive) {
PersonRolleTable.select {
(PersonRolleTable.rolleId eq rolleId) and (PersonRolleTable.istAktiv eq true)
}
PersonRolleTable.selectAll()
.where { (PersonRolleTable.rolleId eq rolleId) and (PersonRolleTable.istAktiv eq true) }
} else {
PersonRolleTable.select { PersonRolleTable.rolleId eq rolleId }
PersonRolleTable.selectAll().where { PersonRolleTable.rolleId eq rolleId }
}
query.map(::rowToDomPersonRolle)
}
override suspend fun findByVereinId(vereinId: Uuid, nurAktive: Boolean): List<DomPersonRolle> = DatabaseFactory.dbQuery {
val query = if (nurAktive) {
PersonRolleTable.select {
(PersonRolleTable.vereinId eq vereinId) and (PersonRolleTable.istAktiv eq true)
}
PersonRolleTable.selectAll()
.where { (PersonRolleTable.vereinId eq vereinId) and (PersonRolleTable.istAktiv eq true) }
} else {
PersonRolleTable.select { PersonRolleTable.vereinId eq vereinId }
PersonRolleTable.selectAll().where { PersonRolleTable.vereinId eq vereinId }
}
query.map(::rowToDomPersonRolle)
}
override suspend fun findByPersonAndRolle(personId: Uuid, rolleId: Uuid, vereinId: Uuid?): DomPersonRolle? = DatabaseFactory.dbQuery {
val query = if (vereinId != null) {
PersonRolleTable.select {
PersonRolleTable.selectAll().where {
(PersonRolleTable.personId eq personId) and
(PersonRolleTable.rolleId eq rolleId) and
(PersonRolleTable.vereinId eq vereinId)
}
} else {
PersonRolleTable.select {
PersonRolleTable.selectAll().where {
(PersonRolleTable.personId eq personId) and
(PersonRolleTable.rolleId eq rolleId) and
PersonRolleTable.vereinId.isNull()
@@ -130,7 +127,7 @@ class PersonRolleRepositoryImpl : PersonRolleRepository {
}
override suspend fun findValidAt(stichtag: LocalDate, nurAktive: Boolean): List<DomPersonRolle> = DatabaseFactory.dbQuery {
val baseQuery = PersonRolleTable.select {
val baseQuery = PersonRolleTable.selectAll().where {
(PersonRolleTable.gueltigVon lessEq stichtag) and
(PersonRolleTable.gueltigBis.isNull() or (PersonRolleTable.gueltigBis greaterEq stichtag))
}
@@ -145,7 +142,7 @@ class PersonRolleRepositoryImpl : PersonRolleRepository {
}
override suspend fun findByPersonValidAt(personId: Uuid, stichtag: LocalDate, nurAktive: Boolean): List<DomPersonRolle> = DatabaseFactory.dbQuery {
val baseQuery = PersonRolleTable.select {
val baseQuery = PersonRolleTable.selectAll().where {
(PersonRolleTable.personId eq personId) and
(PersonRolleTable.gueltigVon lessEq stichtag) and
(PersonRolleTable.gueltigBis.isNull() or (PersonRolleTable.gueltigBis greaterEq stichtag))
@@ -177,7 +174,7 @@ class PersonRolleRepositoryImpl : PersonRolleRepository {
override suspend fun hasPersonRolle(personId: Uuid, rolleId: Uuid, vereinId: Uuid?, stichtag: LocalDate?): Boolean = DatabaseFactory.dbQuery {
val checkDate = stichtag ?: Clock.System.todayIn(TimeZone.currentSystemDefault())
val baseQuery = PersonRolleTable.select {
val baseQuery = PersonRolleTable.selectAll().where {
(PersonRolleTable.personId eq personId) and
(PersonRolleTable.rolleId eq rolleId) and
(PersonRolleTable.istAktiv eq true) and
@@ -1,6 +1,5 @@
package at.mocode.members.infrastructure.repository
import at.mocode.enums.BerechtigungE
import at.mocode.members.domain.model.DomBerechtigung
import at.mocode.members.domain.model.DomRolleBerechtigung
import at.mocode.members.domain.repository.RolleBerechtigungRepository
@@ -9,9 +8,9 @@ import at.mocode.members.infrastructure.table.RolleBerechtigungTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlinx.datetime.TimeZone
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
@@ -91,41 +90,39 @@ class RolleBerechtigungRepositoryImpl : RolleBerechtigungRepository {
}
override suspend fun findById(rolleBerechtigungId: Uuid): DomRolleBerechtigung? = DatabaseFactory.dbQuery {
RolleBerechtigungTable.select { RolleBerechtigungTable.id eq rolleBerechtigungId }
RolleBerechtigungTable.selectAll().where { RolleBerechtigungTable.id eq rolleBerechtigungId }
.map(::rowToDomRolleBerechtigung)
.singleOrNull()
}
override suspend fun findByRolleId(rolleId: Uuid, nurAktive: Boolean): List<DomRolleBerechtigung> = DatabaseFactory.dbQuery {
val query = if (nurAktive) {
RolleBerechtigungTable.select {
(RolleBerechtigungTable.rolleId eq rolleId) and (RolleBerechtigungTable.istAktiv eq true)
}
RolleBerechtigungTable.selectAll()
.where { (RolleBerechtigungTable.rolleId eq rolleId) and (RolleBerechtigungTable.istAktiv eq true) }
} else {
RolleBerechtigungTable.select { RolleBerechtigungTable.rolleId eq rolleId }
RolleBerechtigungTable.selectAll().where { RolleBerechtigungTable.rolleId eq rolleId }
}
query.map(::rowToDomRolleBerechtigung)
}
override suspend fun findByBerechtigungId(berechtigungId: Uuid, nurAktive: Boolean): List<DomRolleBerechtigung> = DatabaseFactory.dbQuery {
val query = if (nurAktive) {
RolleBerechtigungTable.select {
(RolleBerechtigungTable.berechtigungId eq berechtigungId) and (RolleBerechtigungTable.istAktiv eq true)
}
RolleBerechtigungTable.selectAll()
.where { (RolleBerechtigungTable.berechtigungId eq berechtigungId) and (RolleBerechtigungTable.istAktiv eq true) }
} else {
RolleBerechtigungTable.select { RolleBerechtigungTable.berechtigungId eq berechtigungId }
RolleBerechtigungTable.selectAll().where { RolleBerechtigungTable.berechtigungId eq berechtigungId }
}
query.map(::rowToDomRolleBerechtigung)
}
override suspend fun findByRolleAndBerechtigung(rolleId: Uuid, berechtigungId: Uuid): DomRolleBerechtigung? = DatabaseFactory.dbQuery {
RolleBerechtigungTable.select {
(RolleBerechtigungTable.rolleId eq rolleId) and (RolleBerechtigungTable.berechtigungId eq berechtigungId)
}.map(::rowToDomRolleBerechtigung).singleOrNull()
RolleBerechtigungTable.selectAll()
.where { (RolleBerechtigungTable.rolleId eq rolleId) and (RolleBerechtigungTable.berechtigungId eq berechtigungId) }
.map(::rowToDomRolleBerechtigung).singleOrNull()
}
override suspend fun findAllActive(): List<DomRolleBerechtigung> = DatabaseFactory.dbQuery {
RolleBerechtigungTable.select { RolleBerechtigungTable.istAktiv eq true }
RolleBerechtigungTable.selectAll().where { RolleBerechtigungTable.istAktiv eq true }
.map(::rowToDomRolleBerechtigung)
}
@@ -148,7 +145,7 @@ class RolleBerechtigungRepositoryImpl : RolleBerechtigungRepository {
}
override suspend fun hasRolleBerechtigung(rolleId: Uuid, berechtigungId: Uuid): Boolean = DatabaseFactory.dbQuery {
RolleBerechtigungTable.select {
RolleBerechtigungTable.selectAll().where {
(RolleBerechtigungTable.rolleId eq rolleId) and
(RolleBerechtigungTable.berechtigungId eq berechtigungId) and
(RolleBerechtigungTable.istAktiv eq true)
@@ -156,14 +153,14 @@ class RolleBerechtigungRepositoryImpl : RolleBerechtigungRepository {
}
override suspend fun assignBerechtigungToRolle(rolleId: Uuid, berechtigungId: Uuid, zugewiesenVon: Uuid?): DomRolleBerechtigung = DatabaseFactory.dbQuery {
// Check if assignment already exists
// Check if the assignment already exists
val existing = findByRolleAndBerechtigung(rolleId, berechtigungId)
if (existing != null) {
// Relationship already exists, return it
return@dbQuery existing
}
// Create new assignment
// Create a new assignment
val newAssignment = DomRolleBerechtigung(
rolleId = rolleId,
berechtigungId = berechtigungId,
@@ -7,9 +7,9 @@ import at.mocode.members.infrastructure.table.RolleTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlinx.datetime.TimeZone
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
@@ -67,24 +67,24 @@ class RolleRepositoryImpl : RolleRepository {
}
override suspend fun findById(rolleId: Uuid): DomRolle? = DatabaseFactory.dbQuery {
RolleTable.select { RolleTable.id eq rolleId }
RolleTable.selectAll().where { RolleTable.id eq rolleId }
.map(::rowToDomRolle)
.singleOrNull()
}
override suspend fun findByTyp(rolleTyp: RolleE): DomRolle? = DatabaseFactory.dbQuery {
RolleTable.select { RolleTable.rolleTyp eq rolleTyp }
RolleTable.selectAll().where { RolleTable.rolleTyp eq rolleTyp }
.map(::rowToDomRolle)
.singleOrNull()
}
override suspend fun findByName(name: String): List<DomRolle> = DatabaseFactory.dbQuery {
RolleTable.select { RolleTable.name like "%$name%" }
RolleTable.selectAll().where { RolleTable.name like "%$name%" }
.map(::rowToDomRolle)
}
override suspend fun findAllActive(): List<DomRolle> = DatabaseFactory.dbQuery {
RolleTable.select { RolleTable.istAktiv eq true }
RolleTable.selectAll().where { RolleTable.istAktiv eq true }
.map(::rowToDomRolle)
}
@@ -122,7 +122,7 @@ class RolleRepositoryImpl : RolleRepository {
}
override suspend fun existsByTyp(rolleTyp: RolleE): Boolean = DatabaseFactory.dbQuery {
RolleTable.select { RolleTable.rolleTyp eq rolleTyp }
RolleTable.selectAll().where { RolleTable.rolleTyp eq rolleTyp }
.count() > 0
}
}
@@ -67,25 +67,25 @@ class UserRepositoryImpl : UserRepository {
}
override suspend fun findById(userId: Uuid): DomUser? = DatabaseFactory.dbQuery {
UserTable.select { UserTable.id eq userId }
UserTable.selectAll().where { UserTable.id eq userId }
.map(::rowToDomUser)
.singleOrNull()
}
override suspend fun findByUsername(username: String): DomUser? = DatabaseFactory.dbQuery {
UserTable.select { UserTable.username eq username }
UserTable.selectAll().where { UserTable.username eq username }
.map(::rowToDomUser)
.singleOrNull()
}
override suspend fun findByEmail(email: String): DomUser? = DatabaseFactory.dbQuery {
UserTable.select { UserTable.email eq email }
UserTable.selectAll().where { UserTable.email eq email }
.map(::rowToDomUser)
.singleOrNull()
}
override suspend fun findByPersonId(personId: Uuid): DomUser? = DatabaseFactory.dbQuery {
UserTable.select { UserTable.personId eq personId }
UserTable.selectAll().where { UserTable.personId eq personId }
.map(::rowToDomUser)
.singleOrNull()
}
@@ -201,7 +201,7 @@ class UserRepositoryImpl : UserRepository {
}
override suspend fun getActiveUsers(): List<DomUser> = DatabaseFactory.dbQuery {
UserTable.select { UserTable.isActive eq true }
UserTable.selectAll().where { UserTable.isActive eq true }
.map(::rowToDomUser)
}
}
@@ -2,7 +2,6 @@ package at.mocode.members.infrastructure.repository
import at.mocode.members.domain.model.DomVerein
import at.mocode.members.domain.repository.VereinRepository
import at.mocode.members.infrastructure.repository.VereinTable
import at.mocode.shared.database.DatabaseFactory
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Clock
@@ -21,20 +20,20 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
class VereinRepositoryImpl : VereinRepository {
override suspend fun findById(id: Uuid): DomVerein? = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.id eq id }
VereinTable.selectAll().where { VereinTable.id eq id }
.map { rowToDomVerein(it) }
.singleOrNull()
}
override suspend fun findByOepsVereinsNr(oepsVereinsNr: String): DomVerein? = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.oepsVereinsNr eq oepsVereinsNr }
VereinTable.selectAll().where { VereinTable.oepsVereinsNr eq oepsVereinsNr }
.map { rowToDomVerein(it) }
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<DomVerein> = DatabaseFactory.dbQuery {
val searchPattern = "%$searchTerm%"
VereinTable.select {
VereinTable.selectAll().where {
(VereinTable.name like searchPattern) or
(VereinTable.kuerzel like searchPattern)
}
@@ -43,24 +42,24 @@ class VereinRepositoryImpl : VereinRepository {
}
override suspend fun findByBundeslandId(bundeslandId: Uuid): List<DomVerein> = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.bundeslandId eq bundeslandId }
VereinTable.selectAll().where { VereinTable.bundeslandId eq bundeslandId }
.map { rowToDomVerein(it) }
}
override suspend fun findByLandId(landId: Uuid): List<DomVerein> = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.landId eq landId }
VereinTable.selectAll().where { VereinTable.landId eq landId }
.map { rowToDomVerein(it) }
}
override suspend fun findAllActive(limit: Int, offset: Int): List<DomVerein> = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.istAktiv eq true }
VereinTable.selectAll().where { VereinTable.istAktiv eq true }
.limit(limit, offset.toLong())
.map { rowToDomVerein(it) }
}
override suspend fun findByLocation(searchTerm: String, limit: Int): List<DomVerein> = DatabaseFactory.dbQuery {
val searchPattern = "%$searchTerm%"
VereinTable.select {
VereinTable.selectAll().where {
(VereinTable.ort like searchPattern) or
(VereinTable.plz like searchPattern)
}
@@ -123,19 +122,17 @@ class VereinRepositoryImpl : VereinRepository {
}
override suspend fun existsByOepsVereinsNr(oepsVereinsNr: String): Boolean = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.oepsVereinsNr eq oepsVereinsNr }
VereinTable.selectAll().where { VereinTable.oepsVereinsNr eq oepsVereinsNr }
.count() > 0
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
VereinTable.select { VereinTable.istAktiv eq true }
VereinTable.selectAll().where { VereinTable.istAktiv eq true }
.count()
}
override suspend fun countActiveByBundeslandId(bundeslandId: Uuid): Long = DatabaseFactory.dbQuery {
VereinTable.select {
(VereinTable.istAktiv eq true) and (VereinTable.bundeslandId eq bundeslandId)
}.count()
VereinTable.selectAll().where { (VereinTable.istAktiv eq true) and (VereinTable.bundeslandId eq bundeslandId) }.count()
}
/**
@@ -1,6 +1,5 @@
package at.mocode.members.infrastructure.table
import at.mocode.members.infrastructure.table.RolleTable
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.kotlin.datetime.date
import org.jetbrains.exposed.sql.kotlin.datetime.timestamp
@@ -1,6 +1,5 @@
package at.mocode.validation
import at.mocode.dto.base.ApiResponse
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuidFrom
import kotlinx.datetime.LocalDate
@@ -19,7 +18,7 @@ object ApiValidationUtils {
return try {
uuidFrom(uuidString)
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
null
}
}
@@ -44,7 +43,7 @@ object ApiValidationUtils {
if (limitValue < 1 || limitValue > 1000) {
errors.add(ValidationError("limit", "Limit must be between 1 and 1000", "INVALID_RANGE"))
}
} catch (e: NumberFormatException) {
} catch (_: NumberFormatException) {
errors.add(ValidationError("limit", "Limit must be a valid integer", "INVALID_FORMAT"))
}
}
@@ -56,7 +55,7 @@ object ApiValidationUtils {
if (offsetValue < 0) {
errors.add(ValidationError("offset", "Offset must be non-negative", "INVALID_RANGE"))
}
} catch (e: NumberFormatException) {
} catch (_: NumberFormatException) {
errors.add(ValidationError("offset", "Offset must be a valid integer", "INVALID_FORMAT"))
}
}
@@ -65,7 +64,7 @@ object ApiValidationUtils {
startDate?.let { dateStr ->
try {
LocalDate.parse(dateStr)
} catch (e: Exception) {
} catch (_: Exception) {
errors.add(ValidationError("startDate", "Invalid date format. Use YYYY-MM-DD", "INVALID_FORMAT"))
}
}
@@ -73,7 +72,7 @@ object ApiValidationUtils {
endDate?.let { dateStr ->
try {
LocalDate.parse(dateStr)
} catch (e: Exception) {
} catch (_: Exception) {
errors.add(ValidationError("endDate", "Invalid date format. Use YYYY-MM-DD", "INVALID_FORMAT"))
}
}