(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,65 +74,62 @@ 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)
(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()
(PersonRolleTable.rolleId eq rolleId) and
PersonRolleTable.vereinId.isNull()
}
}
query.map(::rowToDomPersonRolle).singleOrNull()
}
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))
(PersonRolleTable.gueltigBis.isNull() or (PersonRolleTable.gueltigBis greaterEq stichtag))
}
val query = if (nurAktive) {
@@ -145,10 +142,10 @@ 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))
(PersonRolleTable.gueltigVon lessEq stichtag) and
(PersonRolleTable.gueltigBis.isNull() or (PersonRolleTable.gueltigBis greaterEq stichtag))
}
val query = if (nurAktive) {
@@ -177,12 +174,12 @@ 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
(PersonRolleTable.gueltigVon lessEq checkDate) and
(PersonRolleTable.gueltigBis.isNull() or (PersonRolleTable.gueltigBis greaterEq checkDate))
(PersonRolleTable.rolleId eq rolleId) and
(PersonRolleTable.istAktiv eq true) and
(PersonRolleTable.gueltigVon lessEq checkDate) and
(PersonRolleTable.gueltigBis.isNull() or (PersonRolleTable.gueltigBis greaterEq checkDate))
}
val query = if (vereinId != null) {
@@ -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,22 +145,22 @@ 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)
(RolleBerechtigungTable.berechtigungId eq berechtigungId) and
(RolleBerechtigungTable.istAktiv eq true)
}.count() > 0
}
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"))
}
}