Compare commits

...

2 Commits

Author SHA1 Message Date
calboo
b77f2fa371 patching values 2025-11-30 21:59:05 +01:00
calboo
7a100c96c9 settzing an getting values 2025-11-30 21:52:51 +01:00
13 changed files with 342 additions and 5 deletions

View File

@@ -15,6 +15,8 @@ import io.ktor.server.websocket.pingPeriod
import io.ktor.server.websocket.timeout
import kotlinx.serialization.json.Json
import org.calvin.erfmann.api.plugins.configureRouting
import org.calvin.erfmann.stuff.authService
import org.calvin.erfmann.theGoodStuff.PoolManager
import java.time.Duration
class apiServ {
@@ -23,7 +25,8 @@ class apiServ {
var authService = authService("password")
var poolManager = PoolManager()
@@ -45,7 +48,8 @@ class apiServ {
masking = false
}
configureRouting(
authService,
poolManager
)
}
}

View File

@@ -10,13 +10,21 @@ import io.ktor.server.application.Application
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.routing.routing
import kotlinx.serialization.json.Json
import org.calvin.erfmann.api.routes.getValue
import org.calvin.erfmann.api.routes.helloRoutes
import org.calvin.erfmann.api.routes.login
import org.calvin.erfmann.api.routes.patchValue
import org.calvin.erfmann.api.routes.setValue
import org.calvin.erfmann.stuff.authService
import org.calvin.erfmann.theGoodStuff.PoolManager
fun Application.configureRouting() {
fun Application.configureRouting(authService: authService, poolManager: PoolManager) {
routing {
helloRoutes()
login(authService)
getValue(authService, poolManager)
setValue(authService, poolManager)
patchValue(authService, poolManager)
}
}

View File

@@ -0,0 +1,40 @@
package org.calvin.erfmann.api.routes
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import kotlinx.serialization.Serializable
import org.calvin.erfmann.stuff.authService
import org.calvin.erfmann.theGoodStuff.PoolManager
@Serializable
data class GetValueRequest(val token: String, val pool: String, val key: String,)
fun Route.getValue(authService: authService, poolManager: PoolManager) {
get("/value") {
val request = call.receive<GetValueRequest>()
val isValid = authService.isTokenValid(request.token)
if (isValid) {
val pool = poolManager.getPool(request.pool)
if (pool != null) {
val value = pool.getValueValue(request.key)
if (value != null) {
call.respond(mapOf("value" to value))
} else {
call.respond(mapOf("error" to "Key not found"))
}
} else {
call.respond(mapOf("error" to "Pool not found"))
}
} else {
call.respond(mapOf("error" to "Invalid token"))
}
}
}

View File

@@ -5,6 +5,10 @@ import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import kotlinx.serialization.Serializable
fun Route.helloRoutes() {
route("/hello") {

View File

@@ -0,0 +1,31 @@
package org.calvin.erfmann.api.routes
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
import kotlinx.serialization.Serializable
import org.calvin.erfmann.stuff.authService
@Serializable
data class LoginRequest(val password: String)
fun Route.login(authService: authService) {
post("/login") {
val request = call.receive<LoginRequest>()
val token = authService.getToken(request.password)
if (token != null) {
call.respond(mapOf("token" to token))
} else {
call.respond(mapOf("error" to "Invalid password"))
}
}
}

View File

@@ -0,0 +1,41 @@
package org.calvin.erfmann.api.routes
import io.ktor.server.routing.patch
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.post
import kotlinx.serialization.Serializable
import org.calvin.erfmann.stuff.authService
import org.calvin.erfmann.theGoodStuff.PoolManager
@Serializable
data class PatchValueRequest(val token: String, val pool: String, val key: String, val value: String)
fun Route.patchValue(authService: authService, poolManager: PoolManager) {
patch("/value") {
val request = call.receive<SetValueRequest>()
val isValid = authService.isTokenValid(request.token)
if (isValid) {
val pool = poolManager.getPool(request.pool)
if (pool != null) {
pool.setValueValue(request.key, request.value)
call.respond(mapOf("status" to "success"))
} else {
call.respond(mapOf("error" to "Pool not found"))
}
} else {
call.respond(mapOf("error" to "Invalid token"))
}
}
}

View File

@@ -0,0 +1,38 @@
package org.calvin.erfmann.api.routes
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.post
import kotlinx.serialization.Serializable
import org.calvin.erfmann.stuff.authService
import org.calvin.erfmann.theGoodStuff.PoolManager
@Serializable
data class SetValueRequest(val token: String, val pool: String, val key: String, val value: String)
fun Route.setValue(authService: authService, poolManager: PoolManager) {
post("/value") {
val request = call.receive<SetValueRequest>()
val isValid = authService.isTokenValid(request.token)
if (isValid) {
val pool = poolManager.getPool(request.pool)
if (pool != null) {
pool.setValueValue(request.key, request.value)
call.respond(mapOf("status" to "success"))
} else {
poolManager.createPool(request.pool).setValueValue(request.key, request.value)
call.respond(mapOf("status" to "success"))
}
} else {
call.respond(mapOf("error" to "Invalid token"))
}
}
}

View File

@@ -0,0 +1,18 @@
package org.calvin.erfmann.api.utils
import java.security.SecureRandom
class tokenGenerator {
private val CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
private val secureRandom = SecureRandom()
/**
* Generiert einen sicheren Token.
* @param length Standardmäßig 32 Zeichen, kann aber angepasst werden.
*/
fun generate(length: Int = 32): String {
return (1..length)
.map { CHARACTERS[secureRandom.nextInt(CHARACTERS.length)] }
.joinToString("")
}
}

View File

@@ -0,0 +1,30 @@
package org.calvin.erfmann.stuff
import org.calvin.erfmann.api.utils.tokenGenerator
class authService(password: String) {
val password: String = password
var activeTokens = mutableListOf<String>()
fun getToken(inputPassword: String): String?{
if (inputPassword != password){
return null
}
val token = tokenGenerator().generate()
activeTokens.add(token)
return token
}
fun isTokenValid(token: String): Boolean{
return activeTokens.contains(token)
}
}

View File

@@ -0,0 +1,46 @@
package org.calvin.erfmann.theGoodStuff
class Pool(initName: String) {
var name: String = initName
var values: MutableMap<String, Value> = mutableMapOf()
fun getValueValue(key: String): String? {
val value = values[key]
return value?.getValueValue()
}
fun setValueValue(key: String, newValue: String) {
val value = values[key]
if (value != null) {
value.setValueValue(newValue)
} else {
values[key] = Value(key, newValue)
}
}
fun updateValueValue(key: String, newValue: String) {
val value = values[key]
if (value != null) {
value.setValueValue(newValue)
}
}
fun getVersion(key: String, version: Long): String? {
val value = values[key]
return value?.getVersion(version)
}
fun deleteValue(key: String) {
values.remove(key)
}
fun isKeyPresent(key: String): Boolean {
return values.containsKey(key)
}
}

View File

@@ -0,0 +1,24 @@
package org.calvin.erfmann.theGoodStuff
class PoolManager{
var pools: MutableMap<String, Pool> = mutableMapOf()
fun getPool(poolName: String): Pool? {
return pools[poolName]
}
fun createPool(poolName: String): Pool {
val pool = Pool(poolName)
pools[poolName] = pool
return pool
}
fun deletePool(poolName: String) {
pools.remove(poolName)
}
fun isPoolPresent(poolName: String): Boolean {
return pools.containsKey(poolName)
}
}

View File

@@ -0,0 +1,38 @@
package org.calvin.erfmann.theGoodStuff
class Value(initKey: String, initValue: String) {
// Das einfachste Value Element
var key: String = initKey
var value: String = initValue
var lastUpdated: Long = System.currentTimeMillis()
var createdAt: Long = System.currentTimeMillis()
var lastAcccessed: Long = System.currentTimeMillis()
var currentVersion: Long = 0
var versions = mutableListOf<ValueVersion>()
fun getValueValue(): String {
this.lastAcccessed = System.currentTimeMillis()
return this.value
}
fun getCurrentValueVersion(): Long {
return this.currentVersion
}
fun setValueValue(newValue: String) {
versions.add(ValueVersion(this.value , this.currentVersion))
this.value = newValue
this.lastUpdated = System.currentTimeMillis()
this.currentVersion += 1
}
fun getVersion(version: Long): String? {
val ver = versions.find { it.version == version }
return ver?.getValueValue()
}
}

View File

@@ -0,0 +1,15 @@
package org.calvin.erfmann.theGoodStuff
class ValueVersion(initValue: String, initVersion: Long) {
// Eine Version eines Values
var value: String = initValue
var lastAcccessed: Long = 1
var version : Long = initVersion
fun getValueValue(): String {
this.lastAcccessed = System.currentTimeMillis()
return this.value
}
}