feat/gitignore #9
|
|
@ -33,187 +33,190 @@ fun isValidPassword(password: String): Boolean {
|
|||
}
|
||||
|
||||
fun Application.configureRouting(repository: KidioRepository, jwtService : JwtService) {
|
||||
fun Application.configureRouting(
|
||||
repository: KidioRepository,
|
||||
jwtService: JwtService,
|
||||
) {
|
||||
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 (!isValidPassword(registerRequest.passwordPlain)) {
|
||||
call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"Das Passwort muss mindestens 8 Zeichen lang sein, mindestens einen Großbuchstaben und ein Sonderzeichen enthalten und darf keine Emojis enthalten."
|
||||
)
|
||||
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
|
||||
get("/api/v1/health") {
|
||||
call.respond(mapOf("status" to "OK", "message" to "Kidio Backend läuft!"))
|
||||
}
|
||||
|
||||
post("/api/v1/auth/login") {
|
||||
val loginRequest = call.receive<LoginRequest>()
|
||||
if (loginRequest.email.isBlank() || loginRequest.passwordPlain.isBlank()) {
|
||||
call.respond(HttpStatusCode.BadRequest, "Bitte füllen Sie alle Felder aus")
|
||||
return@post
|
||||
}
|
||||
val getUser = repository.findByEmail(loginRequest.email)
|
||||
if (getUser == null || !repository.verifyPassword(loginRequest.passwordPlain, getUser.passwordHash)) {
|
||||
call.respond(HttpStatusCode.Unauthorized, "Ungültige Anmeldedaten")
|
||||
return@post
|
||||
}
|
||||
val token = jwtService.generateToken(getUser.id)
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
AuthResponse(
|
||||
token,
|
||||
userId = getUser.id,
|
||||
familyName = getUser.familyName,
|
||||
childAge = getUser.childAge,
|
||||
),
|
||||
)
|
||||
return@post
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
authenticate("auth-jwt") {
|
||||
|
||||
// 1. Alle verfügbaren Aufgaben abrufen
|
||||
get("/api/v1/tasks") {
|
||||
val tasks = repository.getAllTasks()
|
||||
call.respond(tasks)
|
||||
}
|
||||
|
||||
// 2. Antwort auf eine Aufgabe überprüfen
|
||||
post("/api/v1/tasks/verify") {
|
||||
val request = call.receive<TaskVerifyRequest>()
|
||||
val principal = call.principal<UserPrincipal>()
|
||||
val userId = principal?.userId
|
||||
if (userId == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized, mapOf("error" to "Ungültiges oder abgelaufenes Token"))
|
||||
fun Application.configureRouting(
|
||||
repository: KidioRepository,
|
||||
jwtService: JwtService,
|
||||
) {
|
||||
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
|
||||
}
|
||||
val taskInfo = repository.getTaskAnswerAndReward(request.taskId)
|
||||
if (taskInfo == null) {
|
||||
if (!isValidPassword(registerRequest.passwordPlain)) {
|
||||
call.respond(
|
||||
TaskVerifyResponse(
|
||||
isCorrect = false,
|
||||
earnedMinutes = 0,
|
||||
message = "Aufgabe nicht gefunden!",
|
||||
),
|
||||
HttpStatusCode.BadRequest,
|
||||
"Das Passwort muss mindestens 8 Zeichen lang sein, mindestens einen Großbuchstaben und ein Sonderzeichen enthalten und darf keine Emojis enthalten."
|
||||
)
|
||||
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
|
||||
}
|
||||
|
||||
val (correctAnswer, reward) = taskInfo
|
||||
val isCorrect = request.selectedAnswer.trim() == correctAnswer.trim()
|
||||
// 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
|
||||
get("/api/v1/health") {
|
||||
call.respond(mapOf("status" to "OK", "message" to "Kidio Backend läuft!"))
|
||||
}
|
||||
|
||||
post("/api/v1/auth/login") {
|
||||
val loginRequest = call.receive<LoginRequest>()
|
||||
if (loginRequest.email.isBlank() || loginRequest.passwordPlain.isBlank()) {
|
||||
call.respond(HttpStatusCode.BadRequest, "Bitte füllen Sie alle Felder aus")
|
||||
return@post
|
||||
}
|
||||
val getUser = repository.findByEmail(loginRequest.email)
|
||||
if (getUser == null || !repository.verifyPassword(loginRequest.passwordPlain, getUser.passwordHash)) {
|
||||
call.respond(HttpStatusCode.Unauthorized, "Ungültige Anmeldedaten")
|
||||
return@post
|
||||
}
|
||||
val token = jwtService.generateToken(getUser.id)
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
AuthResponse(
|
||||
token,
|
||||
userId = getUser.id,
|
||||
familyName = getUser.familyName,
|
||||
childAge = getUser.childAge,
|
||||
),
|
||||
)
|
||||
return@post
|
||||
|
||||
|
||||
}
|
||||
|
||||
authenticate("auth-jwt") {
|
||||
|
||||
// 1. Alle verfügbaren Aufgaben abrufen
|
||||
get("/api/v1/tasks") {
|
||||
val tasks = repository.getAllTasks()
|
||||
call.respond(tasks)
|
||||
}
|
||||
|
||||
// 2. Antwort auf eine Aufgabe überprüfen
|
||||
post("/api/v1/tasks/verify") {
|
||||
val request = call.receive<TaskVerifyRequest>()
|
||||
val principal = call.principal<UserPrincipal>()
|
||||
val userId = principal?.userId
|
||||
if (userId == null) {
|
||||
call.respond(
|
||||
HttpStatusCode.Unauthorized,
|
||||
mapOf("error" to "Ungültiges oder abgelaufenes Token")
|
||||
)
|
||||
return@post
|
||||
}
|
||||
val taskInfo = repository.getTaskAnswerAndReward(request.taskId)
|
||||
if (taskInfo == null) {
|
||||
call.respond(
|
||||
TaskVerifyResponse(
|
||||
isCorrect = false,
|
||||
earnedMinutes = 0,
|
||||
message = "Aufgabe nicht gefunden!",
|
||||
),
|
||||
)
|
||||
return@post
|
||||
}
|
||||
|
||||
val (correctAnswer, reward) = taskInfo
|
||||
val isCorrect = request.selectedAnswer.trim() == correctAnswer.trim()
|
||||
|
||||
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!",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
get("/api/v1/screentime") {
|
||||
val principal = call.principal<UserPrincipal>()
|
||||
val userid =
|
||||
principal?.userId
|
||||
?: run {
|
||||
call.respond(HttpStatusCode.Unauthorized, mapOf("error" to "Ungültiger Token"))
|
||||
return@get
|
||||
}
|
||||
val remainingSeconds = repository.getScreentime(userid)
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
SyncResponse(
|
||||
remainingSeconds = remainingSeconds,
|
||||
isBlocked = remainingSeconds <= 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// 3. Bildschirmzeit synchronisieren
|
||||
post("/api/v1/screentime/sync") {
|
||||
val request = call.receive<SyncRequest>()
|
||||
|
||||
// Wir holen die echte, fälschungssichere userId aus dem Login-Token:
|
||||
val principal = call.principal<UserPrincipal>()
|
||||
val userId =
|
||||
principal?.userId ?: request.userId // Fallback auf request.userId, falls token noch fehlt
|
||||
|
||||
val currentSeconds = repository.getScreentime(userId)
|
||||
var newSeconds = currentSeconds - request.usedSecondsSinceLastSync
|
||||
if (newSeconds < 0) newSeconds = 0
|
||||
|
||||
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!",
|
||||
SyncResponse(
|
||||
remainingSeconds = newSeconds,
|
||||
isBlocked = newSeconds <= 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
get("/api/v1/screentime") {
|
||||
val principal = call.principal<UserPrincipal>()
|
||||
val userid =
|
||||
principal?.userId
|
||||
?: run {
|
||||
call.respond(HttpStatusCode.Unauthorized, mapOf("error" to "Ungültiger Token"))
|
||||
return@get
|
||||
}
|
||||
val remainingSeconds = repository.getScreentime(userid)
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
SyncResponse(
|
||||
remainingSeconds = remainingSeconds,
|
||||
isBlocked = remainingSeconds <= 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// 3. Bildschirmzeit synchronisieren
|
||||
post("/api/v1/screentime/sync") {
|
||||
val request = call.receive<SyncRequest>()
|
||||
|
||||
// Wir holen die echte, fälschungssichere userId aus dem Login-Token:
|
||||
val principal = call.principal<UserPrincipal>()
|
||||
val userId = principal?.userId ?: request.userId // Fallback auf request.userId, falls token noch fehlt
|
||||
|
||||
val currentSeconds = repository.getScreentime(userId)
|
||||
var newSeconds = currentSeconds - request.usedSecondsSinceLastSync
|
||||
if (newSeconds < 0) newSeconds = 0
|
||||
|
||||
repository.updateScreentime(userId, newSeconds)
|
||||
|
||||
call.respond(
|
||||
SyncResponse(
|
||||
remainingSeconds = newSeconds,
|
||||
isBlocked = newSeconds <= 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue