Skip to content

Commit

Permalink
Merge pull request #455 from dres-dev/dev
Browse files Browse the repository at this point in the history
v2.0.0-RC3
  • Loading branch information
sauterl authored Jan 13, 2024
2 parents 4cf3a97 + b95866e commit d1de7fb
Show file tree
Hide file tree
Showing 65 changed files with 302 additions and 95 deletions.
1 change: 1 addition & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ dependencies {
///// Kotlin
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: version_kotlin
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: version_kotlin
implementation group: 'org.jetbrains.kotlinx', name:'kotlinx-serialization-json', version: '1.6.2'
}

kapt {
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/kotlin/dev/dres/DRES.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import kotlin.system.exitProcess
*/
object DRES {
/** Version of DRES. */
const val VERSION = "2.0.0-RC1"
const val VERSION = "2.0.0-RC3"

/** Application root; should be relative to JAR file or classes path. */
val APPLICATION_ROOT: Path =
Expand Down
42 changes: 42 additions & 0 deletions backend/src/main/kotlin/dev/dres/api/rest/KotlinxJsonMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package dev.dres.api.rest

import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import io.javalin.json.JsonMapper
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
import java.lang.reflect.Type

object KotlinxJsonMapper : JsonMapper {

private val fallbackMapper = jacksonObjectMapper()

override fun <T : Any> fromJsonString(json: String, targetType: Type): T {

return try {
@Suppress("UNCHECKED_CAST")
val serializer = serializer(targetType) as KSerializer<T>
Json.decodeFromString(serializer, json)
} catch (e: SerializationException) {
null
} catch (e: IllegalStateException) {
null
} ?: fallbackMapper.readValue(json, fallbackMapper.typeFactory.constructType(targetType))

}

override fun toJsonString(obj: Any, type: Type): String {

return try {
val serializer = serializer(type)
Json.encodeToString(serializer, obj)
} catch (e: SerializationException) {
null
} catch (e: IllegalStateException) {
null
} ?: fallbackMapper.writeValueAsString(obj)

}
}
49 changes: 37 additions & 12 deletions backend/src/main/kotlin/dev/dres/api/rest/RestApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import org.eclipse.jetty.server.*
import org.eclipse.jetty.util.thread.QueuedThreadPool
import org.slf4j.LoggerFactory
import org.slf4j.MarkerFactory
import kotlin.math.min

/**
* This is a singleton instance of the RESTful API
Expand Down Expand Up @@ -101,8 +102,14 @@ object RestApi {
UserDetailsHandler(),

// Media
PreviewImageHandler(store, cache), /* [PreviewImageHandler] vs [PreviewImageTimelessHandler]: Optional path parameters are not allowed in OpenApi. [PreviewImageHandler] has timestamp as path parameter and must be initialised first */
PreviewImageTimelessHandler(store,cache), /* [PreviewImageHandler] vs [PreviewImageTimelessHandler]: Optional path parameters are not allowed in OpenApi */
PreviewImageHandler(
store,
cache
), /* [PreviewImageHandler] vs [PreviewImageTimelessHandler]: Optional path parameters are not allowed in OpenApi. [PreviewImageHandler] has timestamp as path parameter and must be initialised first */
PreviewImageTimelessHandler(
store,
cache
), /* [PreviewImageHandler] vs [PreviewImageTimelessHandler]: Optional path parameters are not allowed in OpenApi */
PreviewVideoHandler(store, cache),
GetExternalMediaHandler(), // Must be registered before GetMediaHandler, as route is similar
GetMediaHandler(store),
Expand All @@ -120,16 +127,16 @@ object RestApi {
ShowMediaItemHandler(),
ResolveMediaItemListByNameHandler(), // Must be before ListMediaItem
ListMediaItemHandler(),
if(DRES.CONFIG.externalMediaEndpointsEnabled){
if (DRES.CONFIG.externalMediaEndpointsEnabled) {
UploadExternalItemHandler()
}else{
} else {
null
},
ListExternalItemHandler(),
FindExternalItemHandler(),
if(DRES.CONFIG.externalMediaEndpointsEnabled){
if (DRES.CONFIG.externalMediaEndpointsEnabled) {
DeleteExternalItemHandler()
}else{
} else {
null
}, // Must be last of external/ route

Expand Down Expand Up @@ -219,9 +226,13 @@ object RestApi {
)

javalin = Javalin.create {

it.jsonMapper(KotlinxJsonMapper)

it.plugins.enableCors { cors ->
cors.add { corsPluginConfig ->
corsPluginConfig.reflectClientOrigin = true // anyHost() has similar implications and might be used in production? I'm not sure how to cope with production and dev here simultaneously
corsPluginConfig.reflectClientOrigin =
true // anyHost() has similar implications and might be used in production? I'm not sure how to cope with production and dev here simultaneously
corsPluginConfig.allowCredentials = true
}
}
Expand All @@ -234,7 +245,8 @@ object RestApi {
u.withOpenApiInfo { t ->
t.title = "DRES API"
t.version = DRES.VERSION
t.description = "API for DRES (Distributed Retrieval Evaluation Server), Version ${DRES.VERSION}"
t.description =
"API for DRES (Distributed Retrieval Evaluation Server), Version ${DRES.VERSION}"
val contact = OpenApiContact()
contact.url = "https://dres.dev"
contact.name = "The DRES Dev Team"
Expand All @@ -244,8 +256,9 @@ object RestApi {
// license.identifier = "MIT"
t.license = license
}
u.withSecurity(SecurityComponentConfiguration()
.withSecurityScheme("CookieAuth", CookieAuth(AccessManager.SESSION_COOKIE_NAME))
u.withSecurity(
SecurityComponentConfiguration()
.withSecurityScheme("CookieAuth", CookieAuth(AccessManager.SESSION_COOKIE_NAME))
)
}

Expand Down Expand Up @@ -294,7 +307,13 @@ object RestApi {
//check for session cookie
val cookieId = ctx.cookie(AccessManager.SESSION_COOKIE_NAME)
if (cookieId != null) {
val cookie = Cookie(AccessManager.SESSION_COOKIE_NAME, cookieId, maxAge = AccessManager.SESSION_COOKIE_LIFETIME, secure = true, sameSite = SameSite.NONE)
val cookie = Cookie(
AccessManager.SESSION_COOKIE_NAME,
cookieId,
maxAge = AccessManager.SESSION_COOKIE_LIFETIME,
secure = true,
sameSite = SameSite.NONE
)
ctx.cookie(cookie) //update cookie lifetime
ctx.attribute("session", cookieId) //store id in attribute for later use
}
Expand Down Expand Up @@ -365,7 +384,13 @@ object RestApi {


private val pool = QueuedThreadPool(
1000, 8, 60000, -1, null, null, NamedThreadFactory("JavalinPool")
32,
10,
60000,
-1,
null,
null,
NamedThreadFactory("JavalinPool")
)

val readyThreadCount: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ import dev.dres.data.model.run.RunActionContext.Companion.runActionContext
import dev.dres.data.model.submissions.*
import dev.dres.mgmt.cache.CacheManager
import dev.dres.run.InteractiveRunManager
import dev.dres.run.audit.AuditLogSource
import dev.dres.run.audit.AuditLogger
import dev.dres.run.exceptions.IllegalRunStateException
import dev.dres.run.exceptions.IllegalTeamIdException
import dev.dres.run.filter.SubmissionRejectedException
import dev.dres.utilities.extensions.sessionToken
import io.javalin.http.Context
import io.javalin.openapi.*
import jetbrains.exodus.database.TransientEntityStore
Expand Down Expand Up @@ -133,6 +136,14 @@ class LegacySubmissionHandler(private val store: TransientEntityStore, private v
} catch (e: IllegalTeamIdException) {
logger.info("Submission with unknown team id '${submission.teamId}' was received.")
throw ErrorStatusException(400, "Run manager does not know the given teamId ${submission.teamId}.", ctx)
} finally {
AuditLogger.submission(
submission,
rac.evaluationId!!,
AuditLogSource.REST,
ctx.sessionToken(),
ctx.ip()
)
}

/* Lookup verdict for submission and return it. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import io.javalin.http.BadRequestResponse
import io.javalin.http.Context
import io.javalin.openapi.*
import jetbrains.exodus.database.TransientEntityStore
import kotlinx.serialization.Serializable

/**
* A [PostRestHandler] that handles user-requests to login.
Expand All @@ -28,6 +29,7 @@ class LoginHandler() : RestHandler, PostRestHandler<ApiUser> {
override val route = "login"
override val apiVersion = RestApi.LATEST_API_VERSION

@Serializable
data class LoginRequest(var username: String, var password: String)

@OpenApi(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dev.dres.data.model.media.*
import kotlinx.dnq.query.filter
import kotlinx.dnq.query.first
import kotlinx.dnq.util.findById
import kotlinx.serialization.Serializable

/**
* The RESTful API equivalent for [DbMediaItem].
Expand All @@ -13,6 +14,7 @@ import kotlinx.dnq.util.findById
* @author Ralph Gasser
* @version 1.1.0
*/
@Serializable
data class ApiMediaItem(
override val mediaItemId: MediaItemId,
override val name: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
package dev.dres.api.rest.types.collection

import kotlinx.serialization.Serializable

@Serializable
data class ApiMediaItemMetaDataEntry(val key: String, val value: String)
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package dev.dres.api.rest.types.collection.time

import dev.dres.data.model.media.time.TemporalPoint
import kotlinx.serialization.Serializable

/**
* RESTful API representation of a [TemporalPoint].
*
* @version 1.0.0
* @author Ralph Gasser
*/
@Serializable
data class ApiTemporalPoint(val value: String, val unit: ApiTemporalUnit) {

companion object{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package dev.dres.api.rest.types.collection.time

import dev.dres.data.model.media.time.TemporalRange
import kotlinx.serialization.Serializable

/**
* RESTful API representation of a [TemporalRange].
*
* @version 1.0.0
* @author Ralph Gasser
*/
@Serializable
data class ApiTemporalRange(val start: ApiTemporalPoint, val end: ApiTemporalPoint) {
constructor(range: TemporalRange) : this(ApiTemporalPoint.fromTemporalPoint(range.start), ApiTemporalPoint.fromTemporalPoint(range.end))
fun toTemporalRange(fps: Float): TemporalRange = TemporalRange(start.toTemporalPoint(fps), end.toTemporalPoint(fps))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import dev.dres.run.InteractiveAsynchronousRunManager
import dev.dres.run.InteractiveSynchronousRunManager
import dev.dres.run.NonInteractiveRunManager
import dev.dres.run.RunManager
import kotlinx.serialization.Serializable

/**
* Contains the basic and most importantly static information about a [RunManager] that is relevant to a participant.
*
*/
@Serializable
data class ApiClientEvaluationInfo(
val id: String,
val name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package dev.dres.api.rest.types.evaluation

import dev.dres.api.rest.types.template.tasks.ApiTaskTemplate
import dev.dres.data.model.template.task.DbTaskTemplate
import kotlinx.serialization.Serializable

/**
* Basic and most importantly static information about a [DbTaskTemplate] relevant to the participant.
*/
@Serializable
data class ApiClientTaskTemplateInfo(
val name: String,
val taskGroup: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import dev.dres.api.rest.types.template.ApiEvaluationTemplate
import dev.dres.data.model.run.DbEvaluation
import dev.dres.data.model.run.interfaces.Evaluation
import dev.dres.data.model.run.interfaces.EvaluationId
import kotlinx.serialization.Serializable

/**
* The RESTful API equivalent of a [DbEvaluation].
Expand All @@ -12,6 +13,7 @@ import dev.dres.data.model.run.interfaces.EvaluationId
* @author Ralph Gasser
* @version 2.0.0
*/
@Serializable
data class ApiEvaluation(
override val evaluationId: EvaluationId,
val name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dev.dres.run.InteractiveAsynchronousRunManager
import dev.dres.run.InteractiveSynchronousRunManager
import dev.dres.run.NonInteractiveRunManager
import dev.dres.run.RunManager
import kotlinx.serialization.Serializable

/**
* Contains the basic and most importantly static information about a [RunManager].
Expand All @@ -14,6 +15,7 @@ import dev.dres.run.RunManager
* @author Ralph Gasser
* @version 1.1.0
*/
@Serializable
data class ApiEvaluationInfo(
val id: String,
val name: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package dev.dres.api.rest.types.evaluation

import dev.dres.run.*
import kotlinx.serialization.Serializable

@Serializable
data class ApiEvaluationOverview(val state: RunManagerStatus, val teamOverviews: List<ApiTeamTaskOverview>) {
companion object {
fun of(manager: InteractiveRunManager): ApiEvaluationOverview {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.dres.api.rest.types.evaluation

import dev.dres.data.model.run.RunActionContext
import dev.dres.run.*
import kotlinx.serialization.Serializable

/**
* Contains the information about the state of an [InteractiveRunManager].
Expand All @@ -10,6 +11,7 @@ import dev.dres.run.*
*
* @version 1.3.0
*/
@Serializable
data class ApiEvaluationState(
val evaluationId: String,
val evaluationStatus: ApiEvaluationStatus,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.dres.api.rest.types.evaluation

import dev.dres.api.rest.types.evaluation.submission.ApiVerdictStatus
import kotlinx.serialization.Serializable

/**
* Data transfer object for overriding a [ApiAnswerSet]'s verdict.
Expand All @@ -9,4 +10,5 @@ import dev.dres.api.rest.types.evaluation.submission.ApiVerdictStatus
* @author Loris Sauter
* @version 1.0
*/
@Serializable
data class ApiOverrideAnswerSetVerdictDto(val verdict: ApiVerdictStatus)
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package dev.dres.api.rest.types.evaluation
import dev.dres.api.rest.types.evaluation.submission.ApiSubmission
import dev.dres.data.model.run.interfaces.EvaluationId
import dev.dres.data.model.template.TemplateId
import kotlinx.serialization.Serializable

/**
* Encodes [ApiSubmission] data for a specific [EvaluationId] and (optionally) [EvaluationId].
*
* @author Loris Sauter
* @version 1.1.0
*/
@Serializable
data class ApiSubmissionInfo(val evaluationId: EvaluationId, val taskId: TemplateId, val submissions: List<ApiSubmission>)
Loading

0 comments on commit d1de7fb

Please sign in to comment.