Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3bd624e
Initial domain concept
alexstaeding Apr 5, 2024
7cb2251
Semester -> Term and add owner to Course
alexstaeding Apr 5, 2024
9ccf8cb
Add SubmissionGroup(Category) and refactor a bit
alexstaeding Apr 5, 2024
98f3827
Put SubmissionGroupCategory into SubmissionGroup as nested class
alexstaeding Apr 8, 2024
21ddaf6
Format
alexstaeding Apr 8, 2024
673e6c1
Add tables
alexstaeding Apr 16, 2024
f855c06
Unsolved issue with exposed
alexstaeding Apr 16, 2024
91c3872
Progess
alexstaeding Apr 17, 2024
85594bc
Rubric stuff
alexstaeding Apr 24, 2024
697c916
Merge branch 'master' into feature/domain
alexstaeding Apr 24, 2024
252d93b
Fix GradingRun
alexstaeding Apr 24, 2024
7268c68
More stuff
alexstaeding Apr 24, 2024
22dfe8a
Small cleanup
alexstaeding Apr 24, 2024
dc441a7
Merge branch 'master' into feature/domain
alexstaeding Apr 24, 2024
2088d7a
Remove term comment
alexstaeding Apr 24, 2024
7fdfe87
Clean up
alexstaeding Apr 24, 2024
831fcef
Yeet
alexstaeding Apr 24, 2024
ad07463
Fix style
alexstaeding Apr 24, 2024
8205adc
Extract domain interfaces
alexstaeding Apr 24, 2024
03517af
Work on user sql
alexstaeding Apr 24, 2024
f8cdcc8
Add repositories
alexstaeding Apr 25, 2024
fa47af8
Merge branch 'master' into feature/domain
alexstaeding Jun 14, 2024
9c3a6a7
Get graphql to work
alexstaeding Jun 19, 2024
e292756
Work on graph integration
alexstaeding Jun 20, 2024
2209c61
SizedIterableCollection limit and list
alexstaeding Jun 21, 2024
ba7e372
Continue work
alexstaeding Jun 22, 2024
b3a86e0
More stuff
alexstaeding Jul 8, 2024
0bc09fb
Remove ExecutionContext for now
alexstaeding Jul 8, 2024
41a920f
Clean up graphql endpoints for user
alexstaeding Jul 9, 2024
d2a0272
Remove recursion for list query
alexstaeding Jul 9, 2024
522568a
Clean up Users class
alexstaeding Jul 9, 2024
874e9e8
More work
alexstaeding Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
Expand All @@ -20,16 +21,19 @@ allprojects {
?.takeIf { version.toString().contains("SNAPSHOT") }
?.also { version = version.toString().replace("SNAPSHOT", "RC$it") }

tasks {
withType<KotlinCompile> {
kotlinOptions.jvmTarget = "17"
}
withType<JavaCompile> {
options.encoding = "UTF-8"
sourceCompatibility = "17"
targetCompatibility = "17"
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_21
freeCompilerArgs = listOf(
"-opt-in=kotlin.RequiresOptIn",
"-Xcontext-receivers",
)
}
}

java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
}

tasks {
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ volumes:

services:
db:
image: postgres:latest
image: postgres:16.3
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=admin
- POSTGRES_DB=lab
- POSTGRES_DB=sgl
ports:
- "5432:5432"

Expand Down
7 changes: 4 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ exposed = "0.49.0"

[libraries]
annotations = "org.jetbrains:annotations:24.0.1"
coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0"
# com.expediagroup:graphql-kotlin-ktor-server:7.0.2
graphql-server = { module = "com.expediagroup:graphql-kotlin-ktor-server", version.ref = "graphql" }
graphql-client = { module = "com.expediagroup:graphql-kotlin-ktor-client", version.ref = "graphql" }
Expand All @@ -25,7 +24,7 @@ ktor-server-status-pages = { module = "io.ktor:ktor-server-status-pages" }
ktor-serialization-kotlinx = { module = "io.ktor:ktor-serialization-kotlinx" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json" } # TODO: Remove
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }

kotlinx-coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0"
kubernetes-client = "io.fabric8:kubernetes-client:6.11.0"
logging-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" }
logging-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" }
Expand All @@ -44,11 +43,13 @@ protobuf-kotlin = "com.google.protobuf:protobuf-kotlin:4.26.1"

bcrypt = "org.mindrot:jbcrypt:0.4"

shiro = "org.apache.shiro:shiro-core:2.0.1"

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ktlint = "org.jlleitschuh.gradle.ktlint:11.6.1"
protobuf = "com.google.protobuf:0.9.4"
shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" }
shadow = { id = "io.github.goooler.shadow", version = "8.1.7" }
ktor = "io.ktor.plugin:2.3.10"
16 changes: 16 additions & 0 deletions hub/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {

dependencies {
implementation(libs.graphql.server)
implementation(libs.koin)
implementation(libs.ktor.server.netty)
implementation(libs.ktor.server.auth)
implementation(libs.ktor.server.contentnegotiation)
Expand All @@ -28,8 +29,23 @@ dependencies {
implementation(libs.ktor.server.call.logging)
implementation(libs.ktor.client.logging)
implementation(libs.kotlin.reflect)
implementation(libs.kotlinx.coroutines)
}

application {
mainClass.set("org.sourcegrade.lab.hub.MainKt")
}

tasks {
named<JavaExec>("runShadow") {
environment("SGL_DB_URL", "jdbc:postgresql://localhost:5432/sgl")
environment("SGL_DB_USER", "admin")
environment("SGL_DB_PASSWORD", "admin")
environment("SGL_DEPLOYMENT_URL", "http://localhost:8080")
environment("SGL_AUTH_URL", "http://localhost:8080/auth")
environment("SGL_AUTH_CLIENT_ID", "sgl")
environment("SGL_AUTH_CLIENT_SECRET", "sgl")
environment("SGL_AUTH_ACCESS_TOKEN_URL", "http://localhost:8080/auth/token")
environment("SGL_AUTH_SCOPES", "openid profile email")
}
}
25 changes: 23 additions & 2 deletions hub/src/main/kotlin/org/sourcegrade/lab/hub/Main.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
/*
* Lab - SourceGrade.org
* Copyright (C) 2019-2024 Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.sourcegrade.lab.hub

import io.ktor.server.netty.EngineMain
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty

fun main(args: Array<String>) = EngineMain.main(args)
fun main() {
embeddedServer(Netty, port = 7500) { module() }.start(wait = true)
}
121 changes: 100 additions & 21 deletions hub/src/main/kotlin/org/sourcegrade/lab/hub/Module.kt
Original file line number Diff line number Diff line change
@@ -1,49 +1,122 @@
/*
* Lab - SourceGrade.org
* Copyright (C) 2019-2024 Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.sourcegrade.lab.hub

import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks
import com.expediagroup.graphql.server.ktor.GraphQL
import com.expediagroup.graphql.server.ktor.graphQLGetRoute
import com.expediagroup.graphql.server.ktor.graphQLPostRoute
import com.expediagroup.graphql.server.ktor.graphQLSDLRoute
import com.expediagroup.graphql.server.ktor.graphiQLRoute
import graphql.schema.GraphQLType
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpMethod
import io.ktor.http.Url
import io.ktor.server.application.Application
import io.ktor.server.application.install
import io.ktor.server.config.tryGetString
import io.ktor.server.plugins.callloging.CallLogging
import io.ktor.server.plugins.cors.routing.CORS
import io.ktor.server.request.path
import io.ktor.server.routing.Routing
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.DatabaseConfig
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
import org.koin.ktor.ext.inject
import org.koin.ktor.plugin.Koin
import org.sourcegrade.lab.hub.db.CourseMemberships
import org.sourcegrade.lab.hub.db.Criteria
import org.sourcegrade.lab.hub.db.DBModule
import org.sourcegrade.lab.hub.db.GradedCriteria
import org.sourcegrade.lab.hub.db.GradedRubrics
import org.sourcegrade.lab.hub.db.GradingRuns
import org.sourcegrade.lab.hub.db.Rubrics
import org.sourcegrade.lab.hub.db.SubmissionGroupCategories
import org.sourcegrade.lab.hub.db.SubmissionGroupMemberships
import org.sourcegrade.lab.hub.db.Submissions
import org.sourcegrade.lab.hub.db.Terms
import org.sourcegrade.lab.hub.db.assignment.Assignments
import org.sourcegrade.lab.hub.db.course.Courses
import org.sourcegrade.lab.hub.db.user.Users
import org.sourcegrade.lab.hub.graphql.AssignmentMutations
import org.sourcegrade.lab.hub.graphql.AssignmentQueries
import org.sourcegrade.lab.hub.graphql.CourseMutations
import org.sourcegrade.lab.hub.graphql.CourseQueries
import org.sourcegrade.lab.hub.graphql.Scalars
import org.sourcegrade.lab.hub.graphql.UserMutations
import org.sourcegrade.lab.hub.graphql.UserQueries
import org.sourcegrade.lab.hub.http.authenticationModule
import org.sourcegrade.lab.hub.queries.CourseMutations
import org.sourcegrade.lab.hub.queries.CourseQueries
import org.sourcegrade.lab.hub.queries.HelloWorldQuery
import org.sourcegrade.lab.hub.queries.UserMutations
import org.sourcegrade.lab.hub.queries.UserQueries
import kotlin.reflect.KType

fun Application.module() {
val environment = environment
val url =
Url(
environment.config.tryGetString("ktor.deployment.url")
?: throw IllegalStateException("No deployment url set"),
install(Koin) {
modules(
module {
single<Logger> { LogManager.getLogger("SGL Supervisor") }
singleOf(::UserQueries)
singleOf(::UserMutations)
singleOf(::AssignmentQueries)
singleOf(::AssignmentMutations)
singleOf(::CourseQueries)
singleOf(::CourseMutations)
},
DBModule,
)

}
val databaseConfig =
DatabaseConfig {
keepLoadedReferencesOutOfTransaction = true
}

val logger by inject<Logger>()

logger.info("Connecting to database...")
Database.connect(
environment.config.tryGetString("ktor.db.url") ?: "",
url = getEnv("SGL_DB_URL"),
driver = "org.postgresql.Driver",
user = environment.config.tryGetString("ktor.db.user") ?: "",
password = environment.config.tryGetString("ktor.db.password") ?: "",
user = getEnv("SGL_DB_USER"),
password = getEnv("SGL_DB_PASSWORD"),
databaseConfig = databaseConfig,
)
logger.info("Finished connecting to database.")
logger.info("Creating tables...")
transaction {
SchemaUtils.createMissingTablesAndColumns(
Assignments,
CourseMemberships,
Courses,
Criteria,
GradedCriteria,
GradedRubrics,
GradingRuns,
Rubrics,
SubmissionGroupCategories,
SubmissionGroupMemberships,
Submissions,
Terms,
Users,
)
}
logger.info("Finished creating tables.")

install(CORS) {
allowMethod(HttpMethod.Options)
Expand All @@ -56,17 +129,21 @@ fun Application.module() {

install(GraphQL) {
schema {
hooks = object : SchemaGeneratorHooks {
override fun willGenerateGraphQLType(type: KType): GraphQLType? = Scalars.willGenerateGraphQLType(type)
}
packages = listOf("org.sourcegrade.lab.hub")
queries =
listOf(
HelloWorldQuery(),
UserQueries(),
CourseQueries(),
inject<UserQueries>().value,
inject<AssignmentQueries>().value,
inject<CourseQueries>().value,
)
mutations =
listOf(
UserMutations(),
CourseMutations(),
inject<UserMutations>().value,
inject<AssignmentMutations>().value,
inject<CourseMutations>().value,
)
}
}
Expand All @@ -85,3 +162,5 @@ fun Application.module() {
filter { call -> call.request.path().startsWith("/") }
}
}

internal fun getEnv(key: String): String = System.getenv(key) ?: throw IllegalStateException("$key not set in environment")
18 changes: 18 additions & 0 deletions hub/src/main/kotlin/org/sourcegrade/lab/hub/Routing.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/*
* Lab - SourceGrade.org
* Copyright (C) 2019-2024 Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.sourcegrade.lab.hub

import io.ktor.client.request.get
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Lab - SourceGrade.org
* Copyright (C) 2019-2024 Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.sourcegrade.lab.hub.db

import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
import kotlinx.datetime.Clock
import org.jetbrains.exposed.dao.EntityClass
import org.jetbrains.exposed.dao.UUIDEntity
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.UUIDTable
import org.jetbrains.exposed.sql.kotlin.datetime.timestamp
import org.sourcegrade.lab.hub.db.course.Courses
import org.sourcegrade.lab.hub.db.course.DBCourse
import org.sourcegrade.lab.hub.db.user.DBUser
import org.sourcegrade.lab.hub.db.user.Users
import org.sourcegrade.lab.hub.domain.Course
import org.sourcegrade.lab.hub.domain.UserMembership
import java.util.UUID

internal object CourseMemberships : UUIDTable("sgl_course_membership") {
val createdUtc = timestamp("createdUtc").clientDefault { Clock.System.now() }
val userId = reference("user_id", Users)
val startUtc = timestamp("startUtc")
val endUtc = timestamp("endUtc").nullable()
val courseId = reference("course_id", Courses)
}

@GraphQLIgnore
internal class DBCourseMembership(id: EntityID<UUID>) : UUIDEntity(id), UserMembership<Course> {
override val uuid: UUID = id.value
override val createdUtc by CourseMemberships.createdUtc
override val startUtc by CourseMemberships.startUtc
override val endUtc by CourseMemberships.endUtc
override val user: DBUser by DBUser referencedOn CourseMemberships.userId
override val target: DBCourse by DBCourse referencedOn CourseMemberships.courseId

companion object : EntityClass<UUID, DBCourseMembership>(CourseMemberships)
}
Loading