Skip to content

Commit

Permalink
Added handlers to request status of submissions
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaro committed Jul 10, 2024
1 parent 2312f89 commit c9b4950
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 23 deletions.
7 changes: 6 additions & 1 deletion backend/src/main/kotlin/dev/dres/api/rest/RestApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import dev.dres.api.rest.handler.log.ResultLogHandler
import dev.dres.api.rest.handler.preview.*
import dev.dres.api.rest.handler.scores.ListEvaluationScoreHandler
import dev.dres.api.rest.handler.submission.SubmissionHandler
import dev.dres.api.rest.handler.submission.SubmissionStatusHandler
import dev.dres.api.rest.handler.system.CurrentTimeHandler
import dev.dres.api.rest.handler.system.InfoHandler
import dev.dres.api.rest.handler.system.LoginHandler
Expand Down Expand Up @@ -148,7 +149,11 @@ object RestApi {
GetTeamLogoHandler(),

// Submission
SubmissionHandler(store),
SubmissionHandler(),

// Submission Status
SubmissionStatusHandler(store),
SubmissionStatusHandler(store),

// Log
QueryLogHandler(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package dev.dres.api.rest.handler.submission

import dev.dres.api.rest.AccessManager
import dev.dres.api.rest.RestApi
import dev.dres.api.rest.handler.AccessManagedRestHandler
import dev.dres.api.rest.handler.GetRestHandler
import dev.dres.api.rest.types.evaluation.submission.ApiSubmission
import dev.dres.api.rest.types.evaluation.submission.ApiSubmissionList
import dev.dres.api.rest.types.status.ErrorStatus
import dev.dres.api.rest.types.status.ErrorStatusException
import dev.dres.api.rest.types.users.ApiRole
import dev.dres.data.model.run.RunActionContext.Companion.runActionContext
import io.javalin.http.Context
import io.javalin.openapi.*
import jetbrains.exodus.database.TransientEntityStore

class SubmissionAllStatusHandler(private val store: TransientEntityStore) : GetRestHandler<ApiSubmissionList>,
AccessManagedRestHandler {

override val permittedRoles = setOf(ApiRole.PARTICIPANT)

override val apiVersion = RestApi.LATEST_API_VERSION

override val route = "submission/{evaluationId}/all"


@OpenApi(
summary = "Endpoint provide the information about all submissions of a team.",
path = "/api/v2/submission/{evaluationId}/{submissionId}",
methods = [HttpMethod.GET],
operationId = OpenApiOperation.AUTO_GENERATE,
pathParams = [
OpenApiParam(
"evaluationId",
String::class,
"The ID of the evaluation the submission belongs to.",
required = true
),
],
queryParams = [
OpenApiParam("session", String::class, "Session Token")
],
responses = [
OpenApiResponse(
"200",
[OpenApiContent(ApiSubmissionList::class)],
description = "The submissions for this evaluation."
),
OpenApiResponse("404", [OpenApiContent(ErrorStatus::class)]),
],
tags = ["Submission"]
)
override fun doGet(ctx: Context): ApiSubmissionList {

val rac = ctx.runActionContext()

val runManager = AccessManager.getRunManagerForUser(rac.userId).find { it.id == rac.evaluationId }
?: throw ErrorStatusException(404, "Evaluation with ID '${rac.evaluationId}' could not be found.", ctx)

val teamId = runManager.template.teams.singleOrNull { it.users.any { u -> u.id == rac.userId } }?.id

if (teamId == null) {
throw ErrorStatusException(404, "No valid team found in evaluation with ID '${rac.evaluationId}'.", ctx)
}

val submissions = this.store.transactional(true) {
runManager.allSubmissions().asSequence().filter { it.teamId == teamId }.map { it.toApi() }.toList()
}

return ApiSubmissionList(submissions)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ import dev.dres.api.rest.handler.AccessManagedRestHandler
import dev.dres.api.rest.handler.PostRestHandler
import dev.dres.api.rest.types.evaluation.submission.ApiClientSubmission
import dev.dres.api.rest.types.evaluation.submission.ApiSubmission
import dev.dres.api.rest.types.evaluation.submission.ApiVerdictStatus
import dev.dres.api.rest.types.status.ErrorStatus
import dev.dres.api.rest.types.status.ErrorStatusException
import dev.dres.api.rest.types.status.SuccessStatus
import dev.dres.api.rest.types.users.ApiRole
import dev.dres.data.model.run.RunActionContext.Companion.runActionContext
import dev.dres.data.model.submissions.DbSubmission
import dev.dres.data.model.submissions.DbVerdictStatus
import dev.dres.data.model.submissions.VerdictStatus
import dev.dres.run.audit.AuditLogSource
import dev.dres.run.audit.AuditLogger
import dev.dres.run.exceptions.IllegalRunStateException
Expand All @@ -25,14 +20,9 @@ import io.javalin.http.BadRequestResponse
import io.javalin.http.Context
import io.javalin.http.bodyAsClass
import io.javalin.openapi.*
import jetbrains.exodus.database.TransientEntityStore
import kotlinx.dnq.query.filter
import kotlinx.dnq.query.first
import kotlinx.dnq.query.firstOrNull
import kotlinx.dnq.transactional
import org.slf4j.LoggerFactory

class SubmissionHandler(private val store: TransientEntityStore) : PostRestHandler<ApiSubmission>,
class SubmissionHandler : PostRestHandler<ApiSubmission>,
AccessManagedRestHandler {

override val permittedRoles = setOf(ApiRole.PARTICIPANT)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package dev.dres.api.rest.handler.submission

import dev.dres.api.rest.AccessManager
import dev.dres.api.rest.RestApi
import dev.dres.api.rest.handler.AccessManagedRestHandler
import dev.dres.api.rest.handler.GetRestHandler
import dev.dres.api.rest.types.evaluation.submission.ApiSubmission
import dev.dres.api.rest.types.status.ErrorStatus
import dev.dres.api.rest.types.status.ErrorStatusException
import dev.dres.api.rest.types.users.ApiRole
import dev.dres.data.model.run.RunActionContext.Companion.runActionContext
import io.javalin.http.Context
import io.javalin.openapi.*
import jetbrains.exodus.database.TransientEntityStore

class SubmissionStatusHandler(private val store: TransientEntityStore) : GetRestHandler<ApiSubmission>,
AccessManagedRestHandler {

override val permittedRoles = setOf(ApiRole.PARTICIPANT)

override val apiVersion = RestApi.LATEST_API_VERSION

override val route = "submission/{evaluationId}/{submissionId}"


@OpenApi(
summary = "Endpoint provide the information about a given submission.",
path = "/api/v2/submission/{evaluationId}/{submissionId}",
methods = [HttpMethod.GET],
operationId = OpenApiOperation.AUTO_GENERATE,
pathParams = [
OpenApiParam(
"evaluationId",
String::class,
"The ID of the evaluation the submission belongs to.",
required = true
),
OpenApiParam(
"submissionId",
String::class,
"The ID of the submission.",
required = true
),
],
queryParams = [
OpenApiParam("session", String::class, "Session Token")
],
responses = [
OpenApiResponse(
"200",
[OpenApiContent(ApiSubmission::class)],
description = "The submission."
),
OpenApiResponse("404", [OpenApiContent(ErrorStatus::class)]),
],
tags = ["Submission"]
)
override fun doGet(ctx: Context): ApiSubmission {

val rac = ctx.runActionContext()

val runManager = AccessManager.getRunManagerForUser(rac.userId).find { it.id == rac.evaluationId }
?: throw ErrorStatusException(404, "Evaluation with ID '${rac.evaluationId}' could not be found.", ctx)

val submissionId = ctx.pathParam("submissionId")

val submission = this.store.transactional(true) {
runManager.allSubmissions().find { it.id == submissionId }?.toApi()
}

if (submission == null) {
throw ErrorStatusException(404, "Submission with ID '${submissionId}' not found.", ctx)
}

val teamId = runManager.template.teams.singleOrNull { it.users.any { u -> u.id == rac.userId } }?.id

if (submission.teamId != teamId) {
throw ErrorStatusException(404, "No valid submission found", ctx)
}

return submission
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.dres.api.rest.types.evaluation.submission

import kotlinx.serialization.Serializable

@Serializable
data class ApiSubmissionList(val submissions: List<ApiSubmission>)
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,9 @@ class InteractiveAsynchronousRunManager(
/**
* List of all [DbSubmission]s for this [InteractiveAsynchronousRunManager], irrespective of the [DbTask] it belongs to.
*
* @param context The [RunActionContext] used for the invocation.
* @return List of [DbSubmission]s.
*/
override fun allSubmissions(context: RunActionContext): List<DbSubmission> = this.stateLock.read {
override fun allSubmissions(): List<DbSubmission> = this.stateLock.read {
this.evaluation.taskRuns.flatMap { it.getDbSubmissions() }
}

Expand Down
8 changes: 0 additions & 8 deletions backend/src/main/kotlin/dev/dres/run/InteractiveRunManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,6 @@ interface InteractiveRunManager : RunManager {
*/
fun updateSubmission(context: RunActionContext, submissionId: SubmissionId, submissionStatus: ApiVerdictStatus): Boolean

/**
* List of all [DbSubmission]s for this [InteractiveRunManager], irrespective of the [DbTask] it belongs to.
*
* @param context The [RunActionContext] used for the invocation.
* @return List of [DbSubmission]s
*/
fun allSubmissions(context: RunActionContext): List<DbSubmission>

/**
* List of [DbSubmission]s for the current [DbTask].
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ class InteractiveSynchronousRunManager(
* @param context The [RunActionContext] used for the invocation.
* @return List of [DbSubmission]s.
*/
override fun allSubmissions(context: RunActionContext): List<DbSubmission> =
override fun allSubmissions(): List<DbSubmission> =
this.evaluation.taskRuns.flatMap { it.getDbSubmissions() }


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dev.dres.api.rest.types.evaluation.submission.ApiClientSubmission
import dev.dres.api.rest.types.evaluation.submission.ApiSubmission
import dev.dres.data.model.run.*
import dev.dres.data.model.run.interfaces.TaskId
import dev.dres.data.model.submissions.DbSubmission
import dev.dres.run.score.scoreboard.Scoreboard
import dev.dres.run.validation.interfaces.JudgementValidator
import jetbrains.exodus.database.TransientEntityStore
Expand Down Expand Up @@ -206,6 +207,10 @@ class NonInteractiveRunManager(
} */
}

override fun allSubmissions(): List<DbSubmission> {
TODO("Not yet implemented")
}

override fun reScore(taskId: TaskId) {
TODO("Not yet implemented")
}
Expand Down
7 changes: 7 additions & 0 deletions backend/src/main/kotlin/dev/dres/run/RunManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ interface RunManager : Runnable {
*/
fun postSubmission(context: RunActionContext, submission: ApiClientSubmission) : ApiSubmission

/**
* List of all [DbSubmission]s for this [InteractiveRunManager], irrespective of the [DbTask] it belongs to.
*
* @return List of [DbSubmission]s
*/
fun allSubmissions(): List<DbSubmission>

/**
* Returns a list of viewer [ViewerInfo]s for this [RunManager] alongside with their respective state.
*
Expand Down

0 comments on commit c9b4950

Please sign in to comment.