Skip to content

Commit

Permalink
Extend GraphQL API
Browse files Browse the repository at this point in the history
  • Loading branch information
erikhofer committed Oct 28, 2019
1 parent 8491993 commit fd5045f
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 35 deletions.
@@ -0,0 +1,18 @@
package de.code_freak.codefreak.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
import javax.servlet.Filter

@Configuration
class GraphQLConfiguration {

/**
* Enable JPA lazy loading for GraphQL DTOs
*/
@Bean
fun openFilter(): Filter {
return OpenEntityManagerInViewFilter()
}
}
29 changes: 0 additions & 29 deletions src/main/kotlin/de/code_freak/codefreak/graphql/AssignmentApi.kt

This file was deleted.

Expand Up @@ -9,12 +9,12 @@ object ScalarTypes {
private val scalars = mapOf(
UUID::class to GraphQLScalarType.Builder()
.name("ID")
.description("ID to java.util.UUID")
.description("UUID")
.coercing(UuidConverter())
.build(),
Instant::class to GraphQLScalarType.Builder()
.name("DateTime")
.description("DateTime to java.time.Instant")
.description("UTC date and time in ISO-8601 format")
.coercing(DateTimeConverter())
.build()
)
Expand Down
Expand Up @@ -6,7 +6,7 @@ import org.springframework.stereotype.Component
import kotlin.reflect.KType

@Component
class CustomSchemaGeneratorHooksImpl : SchemaGeneratorHooks {
class SchemaGeneratorHooksImpl : SchemaGeneratorHooks {
override fun willGenerateGraphQLType(type: KType): GraphQLType? {
return type.classifier?.let { ScalarTypes.get(it) }
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/kotlin/de/code_freak/codefreak/graphql/ServiceAccess.kt
@@ -0,0 +1,16 @@
package de.code_freak.codefreak.graphql

import de.code_freak.codefreak.service.BaseService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component
import kotlin.reflect.KClass

@Component
class ServiceAccess {

@Autowired
private lateinit var applicationContext: ApplicationContext

fun <T : BaseService> getService(type: KClass<T>): T = applicationContext.getBean(type.java)
}
25 changes: 25 additions & 0 deletions src/main/kotlin/de/code_freak/codefreak/graphql/api/AnswerApi.kt
@@ -0,0 +1,25 @@
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLID
import com.expediagroup.graphql.annotations.GraphQLIgnore
import com.expediagroup.graphql.annotations.GraphQLName
import de.code_freak.codefreak.entity.Answer
import de.code_freak.codefreak.graphql.ServiceAccess
import de.code_freak.codefreak.service.evaluation.EvaluationService
import de.code_freak.codefreak.util.orNull

@GraphQLName("Answer")
class AnswerDto(@GraphQLIgnore val entity: Answer, @GraphQLIgnore val serviceAccess: ServiceAccess) {

@GraphQLID
val id = entity.id
val submission by lazy { SubmissionDto(entity.submission, serviceAccess) }
val task by lazy { TaskDto(entity.task, serviceAccess) }

val latestEvaluation by lazy {
serviceAccess.getService(EvaluationService::class)
.getLatestEvaluation(id)
.map { EvaluationDto(it, serviceAccess) }
.orNull()
}
}
@@ -0,0 +1,56 @@
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLID
import com.expediagroup.graphql.annotations.GraphQLIgnore
import com.expediagroup.graphql.annotations.GraphQLName
import com.expediagroup.graphql.spring.operations.Query
import de.code_freak.codefreak.auth.Authority
import de.code_freak.codefreak.auth.Role
import de.code_freak.codefreak.entity.Assignment
import de.code_freak.codefreak.graphql.ServiceAccess
import de.code_freak.codefreak.service.AssignmentService
import de.code_freak.codefreak.service.SubmissionService
import de.code_freak.codefreak.util.FrontendUtil
import graphql.schema.DataFetchingEnvironment
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.access.annotation.Secured
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional

@GraphQLName("Assignment")
class AssignmentDto(@GraphQLIgnore val entity: Assignment, @GraphQLIgnore val serviceAccess: ServiceAccess) {

@GraphQLID
val id = entity.id
val title = entity.title
val owner by lazy { UserDto(entity.owner) }
val deadline = entity.deadline
val closed = entity.closed
val tasks by lazy { entity.tasks.map { TaskDto(it, serviceAccess) } }

val submissions by lazy {
serviceAccess.getService(SubmissionService::class)
.findSubmissionsOfAssignment(id)
.map { SubmissionDto(it, serviceAccess) }
}
}

@Component
class AssignmentQuery : Query {

@Autowired
private lateinit var serviceAccess: ServiceAccess

@Transactional
@Secured(Authority.ROLE_STUDENT)
fun assignments(env: DataFetchingEnvironment): List<AssignmentDto> {
val assignmentService = serviceAccess.getService(AssignmentService::class)
val user = FrontendUtil.getCurrentUser()
val assignments = if (user.authorities.contains(Role.TEACHER)) {
assignmentService.findAllAssignments()
} else {
assignmentService.findAllAssignmentsForUser(user.entity.id)
}
return assignments.map { AssignmentDto(it, serviceAccess) }
}
}
@@ -1,4 +1,4 @@
package de.code_freak.codefreak.graphql
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLName
import com.expediagroup.graphql.spring.operations.Mutation
Expand Down
@@ -0,0 +1,25 @@
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLID
import com.expediagroup.graphql.annotations.GraphQLIgnore
import com.expediagroup.graphql.annotations.GraphQLName
import de.code_freak.codefreak.entity.Evaluation
import de.code_freak.codefreak.entity.EvaluationResult
import de.code_freak.codefreak.graphql.ServiceAccess

@GraphQLName("Evaluation")
class EvaluationDto(@GraphQLIgnore val entity: Evaluation, @GraphQLIgnore val serviceAccess: ServiceAccess) {

@GraphQLID
val id = entity.id
val answer by lazy { AnswerDto(entity.answer, serviceAccess) }
val createdAt = entity.createdAt
val results by lazy { entity.results.map { EvaluationResultDto(it) } }
}

@GraphQLName("EvaluationResult")
class EvaluationResultDto(@GraphQLIgnore val entity: EvaluationResult) {
val runnerName = entity.runnerName
val position = entity.position
val error = entity.error
}
@@ -0,0 +1,17 @@
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLID
import com.expediagroup.graphql.annotations.GraphQLIgnore
import com.expediagroup.graphql.annotations.GraphQLName
import de.code_freak.codefreak.entity.Submission
import de.code_freak.codefreak.graphql.ServiceAccess

@GraphQLName("Submission")
class SubmissionDto(@GraphQLIgnore val entity: Submission, @GraphQLIgnore val serviceAccess: ServiceAccess) {

@GraphQLID
val id = entity.id
val user by lazy { UserDto(entity.user) }
val assignment by lazy { AssignmentDto(entity.assignment, serviceAccess) }
val answers by lazy { entity.answers.map { AnswerDto(it, serviceAccess) } }
}
18 changes: 18 additions & 0 deletions src/main/kotlin/de/code_freak/codefreak/graphql/api/TaskApi.kt
@@ -0,0 +1,18 @@
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLID
import com.expediagroup.graphql.annotations.GraphQLIgnore
import com.expediagroup.graphql.annotations.GraphQLName
import de.code_freak.codefreak.entity.Task
import de.code_freak.codefreak.graphql.ServiceAccess

@GraphQLName("Task")
class TaskDto(@GraphQLIgnore val entity: Task, @GraphQLIgnore val serviceAccess: ServiceAccess) {

@GraphQLID
val id = entity.id
val title = entity.title
val position = entity.position
val body = entity.body
val assignment by lazy { AssignmentDto(entity.assignment, serviceAccess) }
}
@@ -1,4 +1,4 @@
package de.code_freak.codefreak.graphql
package de.code_freak.codefreak.graphql.api

import com.expediagroup.graphql.annotations.GraphQLID
import com.expediagroup.graphql.annotations.GraphQLName
Expand Down
Expand Up @@ -5,6 +5,7 @@ import org.apache.commons.io.output.ProxyOutputStream
import org.slf4j.Logger
import java.io.InputStream
import java.io.OutputStream
import java.util.Optional

fun String.withTrailingSlash(): String = if (endsWith("/")) this else "$this/"

Expand Down Expand Up @@ -32,3 +33,5 @@ fun Logger.error(e: Throwable) {
error(e.message)
e.printStackTrace()
}

fun <T> Optional<T>.orNull(): T? = orElse(null)
2 changes: 1 addition & 1 deletion src/main/resources/application.yml
Expand Up @@ -36,7 +36,7 @@ logging:

graphql:
packages:
- "de.code_freak.codefreak.graphql"
- "de.code_freak.codefreak.graphql.api"

server:
servlet:
Expand Down

0 comments on commit fd5045f

Please sign in to comment.