Compare commits
2 commits
de33790206
...
b8bfb0b68f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8bfb0b68f | ||
|
|
71f81a97dd |
|
|
@ -9,7 +9,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
object TasksTable : Table("tasks") {
|
object TasksTable : Table("tasks") {
|
||||||
val id = varchar("id", 50)
|
val id = varchar("id", 50)
|
||||||
val question = text("question")
|
val question = text("question")
|
||||||
val options = text("options") // Kommagetrennte Liste der Antwortmöglichkeiten
|
val options = text("options")
|
||||||
val correctAnswer = varchar("correct_answer", 255)
|
val correctAnswer = varchar("correct_answer", 255)
|
||||||
val rewardMinutes = integer("reward_minutes")
|
val rewardMinutes = integer("reward_minutes")
|
||||||
|
|
||||||
|
|
@ -24,10 +24,15 @@ object ScreentimeTable : Table("user_screentime") {
|
||||||
override val primaryKey = PrimaryKey(userId)
|
override val primaryKey = PrimaryKey(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option A: Alles Wichtige für den Haushalt & das Kind in einer Tabelle
|
||||||
object UserTable : Table("users") {
|
object UserTable : Table("users") {
|
||||||
val id = varchar("id", 36)
|
val id = varchar("id", 36)
|
||||||
val username = varchar("username", 50).index(isUnique = true)
|
val email = varchar("email", 255).uniqueIndex()
|
||||||
val passwordHash = varchar("password_hash", 255)
|
val passwordHash = varchar("password_hash", 255)
|
||||||
|
val familyName = varchar("family_name", 100)
|
||||||
|
val childAge = integer("child_age") // Hier ist das Alter wieder!
|
||||||
|
val parentPin = varchar("parent_pin", 4)
|
||||||
|
|
||||||
|
|
||||||
override val primaryKey = PrimaryKey(id)
|
override val primaryKey = PrimaryKey(id)
|
||||||
}
|
}
|
||||||
|
|
@ -36,25 +41,11 @@ object DatabaseFactory {
|
||||||
fun init(config: ApplicationConfig) {
|
fun init(config: ApplicationConfig) {
|
||||||
val driverClassName = config.propertyOrNull("storage.driverClassName")?.getString() ?: "org.postgresql.Driver"
|
val driverClassName = config.propertyOrNull("storage.driverClassName")?.getString() ?: "org.postgresql.Driver"
|
||||||
|
|
||||||
val host = System.getenv("DB_HOST")
|
val host = System.getenv("DB_HOST") ?: config.propertyOrNull("storage.host")?.getString() ?: "localhost"
|
||||||
?: config.propertyOrNull("storage.host")?.getString()
|
val port = System.getenv("DB_PORT") ?: config.propertyOrNull("storage.port")?.getString() ?: "5432"
|
||||||
?: "localhost"
|
val dbName = System.getenv("DB_NAME") ?: config.propertyOrNull("storage.database")?.getString() ?: "kidio_db"
|
||||||
|
val dbUsername = System.getenv("DB_USER") ?: config.propertyOrNull("storage.username")?.getString() ?: "postgres"
|
||||||
val port = System.getenv("DB_PORT")
|
val password = System.getenv("DB_PASSWORD") ?: config.propertyOrNull("storage.password")?.getString() ?: "postgres"
|
||||||
?: config.propertyOrNull("storage.port")?.getString()
|
|
||||||
?: "5432"
|
|
||||||
|
|
||||||
val dbName = System.getenv("DB_NAME")
|
|
||||||
?: config.propertyOrNull("storage.database")?.getString()
|
|
||||||
?: "kidio_db"
|
|
||||||
|
|
||||||
val dbUsername = System.getenv("DB_USER")
|
|
||||||
?: config.propertyOrNull("storage.username")?.getString()
|
|
||||||
?: "postgres"
|
|
||||||
|
|
||||||
val password = System.getenv("DB_PASSWORD")
|
|
||||||
?: config.propertyOrNull("storage.password")?.getString()
|
|
||||||
?: "postgres"
|
|
||||||
|
|
||||||
val jdbcURL = "jdbc:postgresql://$host:$port/$dbName"
|
val jdbcURL = "jdbc:postgresql://$host:$port/$dbName"
|
||||||
|
|
||||||
|
|
@ -66,9 +57,9 @@ object DatabaseFactory {
|
||||||
)
|
)
|
||||||
|
|
||||||
transaction(database) {
|
transaction(database) {
|
||||||
|
// ChildrenTable wurde hier entfernt
|
||||||
SchemaUtils.create(TasksTable, ScreentimeTable, UserTable)
|
SchemaUtils.create(TasksTable, ScreentimeTable, UserTable)
|
||||||
|
|
||||||
// Standard aufgaben, sollte es keine mehr geben
|
|
||||||
if (TasksTable.selectAll().empty()) {
|
if (TasksTable.selectAll().empty()) {
|
||||||
TasksTable.insert {
|
TasksTable.insert {
|
||||||
it[id] = "t1"
|
it[id] = "t1"
|
||||||
|
|
@ -86,7 +77,6 @@ object DatabaseFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seed a default user screentime if empty
|
|
||||||
if (ScreentimeTable.selectAll().empty()) {
|
if (ScreentimeTable.selectAll().empty()) {
|
||||||
ScreentimeTable.insert {
|
ScreentimeTable.insert {
|
||||||
it[userId] = "default_user"
|
it[userId] = "default_user"
|
||||||
|
|
@ -95,13 +85,15 @@ object DatabaseFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a standard user if the Users table is empty.
|
// Korrigierter Seed für UserTable (alle Pflichtfelder befüllt)
|
||||||
if (UserTable.selectAll().empty()) {
|
if (UserTable.selectAll().empty()) {
|
||||||
UserTable.insert {
|
UserTable.insert {
|
||||||
// ID automatische generierung
|
|
||||||
it[id] = "default_user"
|
it[id] = "default_user"
|
||||||
it[username] = "default_user"
|
it[email] = "test@kidio.de"
|
||||||
it[passwordHash] = "1234"
|
it[passwordHash] = "1234" // Dummy-Hash für den Start
|
||||||
|
it[familyName] = "Familie Test"
|
||||||
|
it[childAge] = 8
|
||||||
|
it[parentPin] = "1234"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
|
||||||
data class Task(
|
data class Task(
|
||||||
val id: String,
|
val id: String,
|
||||||
val question: String,
|
val question: String,
|
||||||
val options: List<String>, // Antwortmöglichkeiten
|
val options: List<String>,
|
||||||
val rewardMinutes: Int // Wie viel Belohnung es gibt
|
val rewardMinutes: Int // Wie viel Belohnung es gibt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -33,20 +33,44 @@ data class SyncRequest(
|
||||||
val usedSecondsSinceLastSync: Int
|
val usedSecondsSinceLastSync: Int
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class LoginRequest(
|
|
||||||
val userId: String
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class User(
|
|
||||||
val id: String,
|
|
||||||
val username: String,
|
|
||||||
val passwordHash: String
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SyncResponse(
|
data class SyncResponse(
|
||||||
val remainingSeconds: Int,
|
val remainingSeconds: Int,
|
||||||
val isBlocked: Boolean
|
val isBlocked: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// --- NEU: AUTHENTIFIZIERUNG ---
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RegisterRequest(
|
||||||
|
val email: String,
|
||||||
|
val passwordPlain: String,
|
||||||
|
val familyName: String,
|
||||||
|
val childAge: Int,
|
||||||
|
val parentPin: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class LoginRequest(
|
||||||
|
val userId: String,
|
||||||
|
val email: String,
|
||||||
|
val passwordPlain: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AuthResponse(
|
||||||
|
val token: String, // Der digitale "Ausweis" (JWT)
|
||||||
|
val userId: String, // Wichtig für die App, um Aufgaben zuzuordnen
|
||||||
|
val familyName: String, // Für "Hallo Familie Müller!"
|
||||||
|
val childAge: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interne Backend-Klasse (Domain Model).
|
||||||
|
data class User(
|
||||||
|
val id: String,
|
||||||
|
val email: String,
|
||||||
|
val passwordHash: String,
|
||||||
|
val familyName: String,
|
||||||
|
val childAge: Int,
|
||||||
|
val parentPin: String
|
||||||
|
)
|
||||||
|
|
@ -3,20 +3,22 @@ package com.oliver.kidio.backend.domain.repository
|
||||||
import com.oliver.kidio.backend.Task
|
import com.oliver.kidio.backend.Task
|
||||||
import com.oliver.kidio.backend.User
|
import com.oliver.kidio.backend.User
|
||||||
import com.oliver.kidio.backend.data.database.DatabaseFactory
|
import com.oliver.kidio.backend.data.database.DatabaseFactory
|
||||||
|
import com.oliver.kidio.backend.data.database.DatabaseFactory.dbQuery
|
||||||
import com.oliver.kidio.backend.data.database.RedisFactory
|
import com.oliver.kidio.backend.data.database.RedisFactory
|
||||||
import com.oliver.kidio.backend.data.database.ScreentimeTable
|
import com.oliver.kidio.backend.data.database.ScreentimeTable
|
||||||
import com.oliver.kidio.backend.data.database.TasksTable
|
import com.oliver.kidio.backend.data.database.TasksTable
|
||||||
import com.oliver.kidio.backend.data.database.UserTable
|
import com.oliver.kidio.backend.data.database.UserTable
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.mindrot.jbcrypt.BCrypt
|
||||||
|
|
||||||
interface KidioRepository {
|
interface KidioRepository {
|
||||||
suspend fun getAllTasks(): List<Task>
|
suspend fun getAllTasks(): List<Task>
|
||||||
suspend fun getTaskAnswerAndReward(taskId: String): Pair<String, Int>?
|
suspend fun getTaskAnswerAndReward(taskId: String): Pair<String, Int>?
|
||||||
suspend fun getScreentime(userId: String): Int
|
suspend fun getScreentime(userId: String): Int
|
||||||
suspend fun updateScreentime(userId: String, seconds: Int)
|
suspend fun updateScreentime(userId: String, seconds: Int)
|
||||||
|
suspend fun findByEmail(username: String): User?
|
||||||
suspend fun findByUsername(username: String): User?
|
|
||||||
suspend fun verifyPassword(password: String, passwordHash: String): Boolean
|
suspend fun verifyPassword(password: String, passwordHash: String): Boolean
|
||||||
|
suspend fun registerUser(user: User): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExposedKidioRepository : KidioRepository {
|
class ExposedKidioRepository : KidioRepository {
|
||||||
|
|
@ -31,6 +33,23 @@ class ExposedKidioRepository : KidioRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun registerUser(user: User): Boolean = dbQuery {
|
||||||
|
UserTable.insert {
|
||||||
|
it[UserTable.id] = user.id
|
||||||
|
it[UserTable.email] = user.email
|
||||||
|
it[UserTable.passwordHash] = user.passwordHash
|
||||||
|
it[UserTable.familyName] = user.familyName
|
||||||
|
it[UserTable.childAge] = user.childAge
|
||||||
|
it[UserTable.parentPin] = user.parentPin
|
||||||
|
}
|
||||||
|
ScreentimeTable.insert {
|
||||||
|
it[ScreentimeTable.userId] = user.id
|
||||||
|
it[ScreentimeTable.remainingSeconds] = 1800
|
||||||
|
it[ScreentimeTable.parentPin] = user.parentPin
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getTaskAnswerAndReward(taskId: String): Pair<String, Int>? = DatabaseFactory.dbQuery {
|
override suspend fun getTaskAnswerAndReward(taskId: String): Pair<String, Int>? = DatabaseFactory.dbQuery {
|
||||||
TasksTable.selectAll()
|
TasksTable.selectAll()
|
||||||
.where { TasksTable.id eq taskId }
|
.where { TasksTable.id eq taskId }
|
||||||
|
|
@ -52,12 +71,14 @@ class ExposedKidioRepository : KidioRepository {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("WARNUNG: Konnte nicht aus Redis lesen (Postgres-Fallback genutzt): ${e.message}")
|
println("WARNUNG: Konnte nicht aus Redis lesen (Postgres-Fallback genutzt): ${e.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dbSeconds = DatabaseFactory.dbQuery {
|
val dbSeconds = DatabaseFactory.dbQuery {
|
||||||
ScreentimeTable.selectAll()
|
ScreentimeTable.selectAll()
|
||||||
.where { ScreentimeTable.userId eq userId }
|
.where { ScreentimeTable.userId eq userId }
|
||||||
.map { it[ScreentimeTable.remainingSeconds] }
|
.map { it[ScreentimeTable.remainingSeconds] }
|
||||||
.singleOrNull() ?: 1800
|
.singleOrNull() ?: 1800
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RedisFactory.getResource().use { jedis ->
|
RedisFactory.getResource().use { jedis ->
|
||||||
jedis.setex(redisKey, 3600, dbSeconds.toString())
|
jedis.setex(redisKey, 3600, dbSeconds.toString())
|
||||||
|
|
@ -69,7 +90,7 @@ class ExposedKidioRepository : KidioRepository {
|
||||||
return dbSeconds
|
return dbSeconds
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateScreentime(userId: String, seconds: Int): Unit = DatabaseFactory.dbQuery {
|
override suspend fun updateScreentime(userId: String, seconds: Int) = DatabaseFactory.dbQuery {
|
||||||
val rowsUpdated = ScreentimeTable.update({ ScreentimeTable.userId eq userId }) {
|
val rowsUpdated = ScreentimeTable.update({ ScreentimeTable.userId eq userId }) {
|
||||||
it[remainingSeconds] = seconds
|
it[remainingSeconds] = seconds
|
||||||
}
|
}
|
||||||
|
|
@ -78,25 +99,29 @@ class ExposedKidioRepository : KidioRepository {
|
||||||
it[ScreentimeTable.userId] = userId
|
it[ScreentimeTable.userId] = userId
|
||||||
it[remainingSeconds] = seconds
|
it[remainingSeconds] = seconds
|
||||||
it[parentPin] = "1234"
|
it[parentPin] = "1234"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByUsername(username: String): User? = DatabaseFactory.dbQuery {
|
override suspend fun findByEmail(username: String): User? = DatabaseFactory.dbQuery {
|
||||||
UserTable.selectAll()
|
UserTable.selectAll()
|
||||||
.where { UserTable.username eq username }
|
.where { UserTable.email eq username }
|
||||||
.map {
|
.map {
|
||||||
User(
|
User(
|
||||||
id = it[UserTable.id],
|
id = it[UserTable.id],
|
||||||
username = it[UserTable.username],
|
email = it[UserTable.email],
|
||||||
passwordHash = it[UserTable.passwordHash]
|
passwordHash = it[UserTable.passwordHash],
|
||||||
|
familyName = it[UserTable.familyName],
|
||||||
|
childAge = it[UserTable.childAge],
|
||||||
|
parentPin = it[UserTable.parentPin]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun verifyPassword(password: String, passwordHash: String): Boolean {
|
override suspend fun verifyPassword(password: String, passwordHash: String): Boolean {
|
||||||
return password == passwordHash
|
return BCrypt.checkpw(password, passwordHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,10 +137,7 @@ class InMemoryKidioRepository : KidioRepository {
|
||||||
private val screentimes = mutableMapOf(
|
private val screentimes = mutableMapOf(
|
||||||
"default_user" to 1800
|
"default_user" to 1800
|
||||||
)
|
)
|
||||||
|
private val users = mutableListOf<User>()
|
||||||
private val users = mutableListOf(
|
|
||||||
User(id = "1", username = "max", passwordHash = "geheim123")
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getAllTasks(): List<Task> = tasks
|
override suspend fun getAllTasks(): List<Task> = tasks
|
||||||
|
|
||||||
|
|
@ -127,11 +149,16 @@ class InMemoryKidioRepository : KidioRepository {
|
||||||
screentimes[userId] = seconds
|
screentimes[userId] = seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByUsername(username: String): User? {
|
override suspend fun findByEmail(username: String): User? {
|
||||||
return users.find { it.username == username }
|
return users.find { it.email == username }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun verifyPassword(password: String, passwordHash: String): Boolean {
|
override suspend fun verifyPassword(password: String, passwordHash: String): Boolean {
|
||||||
return password == passwordHash
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun registerUser(user: User): Boolean {
|
||||||
|
users.add(user)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,15 +3,53 @@ package com.oliver.kidio.backend.plugins
|
||||||
import com.oliver.kidio.backend.*
|
import com.oliver.kidio.backend.*
|
||||||
import com.oliver.kidio.backend.domain.repository.KidioRepository
|
import com.oliver.kidio.backend.domain.repository.KidioRepository
|
||||||
import com.oliver.kidio.backend.security.JwtService
|
import com.oliver.kidio.backend.security.JwtService
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.server.auth.authenticate
|
import io.ktor.server.auth.authenticate
|
||||||
|
import io.ktor.server.auth.jwt.JWTPrincipal
|
||||||
|
import io.ktor.server.auth.principal
|
||||||
import io.ktor.server.request.*
|
import io.ktor.server.request.*
|
||||||
import io.ktor.server.response.*
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
import org.mindrot.jbcrypt.BCrypt
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
fun Application.configureRouting(repository: KidioRepository, jwtService : JwtService) {
|
fun Application.configureRouting(repository: KidioRepository, jwtService : JwtService) {
|
||||||
routing {
|
routing {
|
||||||
|
post("/api/v1/auth/register") {
|
||||||
|
val registerRequest = call.receive<RegisterRequest>()
|
||||||
|
if (registerRequest.email.isBlank() || registerRequest.passwordPlain.isBlank()) {
|
||||||
|
call.respond(HttpStatusCode.BadRequest, "Bitte füllen Sie alle Felder aus")
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
if (registerRequest.parentPin.length != 4) {
|
||||||
|
call.respond(HttpStatusCode.BadRequest, "Die Eltern-PIN muss genau 4 Ziffern lang sein")
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
val existingUser = repository.findByEmail(registerRequest.email)
|
||||||
|
if (existingUser != null) {
|
||||||
|
call.respond(HttpStatusCode.Conflict, "Ein Benutzer mit dieser E-Mail-Adresse existiert bereits")
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backend generiert die eindeutige User-ID
|
||||||
|
val userId = UUID.randomUUID().toString()
|
||||||
|
val passwordHash = BCrypt.hashpw(registerRequest.passwordPlain, BCrypt.gensalt())
|
||||||
|
|
||||||
|
//datenbank insert hinzufügen
|
||||||
|
repository.registerUser(User(userId, registerRequest.email, passwordHash, registerRequest.familyName, registerRequest.childAge, registerRequest.parentPin))
|
||||||
|
|
||||||
|
val token = jwtService.generateToken(userId)
|
||||||
|
|
||||||
|
call.respond(
|
||||||
|
HttpStatusCode.Created,
|
||||||
|
mapOf(
|
||||||
|
"token" to token,
|
||||||
|
"userId" to userId,
|
||||||
|
"message" to "Registrierung erfolgreich"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
// Health-Check
|
// Health-Check
|
||||||
get("/api/v1/health") {
|
get("/api/v1/health") {
|
||||||
call.respond(mapOf("status" to "OK", "message" to "Kidio Backend läuft!"))
|
call.respond(mapOf("status" to "OK", "message" to "Kidio Backend läuft!"))
|
||||||
|
|
@ -33,47 +71,52 @@ fun Application.configureRouting(repository: KidioRepository, jwtService : JwtSe
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Antwort auf eine Aufgabe überprüfen
|
// 2. Antwort auf eine Aufgabe überprüfen
|
||||||
post("/api/v1/tasks/verify") {
|
post("/api/v1/tasks/verify") {
|
||||||
val request = call.receive<TaskVerifyRequest>()
|
val request = call.receive<TaskVerifyRequest>()
|
||||||
|
val principal = call.principal<JWTPrincipal>()
|
||||||
|
val userId = principal?.payload?.getClaim("userId")?.asString()
|
||||||
|
|
||||||
val taskInfo = repository.getTaskAnswerAndReward(request.taskId)
|
if (userId == null){
|
||||||
|
call.respond(HttpStatusCode.Unauthorized, mapOf("error" to "Ungültiges oder abgelaufenes Token"))
|
||||||
if (taskInfo == null) {
|
|
||||||
call.respond(
|
|
||||||
TaskVerifyResponse(
|
|
||||||
isCorrect = false,
|
|
||||||
earnedMinutes = 0,
|
|
||||||
message = "Aufgabe nicht gefunden!"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return@post
|
return@post
|
||||||
}
|
}
|
||||||
|
val taskInfo = repository.getTaskAnswerAndReward(request.taskId)
|
||||||
val (correctAnswer, reward) = taskInfo
|
if (taskInfo == null) {
|
||||||
val isCorrect = request.selectedAnswer.trim() == correctAnswer.trim()
|
call.respond(
|
||||||
|
TaskVerifyResponse(
|
||||||
if (isCorrect) {
|
isCorrect = false,
|
||||||
val currentScreentime = repository.getScreentime("default_user")
|
earnedMinutes = 0,
|
||||||
val newSeconds = currentScreentime + (reward * 60)
|
message = "Aufgabe nicht gefunden!"
|
||||||
repository.updateScreentime("default_user", newSeconds)
|
)
|
||||||
|
|
||||||
call.respond(
|
|
||||||
TaskVerifyResponse(
|
|
||||||
isCorrect = true,
|
|
||||||
earnedMinutes = reward,
|
|
||||||
message = "Super gemacht! Du hast $reward Minuten gewonnen."
|
|
||||||
)
|
)
|
||||||
)
|
return@post
|
||||||
} else {
|
}
|
||||||
call.respond(
|
|
||||||
TaskVerifyResponse(
|
val (correctAnswer, reward) = taskInfo
|
||||||
isCorrect = false,
|
val isCorrect = request.selectedAnswer.trim() == correctAnswer.trim()
|
||||||
earnedMinutes = 0,
|
|
||||||
message = "Schade, das war leider falsch. Versuche es nochmal!"
|
if (isCorrect) {
|
||||||
|
val currentScreentime = repository.getScreentime(userId)
|
||||||
|
val newSeconds = currentScreentime + (reward * 60)
|
||||||
|
repository.updateScreentime(userId, newSeconds)
|
||||||
|
|
||||||
|
call.respond(
|
||||||
|
TaskVerifyResponse(
|
||||||
|
isCorrect = true,
|
||||||
|
earnedMinutes = reward,
|
||||||
|
message = "Super gemacht! Du hast $reward Minuten gewonnen."
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
} else {
|
||||||
|
call.respond(
|
||||||
|
TaskVerifyResponse(
|
||||||
|
isCorrect = false,
|
||||||
|
earnedMinutes = 0,
|
||||||
|
message = "Schade, das war leider falsch. Versuche es nochmal!"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Bildschirmzeit synchronisieren
|
// 3. Bildschirmzeit synchronisieren
|
||||||
post("/api/v1/screentime/sync") {
|
post("/api/v1/screentime/sync") {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import io.ktor.server.auth.jwt.*
|
||||||
/**
|
/**
|
||||||
* Repräsentiert den authentifizierten Benutzer im Request-Kontext.
|
* Repräsentiert den authentifizierten Benutzer im Request-Kontext.
|
||||||
*/
|
*/
|
||||||
data class UserPrincipal(val userId: String) : Principal
|
data class UserPrincipal(val userId: String)
|
||||||
|
|
||||||
fun Application.configureSecurity(jwtService: JwtService) {
|
fun Application.configureSecurity(jwtService: JwtService) {
|
||||||
install(Authentication) {
|
install(Authentication) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue