save changed marks

This commit is contained in:
walamana
2023-09-18 11:51:41 +02:00
parent 00cca5ca9a
commit 24f14da9b2
16 changed files with 300 additions and 119 deletions

View File

@@ -2,5 +2,5 @@ ktor_version=2.3.3
kotlin_version=1.9.0
logback_version=1.2.11
kotlin.code.style=official
exposed_version=0.41.1
exposed_version=0.43.0
h2_version=2.1.214

View File

@@ -37,7 +37,7 @@ object MarksDao {
}
suspend fun setMark(ministrantId: Int, gottesdienstId: Int, value: Int): Boolean = dbQuery {
Marks.insert {
Marks.upsert {
it[Marks.mid] = ministrantId
it[Marks.gid] = gottesdienstId
it[Marks.value] = value

View File

@@ -27,6 +27,7 @@ data class Ministrant(
@Serializable
data class SimplifiedMinistrant(
val id: Int,
val username: String,
val firstname: String,
val lastname: String
)
@@ -44,10 +45,10 @@ object Ministranten : Table() {
}
object MinistrantenDao {
private fun resultRowToMinistrant(row: ResultRow, showPasswordHash: Boolean = false) = Ministrant (
private fun resultRowToMinistrant(row: ResultRow, showPasswordHash: Boolean = false) = Ministrant(
row[Ministranten.id],
row[Ministranten.username],
if(showPasswordHash) row[Ministranten.passwordHash] else "",
if (showPasswordHash) row[Ministranten.passwordHash] else "",
row[Ministranten.firstname],
row[Ministranten.lastname],
Date(row[Ministranten.birthday]),
@@ -59,8 +60,18 @@ object MinistrantenDao {
}
suspend fun simplifiedMinistranten(): List<SimplifiedMinistrant> = dbQuery {
Ministranten.selectAll().map { row ->
SimplifiedMinistrant(row[Ministranten.id], row[Ministranten.firstname], row[Ministranten.lastname])
Ministranten.slice(
Ministranten.id,
Ministranten.username,
Ministranten.firstname,
Ministranten.lastname
).selectAll().map { row ->
SimplifiedMinistrant(
row[Ministranten.id],
row[Ministranten.username],
row[Ministranten.firstname],
row[Ministranten.lastname]
)
}
}
@@ -70,7 +81,14 @@ object MinistrantenDao {
}.firstOrNull()
}
suspend fun createMinistrant(username: String, passwordHash: String, firstname: String, lastname: String, birthday: Date, privileges: List<String>) = dbQuery {
suspend fun createMinistrant(
username: String,
passwordHash: String,
firstname: String,
lastname: String,
birthday: Date,
privileges: List<String>
) = dbQuery {
val statement = Ministranten.insert {
it[Ministranten.username] = username
it[Ministranten.passwordHash] = ""
@@ -95,14 +113,14 @@ object MinistrantenDao {
lastname: String? = null,
birthday: Date? = null,
privileges: List<String>? = null
) = dbQuery{
Ministranten.update({Ministranten.id eq id}) {
if(username != null) it[Ministranten.username] = username
if(passwordHash != null) it[Ministranten.passwordHash] = passwordHash
if(firstname != null) it[Ministranten.firstname] = firstname
if(lastname != null) it[Ministranten.lastname] = lastname
if(birthday != null) it[Ministranten.birthday] = birthday.time
if(privileges != null) it[Ministranten.privileges] = privileges.joinToString(",")
) = dbQuery {
Ministranten.update({ Ministranten.id eq id }) {
if (username != null) it[Ministranten.username] = username
if (passwordHash != null) it[Ministranten.passwordHash] = passwordHash
if (firstname != null) it[Ministranten.firstname] = firstname
if (lastname != null) it[Ministranten.lastname] = lastname
if (birthday != null) it[Ministranten.birthday] = birthday.time
if (privileges != null) it[Ministranten.privileges] = privileges.joinToString(",")
}
}
}

View File

@@ -17,6 +17,7 @@ import java.util.*
const val SALT_ROUNDS = 10;
data class JWTEnvironment(
val secret: String,
val issuer: String,
@@ -45,7 +46,7 @@ fun Application.configureSecurity() {
}
fun Application.getJWTEnvironment(): JWTEnvironment{
fun Application.getJWTEnvironment(): JWTEnvironment {
val secret = environment.config.property("jwt.secret").getString()
val issuer = environment.config.property("jwt.issuer").getString()
@@ -58,12 +59,12 @@ fun Payload.mid() = getClaim("id").asInt()
object Security {
fun DEFAULT_EXPIRY() = Date(System.currentTimeMillis() + 1000*60*60);
fun DEFAULT_EXPIRY() = Date(System.currentTimeMillis() + 1000 * 60 * 60);
suspend fun authenticateUser(application: Application, username: String, password: String): Ministrant? {
if(username == "admin") {
if (username == "admin") {
val adminPw = application.environment.config.property("admin.password").getString()
if(adminPw == password) {
if (adminPw == password) {
val allMinis = MinistrantenDao.allMinistranten().map { it.username }
return Ministrant(
0, "admin", "", "admin", "admin", Date(), allMinis
@@ -75,7 +76,7 @@ object Security {
val ministrant = MinistrantenDao.getMinistrant(username, true)
?: return null
if(!BCrypt.verifyer().verify(password.toCharArray(), ministrant.passwordHash).verified) {
if (!BCrypt.verifyer().verify(password.toCharArray(), ministrant.passwordHash).verified) {
return null
}
@@ -95,10 +96,11 @@ object Security {
}
fun createToken(jwtEnv: JWTEnvironment, ministrant: Ministrant) = JWT.create()
.withAudience(jwtEnv.audience)
.withIssuer(jwtEnv.issuer)
.withClaim("username", ministrant.username)
.withClaim("id", ministrant.id)
.withExpiresAt(DEFAULT_EXPIRY())
.sign(Algorithm.HMAC256(jwtEnv.secret))
.withAudience(jwtEnv.audience)
.withIssuer(jwtEnv.issuer)
.withClaim("username", ministrant.username)
.withClaim("id", ministrant.id)
.withClaim("privileges", ministrant.privileges)
.withExpiresAt(DEFAULT_EXPIRY())
.sign(Algorithm.HMAC256(jwtEnv.secret))
}

View File

@@ -28,6 +28,7 @@ data class AuthenticationRequest(
@Serializable
data class AuthenticationResult(
val success: Boolean,
val token: String? = null,
val privileges: List<String>? = null,
)
@@ -61,7 +62,7 @@ fun Route.configureAuthenticationRoutes() {
"token=$token; HttpOnly; Expires=$expiry"
)
call.respond(AuthenticationResult(true, ministrant.privileges))
call.respond(AuthenticationResult(true, token, ministrant.privileges))
}
authenticate {

View File

@@ -8,6 +8,7 @@ import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.util.*
fun Route.configureMarksView() {
route("/marks") {
get {
@@ -15,22 +16,26 @@ fun Route.configureMarksView() {
call.respond(data)
}
put {
val data = call.receive<Mark>()
val mark = MarksDao.setMark(
data.mid,
data.gid,
data.value
)
val changedMarks = call.receive<List<Mark>>()
for(changedMark in changedMarks) {
val mark = MarksDao.setMark(
changedMark.mid,
changedMark.gid,
changedMark.value
)
}
call.respond(HttpStatusCode.OK)
}
patch {
// TODO: Access only by admin
val data = call.receive<Mark>()
val changed = MarksDao.setMark(
data.mid,
data.gid,
data.value
)
val changedMarks = call.receive<List<Mark>>()
for(changedMark in changedMarks) {
val mark = MarksDao.setMark(
changedMark.mid,
changedMark.gid,
changedMark.value
)
}
call.respond(HttpStatusCode.OK)
}
delete {