diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index d25d49c95..69a7b562b 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -1,13 +1,13 @@ import com.adarshr.gradle.testlogger.theme.ThemeType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -val ktor_version: String by project -val logback_version: String by project -val exposed_version: String by project -val postgres_version: String by project -val hikari_version: String by project -val kotest_version: String by project -val flyway_version: String by project +val ktorVersion: String by project +val logbackVersion: String by project +val exposedVersion: String by project +val postgresVersion: String by project +val hikariVersion: String by project +val kotestVersion: String by project +val flywayVersion: String by project // Needed for Shadow project.setProperty("mainClassName", "no.uib.echo.ApplicationKt") @@ -33,40 +33,40 @@ repositories { } dependencies { - implementation("io.ktor:ktor-server-core:$ktor_version") - implementation("io.ktor:ktor-server-netty:$ktor_version") - implementation("io.ktor:ktor-server-content-negotiation:$ktor_version") - implementation("io.ktor:ktor-server-cors:$ktor_version") - implementation("io.ktor:ktor-server-auth:$ktor_version") - implementation("io.ktor:ktor-server-auth-jwt:$ktor_version") - implementation("io.ktor:ktor-server-rate-limit:$ktor_version") - implementation("io.ktor:ktor-server-openapi:$ktor_version") - implementation("io.ktor:ktor-server-swagger:$ktor_version") + implementation("io.ktor:ktor-server-core:$ktorVersion") + implementation("io.ktor:ktor-server-netty:$ktorVersion") + implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion") + implementation("io.ktor:ktor-server-cors:$ktorVersion") + implementation("io.ktor:ktor-server-auth:$ktorVersion") + implementation("io.ktor:ktor-server-auth-jwt:$ktorVersion") + implementation("io.ktor:ktor-server-rate-limit:$ktorVersion") + implementation("io.ktor:ktor-server-openapi:$ktorVersion") + implementation("io.ktor:ktor-server-swagger:$ktorVersion") - implementation("io.ktor:ktor-client-core:$ktor_version") - implementation("io.ktor:ktor-client-cio:$ktor_version") - implementation("io.ktor:ktor-client-logging:$ktor_version") - implementation("io.ktor:ktor-client-serialization:$ktor_version") - implementation("io.ktor:ktor-client-content-negotiation:$ktor_version") + implementation("io.ktor:ktor-client-core:$ktorVersion") + implementation("io.ktor:ktor-client-cio:$ktorVersion") + implementation("io.ktor:ktor-client-logging:$ktorVersion") + implementation("io.ktor:ktor-client-serialization:$ktorVersion") + implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") - implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") + implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") - implementation("ch.qos.logback:logback-classic:$logback_version") + implementation("ch.qos.logback:logback-classic:$logbackVersion") - implementation("org.jetbrains.exposed:exposed-core:$exposed_version") - implementation("org.jetbrains.exposed:exposed-dao:$exposed_version") - implementation("org.jetbrains.exposed:exposed-jdbc:$exposed_version") - implementation("org.jetbrains.exposed:exposed-jodatime:$exposed_version") + implementation("org.jetbrains.exposed:exposed-core:$exposedVersion") + implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion") + implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion") + implementation("org.jetbrains.exposed:exposed-jodatime:$exposedVersion") - implementation("org.postgresql:postgresql:$postgres_version") + implementation("org.postgresql:postgresql:$postgresVersion") - implementation("com.zaxxer:HikariCP:$hikari_version") + implementation("com.zaxxer:HikariCP:$hikariVersion") - implementation("org.flywaydb:flyway-core:$flyway_version") + implementation("org.flywaydb:flyway-core:$flywayVersion") - testImplementation("io.ktor:ktor-server-test-host:$ktor_version") + testImplementation("io.ktor:ktor-server-test-host:$ktorVersion") - testImplementation("io.kotest:kotest-assertions-core:$kotest_version") + testImplementation("io.kotest:kotest-assertions-core:$kotestVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:1.9.20") } @@ -76,8 +76,8 @@ tasks.withType { manifest { attributes( mapOf( - "Main-Class" to application.mainClass - ) + "Main-Class" to application.mainClass, + ), ) } } diff --git a/backend/gradle.properties b/backend/gradle.properties index 0f93ef602..f118e8449 100644 --- a/backend/gradle.properties +++ b/backend/gradle.properties @@ -1,8 +1,8 @@ -ktor_version=2.3.7 -logback_version=1.4.14 -exposed_version=0.45.0 -postgres_version=42.7.1 -hikari_version=5.1.0 -kotest_version=5.8.0 -flyway_version=9.22.3 +ktorVersion=2.3.7 +logbackVersion=1.4.14 +exposedVersion=0.45.0 +postgresVersion=42.7.1 +hikariVersion=5.1.0 +kotestVersion=5.8.0 +flywayVersion=9.22.3 kotlin.code.style=official diff --git a/backend/src/main/kotlin/no/uib/echo/Application.kt b/backend/src/main/kotlin/no/uib/echo/Application.kt index d737c0138..69638bd04 100644 --- a/backend/src/main/kotlin/no/uib/echo/Application.kt +++ b/backend/src/main/kotlin/no/uib/echo/Application.kt @@ -26,10 +26,11 @@ fun Application.module() { val mbMaxPoolSize = environment.config.propertyOrNull("ktor.maxPoolSize")?.getString() val maybeSendGridApiKey = environment.config.propertyOrNull("ktor.sendGridApiKey")?.getString() - val sendGridApiKey = when (maybeSendGridApiKey.isNullOrEmpty()) { - true -> null - false -> maybeSendGridApiKey - } + val sendGridApiKey = + when (maybeSendGridApiKey.isNullOrEmpty()) { + true -> null + false -> maybeSendGridApiKey + } val secret = environment.config.propertyOrNull("jwt.secret")?.getString() val issuer = environment.config.property("jwt.issuer").getString() @@ -51,7 +52,7 @@ fun Application.module() { env, migrateDb, databaseUrl, - mbMaxPoolSize + mbMaxPoolSize, ).init() } @@ -65,7 +66,7 @@ fun Application.module() { audience = audience, issuer = issuer, secret = secret, - jwtConfig = jwtConfig + jwtConfig = jwtConfig, ) configureRateLimit() if (env != Environment.PRODUCTION) configureDocs() diff --git a/backend/src/main/kotlin/no/uib/echo/DatabaseHandler.kt b/backend/src/main/kotlin/no/uib/echo/DatabaseHandler.kt index d643f2fd0..e66a101e9 100644 --- a/backend/src/main/kotlin/no/uib/echo/DatabaseHandler.kt +++ b/backend/src/main/kotlin/no/uib/echo/DatabaseHandler.kt @@ -32,26 +32,27 @@ import java.net.URI private const val DEFAULT_DEV_POOL_SIZE = 7 private const val DEFAULT_PROD_POOL_SIZE = 20 -val tables: Array = arrayOf( - Happening, - StudentGroupHappeningRegistration, - Registration, - Answer, - SpotRange, - User, - Feedback, - StudentGroup, - StudentGroupMembership, - Reaction, - WaitingListUUID, - Whitelist -) +val tables: Array
= + arrayOf( + Happening, + StudentGroupHappeningRegistration, + Registration, + Answer, + SpotRange, + User, + Feedback, + StudentGroup, + StudentGroupMembership, + Reaction, + WaitingListUUID, + Whitelist, + ) class DatabaseHandler( private val env: Environment, private val migrateDb: Boolean, dbUrl: URI, - mbMaxPoolSize: String? + mbMaxPoolSize: String?, ) { private val dbPort = if (dbUrl.port == -1) 5432 else dbUrl.port private val dbUrlStr = "jdbc:postgresql://${dbUrl.host}:${dbPort}${dbUrl.path}" @@ -76,7 +77,7 @@ class DatabaseHandler( driverClassName = "org.postgresql.Driver" connectionTimeout = 1000 maximumPoolSize = maxPoolSize - } + }, ) } @@ -86,7 +87,7 @@ class DatabaseHandler( GIVEN BY THE NAME OF THE SQL FILE IN src/main/resources/db/migration WITH THE HIGHEST PREFIX. I.E., "V29__xyz_abc.sql" IS VERSION "29". !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - */ + */ private val flyway: Flyway = Flyway.configure().baselineVersion("31").cleanDisabled(false).dataSource(dbUrlStr, dbUsername, dbPassword) .load() @@ -131,52 +132,56 @@ class DatabaseHandler( } private fun insertTestData() { - val happenings = listOf( - HappeningJson( - "bedriftspresentasjon-med-bekk", - "Bedpres med Bekk", - "021-05-06T16:46+01:00", - "2030-03-09T16:15+01:00", - spotRanges = listOf( - SpotRangeJson( - 11, - 1, - 2 - ), - SpotRangeJson( - 9, - 3, - 5 - ) + val happenings = + listOf( + HappeningJson( + "bedriftspresentasjon-med-bekk", + "Bedpres med Bekk", + "021-05-06T16:46+01:00", + "2030-03-09T16:15+01:00", + spotRanges = + listOf( + SpotRangeJson( + 11, + 1, + 2, + ), + SpotRangeJson( + 9, + 3, + 5, + ), + ), + HAPPENING_TYPE.BEDPRES, + validStudentGroups[1], ), - HAPPENING_TYPE.BEDPRES, - validStudentGroups[1] - ), - HappeningJson( - "fest-med-tilde", - "Fest med Tilde!", - "2021-05-06T16:46+01:00", - "2030-06-02T14:20+01:00", - spotRanges = listOf( - SpotRangeJson( - 20, - 1, - 5 - ) + HappeningJson( + "fest-med-tilde", + "Fest med Tilde!", + "2021-05-06T16:46+01:00", + "2030-06-02T14:20+01:00", + spotRanges = + listOf( + SpotRangeJson( + 20, + 1, + 5, + ), + ), + HAPPENING_TYPE.EVENT, + validStudentGroups[2], ), - HAPPENING_TYPE.EVENT, - validStudentGroups[2] ) - ) - val adminTestUser = UserJson( - "test.mctest@student.uib.no", - "Test McTest", - memberships = listOf("webkom"), - strikes = 0, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() - ) + val adminTestUser = + UserJson( + "test.mctest@student.uib.no", + "Test McTest", + memberships = listOf("webkom"), + strikes = 0, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) try { transaction { diff --git a/backend/src/main/kotlin/no/uib/echo/Email.kt b/backend/src/main/kotlin/no/uib/echo/Email.kt index f33c5fd34..30eec0fa0 100644 --- a/backend/src/main/kotlin/no/uib/echo/Email.kt +++ b/backend/src/main/kotlin/no/uib/echo/Email.kt @@ -26,13 +26,13 @@ import java.util.regex.Pattern data class SendGridRequest( val personalizations: List, val from: SendGridEmail, - val template_id: String + val template_id: String, ) @Serializable data class SendGridPersonalization( val to: List, - val dynamic_template_data: SendGridTemplate + val dynamic_template_data: SendGridTemplate, ) @Serializable @@ -41,8 +41,7 @@ data class SendGridTemplate( val link: String, val waitListSpot: Int? = null, val registration: FormRegistrationJson? = null, - - val waitingListUUID: String? = null + val waitingListUUID: String? = null, ) @Serializable @@ -51,7 +50,7 @@ data class SendGridEmail(val email: String, val name: String? = null) enum class Template { CONFIRM_REG, CONFIRM_WAIT, - WAITINGLIST_NOTIFY + WAITINGLIST_NOTIFY, } private const val SENDGRID_ENDPOINT = "https://api.sendgrid.com/v3/mail/send" @@ -70,13 +69,14 @@ suspend fun sendWaitingListEmail( sendGridApiKey: String, email: String, slug: String, - uuid: String + uuid: String, ): Boolean { - val hap = transaction { - Happening.select { - Happening.slug eq slug - }.firstOrNull() - } ?: throw Exception("Happening is null.") + val hap = + transaction { + Happening.select { + Happening.slug eq slug + }.firstOrNull() + } ?: throw Exception("Happening is null.") val fromEmail = "webkom@echo.uib.no" try { @@ -88,16 +88,16 @@ suspend fun sendWaitingListEmail( hap[Happening.title], "https://echo.uib.no/event/$slug", null, - registration = FormRegistrationJson( - email, - slug, - emptyList() - ), - "https://echo.uib.no/WaitingList/$uuid" - + registration = + FormRegistrationJson( + email, + slug, + emptyList(), + ), + "https://echo.uib.no/WaitingList/$uuid", ), Template.WAITINGLIST_NOTIFY, - sendGridApiKey + sendGridApiKey, ) } return true @@ -110,13 +110,14 @@ suspend fun sendWaitingListEmail( suspend fun sendConfirmationEmail( sendGridApiKey: String, registration: FormRegistrationJson, - waitListSpot: Long? + waitListSpot: Long?, ) { - val hap = transaction { - Happening.select { - Happening.slug eq registration.slug - }.firstOrNull() - } ?: throw Exception("Happening is null.") + val hap = + transaction { + Happening.select { + Happening.slug eq registration.slug + }.firstOrNull() + } ?: throw Exception("Happening is null.") val fromEmail = "webkom@echo.uib.no" try { @@ -128,10 +129,10 @@ suspend fun sendConfirmationEmail( hap[Happening.title], "https://echo.uib.no/event/${registration.slug}", waitListSpot = waitListSpot?.toInt(), - registration = registration + registration = registration, ), if (waitListSpot != null) Template.CONFIRM_WAIT else Template.CONFIRM_REG, - sendGridApiKey + sendGridApiKey, ) } } catch (e: IOException) { @@ -144,7 +145,7 @@ suspend fun sendEmail( to: String, sendGridTemplate: SendGridTemplate, template: Template, - sendGridApiKey: String + sendGridApiKey: String, ) { if (!isEmailValid(from)) { System.err.println("Email address '$from' is not valid. Not sending email to address '$to'.") @@ -164,35 +165,37 @@ suspend fun sendEmail( SendGridEmail(from) } - val templateId = when (template) { - Template.CONFIRM_REG -> "d-1fff3960b2184def9cf8bac082aeac21" - Template.CONFIRM_WAIT -> "d-1965cd803e6940c1a6724e3c53b70275" - Template.WAITINGLIST_NOTIFY -> "d-4206b11b75c441b8ba5f792281b0f5e2" - } - - val response: HttpResponse = HttpClient { - install(Logging) - install(ContentNegotiation) { - json() + val templateId = + when (template) { + Template.CONFIRM_REG -> "d-1fff3960b2184def9cf8bac082aeac21" + Template.CONFIRM_WAIT -> "d-1965cd803e6940c1a6724e3c53b70275" + Template.WAITINGLIST_NOTIFY -> "d-4206b11b75c441b8ba5f792281b0f5e2" } - }.use { client -> - client.post(SENDGRID_ENDPOINT) { - contentType(ContentType.Application.Json) - bearerAuth(sendGridApiKey) - setBody( - SendGridRequest( - listOf( - SendGridPersonalization( - to = listOf(SendGridEmail(to)), - dynamic_template_data = sendGridTemplate - ) + + val response: HttpResponse = + HttpClient { + install(Logging) + install(ContentNegotiation) { + json() + } + }.use { client -> + client.post(SENDGRID_ENDPOINT) { + contentType(ContentType.Application.Json) + bearerAuth(sendGridApiKey) + setBody( + SendGridRequest( + listOf( + SendGridPersonalization( + to = listOf(SendGridEmail(to)), + dynamic_template_data = sendGridTemplate, + ), + ), + from = fromPers, + template_id = templateId, ), - from = fromPers, - template_id = templateId ) - ) + } } - } if (response.status != HttpStatusCode.Accepted) { throw IOException("Status code is not 202: ${response.status}, ${response.bodyAsText()}") @@ -206,6 +209,6 @@ fun isEmailValid(email: String): Boolean { "\\d{1,2}|25[0-5]|2[0-4]\\d)\\." + "([0-1]?\\d{1,2}|25[0-5]|2[0-4]\\d)\\.([0-1]?" + "\\d{1,2}|25[0-5]|2[0-4]\\d))|" + - "([a-zA-Z]+[\\w-]+\\.)+[a-zA-Z]{2,4})$" + "([a-zA-Z]+[\\w-]+\\.)+[a-zA-Z]{2,4})$", ).matcher(email).matches() } diff --git a/backend/src/main/kotlin/no/uib/echo/Environment.kt b/backend/src/main/kotlin/no/uib/echo/Environment.kt index 6cbc8215a..6391f185a 100644 --- a/backend/src/main/kotlin/no/uib/echo/Environment.kt +++ b/backend/src/main/kotlin/no/uib/echo/Environment.kt @@ -3,7 +3,7 @@ package no.uib.echo enum class Environment { PRODUCTION, DEVELOPMENT, - PREVIEW + PREVIEW, } fun String.toEnvironment(): Environment { @@ -16,5 +16,5 @@ fun String.toEnvironment(): Environment { } data class FeatureToggles( - val sendEmailReg: Boolean + val sendEmailReg: Boolean, ) diff --git a/backend/src/main/kotlin/no/uib/echo/RegistrationResponse.kt b/backend/src/main/kotlin/no/uib/echo/RegistrationResponse.kt index 756094f2b..0c474f460 100644 --- a/backend/src/main/kotlin/no/uib/echo/RegistrationResponse.kt +++ b/backend/src/main/kotlin/no/uib/echo/RegistrationResponse.kt @@ -19,7 +19,7 @@ enum class RegistrationResponse { TooLate, WaitList, NotInRange, - OK + OK, } fun resToJson( @@ -27,7 +27,7 @@ fun resToJson( regDate: String? = null, spotRanges: List? = null, waitListSpot: Long? = null, - studentGroups: List? = null + studentGroups: List? = null, ): RegistrationResponseJson { when (res) { RegistrationResponse.NotSignedIn -> @@ -37,7 +37,11 @@ fun resToJson( RegistrationResponse.InvalidDegreeYear -> return RegistrationResponseJson(res, "Vennligst velg et gyldig trinn.", "") RegistrationResponse.DegreeYearMismatch -> - return RegistrationResponseJson(res, "Årstrinn og studiretning stemmer ikke overens.", "Vennligst gå inn på profilen din og endre til riktig informasjon.") + return RegistrationResponseJson( + res, + "Årstrinn og studiretning stemmer ikke overens.", + "Vennligst gå inn på profilen din og endre til riktig informasjon.", + ) RegistrationResponse.AlreadySubmitted -> return RegistrationResponseJson(res, "Du er allerede påmeldt.", "Du har allerede fått plass.") RegistrationResponse.AlreadySubmittedWaitList -> @@ -47,27 +51,28 @@ fun resToJson( RegistrationResponse.TooLate -> return RegistrationResponseJson(res, "Påmeldingen er stengt.", "Det er ikke mulig å melde seg på lenger.", regDate) RegistrationResponse.WaitList -> { - val desc = when (waitListSpot) { - null -> "Du har blitt satt på ventelisten, og vil bli kontaktet om det åpner seg en ledig plass." - else -> "Du er på plass nr. $waitListSpot på ventelisten, og vil bli kontaktet om det åpner seg en ledig plass." - } + val desc = + when (waitListSpot) { + null -> "Du har blitt satt på ventelisten, og vil bli kontaktet om det åpner seg en ledig plass." + else -> "Du er på plass nr. $waitListSpot på ventelisten, og vil bli kontaktet om det åpner seg en ledig plass." + } return RegistrationResponseJson( res, "Alle plassene er dessverre fylt opp.", - desc + desc, ) } RegistrationResponse.HappeningDoesntExist -> return RegistrationResponseJson( res, "Dette arrangementet finnes ikke.", - "Om du mener dette ikke stemmer, ta kontakt med Webkom." + "Om du mener dette ikke stemmer, ta kontakt med Webkom.", ) RegistrationResponse.OnlyOpenForStudentGroups -> return RegistrationResponseJson( res, "Du kan ikke melde deg på.", - "Dette arrangementet er kun åpent for ${studentGroups?.joinToString(", ") ?: "visse studentgrupper"}." + "Dette arrangementet er kun åpent for ${studentGroups?.joinToString(", ") ?: "visse studentgrupper"}.", ) RegistrationResponse.NotInRange -> { var desc = "Dette arrangementet er kun åpent for " @@ -90,14 +95,14 @@ fun resToJson( return RegistrationResponseJson( res, "Du kan dessverre ikke melde deg på.", - desc + desc, ) } RegistrationResponse.OK -> return RegistrationResponseJson( res, "Påmeldingen din er registrert!", - "Du har fått plass på arrangementet." + "Du har fått plass på arrangementet.", ) } } diff --git a/backend/src/main/kotlin/no/uib/echo/SanityClient.kt b/backend/src/main/kotlin/no/uib/echo/SanityClient.kt index 734bf9f1e..928444a84 100644 --- a/backend/src/main/kotlin/no/uib/echo/SanityClient.kt +++ b/backend/src/main/kotlin/no/uib/echo/SanityClient.kt @@ -15,15 +15,16 @@ class SanityClient( projectId: String, dataset: String, apiVersion: String, - useCdn: Boolean + useCdn: Boolean, ) { private val domain = if (useCdn) "apicdn.sanity.io" else "api.sanity.io" private val baseUrl = "https://$projectId.$domain/$apiVersion/data/query/$dataset" suspend fun fetch(query: String): HttpResponse { - val encodedQuery = withContext(Dispatchers.IO) { - URLEncoder.encode(query, "UTF-8") - } + val encodedQuery = + withContext(Dispatchers.IO) { + URLEncoder.encode(query, "UTF-8") + } val url = "$baseUrl?query=$encodedQuery" @@ -34,7 +35,7 @@ class SanityClient( Json { ignoreUnknownKeys = true coerceInputValues = true - } + }, ) } }.use { diff --git a/backend/src/main/kotlin/no/uib/echo/lib/UserValidation.kt b/backend/src/main/kotlin/no/uib/echo/lib/UserValidation.kt index 1aa6aecc0..c4bd0e389 100644 --- a/backend/src/main/kotlin/no/uib/echo/lib/UserValidation.kt +++ b/backend/src/main/kotlin/no/uib/echo/lib/UserValidation.kt @@ -5,11 +5,16 @@ import no.uib.echo.schema.bachelors import no.uib.echo.schema.masters object UserValidation { - fun validateDegreeAndDegreeYear(degree: Degree?, degreeYear: Int?): Boolean { + fun validateDegreeAndDegreeYear( + degree: Degree?, + degreeYear: Int?, + ): Boolean { if (degreeYear == null || degree == null) { return false } - return (degree in bachelors && degreeYear in 1..3) || (degree in masters && degreeYear in 4..5) || (degree == Degree.ARMNINF && degreeYear == 1) + return (degree in bachelors && degreeYear in 1..3) || + (degree in masters && degreeYear in 4..5) || + (degree == Degree.ARMNINF && degreeYear == 1) } } diff --git a/backend/src/main/kotlin/no/uib/echo/plugins/Authentication.kt b/backend/src/main/kotlin/no/uib/echo/plugins/Authentication.kt index bafaa8802..8493b02f6 100644 --- a/backend/src/main/kotlin/no/uib/echo/plugins/Authentication.kt +++ b/backend/src/main/kotlin/no/uib/echo/plugins/Authentication.kt @@ -13,7 +13,13 @@ import io.ktor.server.auth.jwt.jwt import java.net.URL import java.util.concurrent.TimeUnit -fun Application.configureAuthentication(adminKey: String, audience: String, devIssuer: String, secret: String?, devRealm: String) { +fun Application.configureAuthentication( + adminKey: String, + audience: String, + devIssuer: String, + secret: String?, + devRealm: String, +) { install(Authentication) { basic("auth-admin") { realm = "Access to registrations and happenings." @@ -27,10 +33,11 @@ fun Application.configureAuthentication(adminKey: String, audience: String, devI } val issuer = "https://auth.dataporten.no" - val jwkProvider = JwkProviderBuilder(URL("$issuer/openid/jwks")) - .cached(10, 24, TimeUnit.HOURS) - .rateLimited(10, 1, TimeUnit.MINUTES) - .build() + val jwkProvider = + JwkProviderBuilder(URL("$issuer/openid/jwks")) + .cached(10, 24, TimeUnit.HOURS) + .rateLimited(10, 1, TimeUnit.MINUTES) + .build() jwt("auth-jwt") { realm = "Verify jwt" @@ -51,7 +58,7 @@ fun Application.configureAuthentication(adminKey: String, audience: String, devI .require(Algorithm.HMAC256(secret)) .withAudience(audience) .withIssuer(devIssuer) - .build() + .build(), ) validate { credential -> if (credential.payload.getClaim("email").asString() != "") { diff --git a/backend/src/main/kotlin/no/uib/echo/plugins/ContentNegotiation.kt b/backend/src/main/kotlin/no/uib/echo/plugins/ContentNegotiation.kt index 76253d341..71df81705 100644 --- a/backend/src/main/kotlin/no/uib/echo/plugins/ContentNegotiation.kt +++ b/backend/src/main/kotlin/no/uib/echo/plugins/ContentNegotiation.kt @@ -12,7 +12,7 @@ fun Application.configureContentNegotiation() { Json { ignoreUnknownKeys = true encodeDefaults = true - } + }, ) } } diff --git a/backend/src/main/kotlin/no/uib/echo/plugins/Routing.kt b/backend/src/main/kotlin/no/uib/echo/plugins/Routing.kt index 17a91b5cb..242a091dc 100644 --- a/backend/src/main/kotlin/no/uib/echo/plugins/Routing.kt +++ b/backend/src/main/kotlin/no/uib/echo/plugins/Routing.kt @@ -25,14 +25,14 @@ fun Application.configureRouting( audience: String, issuer: String, secret: String?, - jwtConfig: String + jwtConfig: String, ) { routing { getStatus() } registrationRoutes( sendEmail = featureToggles.sendEmailReg, sendGridApiKey = sendGridApiKey, - jwtConfig = jwtConfig + jwtConfig = jwtConfig, ) happeningRoutes() feedbackRoutes(jwtConfig) diff --git a/backend/src/main/kotlin/no/uib/echo/routes/FeedbackRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/FeedbackRoutes.kt index 672520daa..76a56d3ad 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/FeedbackRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/FeedbackRoutes.kt @@ -79,18 +79,19 @@ fun Route.getFeedback() { return@get } - val feedback = transaction { - Feedback.selectAll().map { - FeedbackResponseJson( - it[Feedback.id], - it[Feedback.email], - it[Feedback.name], - it[Feedback.message], - it[Feedback.sentAt].toString(), - it[Feedback.isRead] - ) + val feedback = + transaction { + Feedback.selectAll().map { + FeedbackResponseJson( + it[Feedback.id], + it[Feedback.email], + it[Feedback.name], + it[Feedback.message], + it[Feedback.sentAt].toString(), + it[Feedback.isRead], + ) + } } - } call.respond(HttpStatusCode.OK, feedback) } diff --git a/backend/src/main/kotlin/no/uib/echo/routes/HappeningRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/HappeningRoutes.kt index 187906086..12801509e 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/HappeningRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/HappeningRoutes.kt @@ -41,44 +41,45 @@ fun Route.deleteHappening() { return@delete } - val hapDeleted = transaction { - val happeningExists = Happening.select { Happening.slug eq slug }.firstOrNull() != null - if (!happeningExists) { - return@transaction false + val hapDeleted = + transaction { + val happeningExists = Happening.select { Happening.slug eq slug }.firstOrNull() != null + if (!happeningExists) { + return@transaction false + } + + SpotRange.deleteWhere { + SpotRange.happeningSlug eq slug + } + + Answer.deleteWhere { + Answer.happeningSlug eq slug + } + + Registration.deleteWhere { + Registration.happeningSlug eq slug + } + + StudentGroupHappeningRegistration.deleteWhere { + StudentGroupHappeningRegistration.happeningSlug eq slug + } + + Happening.deleteWhere { + Happening.slug eq slug + } + + return@transaction true } - SpotRange.deleteWhere { - SpotRange.happeningSlug eq slug - } - - Answer.deleteWhere { - Answer.happeningSlug eq slug - } - - Registration.deleteWhere { - Registration.happeningSlug eq slug - } - - StudentGroupHappeningRegistration.deleteWhere { - StudentGroupHappeningRegistration.happeningSlug eq slug - } - - Happening.deleteWhere { - Happening.slug eq slug - } - - return@transaction true - } - if (hapDeleted) { call.respond( HttpStatusCode.OK, - "Happening with slug = $slug deleted." + "Happening with slug = $slug deleted.", ) } else { call.respond( HttpStatusCode.NotFound, - "Happening with slug = $slug does not exist." + "Happening with slug = $slug does not exist.", ) } } @@ -93,52 +94,55 @@ fun Route.getHappeningInfo() { return@get } - val happening = transaction { - Happening.select { - Happening.slug eq slug - }.firstOrNull() - } + val happening = + transaction { + Happening.select { + Happening.slug eq slug + }.firstOrNull() + } if (happening == null) { call.respond(HttpStatusCode.NotFound, "Happening doesn't exist.") return@get } - val registrationCount = transaction { - SpotRange.select { - SpotRange.happeningSlug eq slug - }.toList().map { - val regcount = - countRegistrationsDegreeYear( - slug, - it[SpotRange.minDegreeYear]..it[SpotRange.maxDegreeYear], - Status.REGISTERED + val registrationCount = + transaction { + SpotRange.select { + SpotRange.happeningSlug eq slug + }.toList().map { + val regcount = + countRegistrationsDegreeYear( + slug, + it[SpotRange.minDegreeYear]..it[SpotRange.maxDegreeYear], + Status.REGISTERED, + ) + + val waitListCount = + countRegistrationsDegreeYear( + slug, + it[SpotRange.minDegreeYear]..it[SpotRange.maxDegreeYear], + Status.WAITLIST, + ) + + SpotRangeWithCountJson( + it[SpotRange.spots], + it[SpotRange.minDegreeYear], + it[SpotRange.maxDegreeYear], + regcount, + waitListCount, ) - - val waitListCount = - countRegistrationsDegreeYear( - slug, - it[SpotRange.minDegreeYear]..it[SpotRange.maxDegreeYear], - Status.WAITLIST - ) - - SpotRangeWithCountJson( - it[SpotRange.spots], - it[SpotRange.minDegreeYear], - it[SpotRange.maxDegreeYear], - regcount, - waitListCount - ) + } } - } val totalCount = countRegistrationsDegreeYear(slug, 1..5, Status.REGISTERED) val totalCountDiff = totalCount - registrationCount.sumOf { it.regCount } if (totalCountDiff > 0) { - val newRegistrationCount = listOf( - registrationCount.first().copy(regCount = registrationCount.first().regCount + totalCountDiff) - ) + registrationCount.drop(1) + val newRegistrationCount = + listOf( + registrationCount.first().copy(regCount = registrationCount.first().regCount + totalCountDiff), + ) + registrationCount.drop(1) call.respond(HttpStatusCode.OK, HappeningInfoJson(newRegistrationCount)) } @@ -146,8 +150,8 @@ fun Route.getHappeningInfo() { call.respond( HttpStatusCode.OK, HappeningInfoJson( - registrationCount - ) + registrationCount, + ), ) } } diff --git a/backend/src/main/kotlin/no/uib/echo/routes/ReactionRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/ReactionRoutes.kt index 2e858ed9d..74220b17d 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/ReactionRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/ReactionRoutes.kt @@ -48,11 +48,12 @@ fun Route.getReactions() { return@get } - val slugExists = transaction { - Happening.select { - Happening.slug eq slug - }.count() > 0 - } + val slugExists = + transaction { + Happening.select { + Happening.slug eq slug + }.count() > 0 + } if (!slugExists) { call.respond(HttpStatusCode.NotFound, "No happening with slug $slug.") return@get @@ -69,8 +70,8 @@ fun Route.getReactions() { reactions[ReactionType.BEER] ?: 0, reactions[ReactionType.EYES] ?: 0, reactions[ReactionType.FIX] ?: 0, - reactedTo - ) + reactedTo, + ), ) } } @@ -83,11 +84,12 @@ fun Route.putReaction() { return@put } - val user = transaction { - User.select { - User.email eq email - }.firstOrNull() - } + val user = + transaction { + User.select { + User.email eq email + }.firstOrNull() + } if (user == null) { call.respond(HttpStatusCode.NotFound, "User with email not found (email = $email).") @@ -103,11 +105,12 @@ fun Route.putReaction() { val reaction = ReactionType.valueOf(reactionQuery.uppercase()).name - val reactionExists = transaction { - Reaction.select { - userEmail eq email and (happeningSlug eq slug) and (Reaction.reaction eq reaction) - }.count() > 0 - } + val reactionExists = + transaction { + Reaction.select { + userEmail eq email and (happeningSlug eq slug) and (Reaction.reaction eq reaction) + }.count() > 0 + } if (reactionExists) { transaction { @@ -136,34 +139,39 @@ fun Route.putReaction() { reactions[ReactionType.BEER] ?: 0, reactions[ReactionType.EYES] ?: 0, reactions[ReactionType.FIX] ?: 0, - reactedTo - ) + reactedTo, + ), ) } } fun getReactionsBySlug(slug: String): Map { - val reactions: Map = transaction { - Reaction.select { - happeningSlug eq slug - }.groupBy { - ReactionType.valueOf(it[Reaction.reaction]) - }.mapValues { - it.value.count() + val reactions: Map = + transaction { + Reaction.select { + happeningSlug eq slug + }.groupBy { + ReactionType.valueOf(it[Reaction.reaction]) + }.mapValues { + it.value.count() + } } - } return reactions } -fun getReactedTo(slug: String, email: String): List { - val reactions: List = transaction { - Reaction.select { - userEmail eq email and (happeningSlug eq slug) - }.map { - ReactionType.valueOf(it[Reaction.reaction]) - }.toList() - } +fun getReactedTo( + slug: String, + email: String, +): List { + val reactions: List = + transaction { + Reaction.select { + userEmail eq email and (happeningSlug eq slug) + }.map { + ReactionType.valueOf(it[Reaction.reaction]) + }.toList() + } return reactions } diff --git a/backend/src/main/kotlin/no/uib/echo/routes/RegistrationRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/RegistrationRoutes.kt index 72e0f6e26..c6bf9dc2a 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/RegistrationRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/RegistrationRoutes.kt @@ -59,7 +59,11 @@ import org.joda.time.DateTime import java.net.URLDecoder import java.util.UUID -fun Application.registrationRoutes(sendGridApiKey: String?, sendEmail: Boolean, jwtConfig: String) { +fun Application.registrationRoutes( + sendGridApiKey: String?, + sendEmail: Boolean, + jwtConfig: String, +) { routing { authenticate(jwtConfig) { getRegistrations() @@ -94,9 +98,10 @@ fun Route.getRegistrations() { val json = call.request.queryParameters["json"] != null val testing = call.request.queryParameters["testing"] != null - val hap = transaction { - Happening.select { Happening.slug eq slug }.firstOrNull() - } + val hap = + transaction { + Happening.select { Happening.slug eq slug }.firstOrNull() + } if (hap == null) { call.respond(HttpStatusCode.NotFound) @@ -108,43 +113,47 @@ fun Route.getRegistrations() { return@get } - val regs = transaction { - Registration.select { - Registration.happeningSlug eq hap[Happening.slug] - }.orderBy(Registration.submitDate to SortOrder.ASC).toList().map { reg -> - val user = transaction { - User.select { - User.email eq reg[Registration.userEmail].lowercase() - } - }.firstOrNull() - - val answers = transaction { - Answer.select { - Answer.registrationEmail.lowerCase() eq reg[Registration.userEmail].lowercase() and (Answer.happeningSlug eq hap[Happening.slug]) - }.orderBy(Answer.id to SortOrder.ASC).toList() - }.map { - AnswerJson( - it[Answer.question], - it[Answer.answer] + val regs = + transaction { + Registration.select { + Registration.happeningSlug eq hap[Happening.slug] + }.orderBy(Registration.submitDate to SortOrder.ASC).toList().map { reg -> + val user = + transaction { + User.select { + User.email eq reg[Registration.userEmail].lowercase() + } + }.firstOrNull() + + val answers = + transaction { + Answer.select { + Answer.registrationEmail.lowerCase() eq reg[Registration.userEmail].lowercase() and + (Answer.happeningSlug eq hap[Happening.slug]) + }.orderBy(Answer.id to SortOrder.ASC).toList() + }.map { + AnswerJson( + it[Answer.question], + it[Answer.answer], + ) + } + + RegistrationJson( + reg[Registration.userEmail], + user?.get(User.alternateEmail), + user?.get(User.name) ?: "", + Degree.valueOf(reg[Registration.degree]), + reg[Registration.degreeYear], + reg[Registration.happeningSlug], + reg[Registration.submitDate].toString(), + reg[Registration.registrationStatus], + reg[Registration.reason], + reg[Registration.deregistrationDate]?.toString(), + answers, + if (user?.get(User.email) != null) getUserStudentGroups(user[User.email]) else emptyList(), ) } - - RegistrationJson( - reg[Registration.userEmail], - user?.get(User.alternateEmail), - user?.get(User.name) ?: "", - Degree.valueOf(reg[Registration.degree]), - reg[Registration.degreeYear], - reg[Registration.happeningSlug], - reg[Registration.submitDate].toString(), - reg[Registration.registrationStatus], - reg[Registration.reason], - reg[Registration.deregistrationDate]?.toString(), - answers, - if (user?.get(User.email) != null) getUserStudentGroups(user[User.email]) else emptyList() - ) } - } if (download) { val fileName = "pameldte-${hap[Happening.slug]}.csv" @@ -153,12 +162,12 @@ fun Route.getRegistrations() { HttpHeaders.ContentDisposition, ContentDisposition.Attachment.withParameter( ContentDisposition.Parameters.FileName, - fileName - ).toString() + fileName, + ).toString(), ) call.respondBytes( contentType = ContentType.parse("text/csv"), - provider = { toCsv(regs, testing = testing).toByteArray() } + provider = { toCsv(regs, testing = testing).toByteArray() }, ) } else if (json) { call.respond(regs) @@ -168,7 +177,10 @@ fun Route.getRegistrations() { } } -fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { +fun Route.postRegistration( + sendGridApiKey: String?, + sendEmail: Boolean, +) { post("/registration") { try { val email = call.principal()?.payload?.getClaim("email")?.asString()?.lowercase() @@ -185,11 +197,12 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { return@post } - val user = transaction { - User.select { - User.email.lowerCase() eq registration.email.lowercase() - }.firstOrNull() - } + val user = + transaction { + User.select { + User.email.lowerCase() eq registration.email.lowercase() + }.firstOrNull() + } if (user == null) { call.respond(HttpStatusCode.Unauthorized, resToJson(RegistrationResponse.NotSignedIn)) @@ -207,48 +220,52 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { if (userDegreeYear == null || userDegreeYear !in 1..5) { call.respond( HttpStatusCode.NonAuthoritativeInformation, - resToJson(RegistrationResponse.InvalidDegreeYear) + resToJson(RegistrationResponse.InvalidDegreeYear), ) return@post } - val happening = transaction { - Happening.select { - Happening.slug eq registration.slug - }.firstOrNull() - } + val happening = + transaction { + Happening.select { + Happening.slug eq registration.slug + }.firstOrNull() + } if (happening == null) { call.respond( HttpStatusCode.Conflict, - resToJson(RegistrationResponse.HappeningDoesntExist) + resToJson(RegistrationResponse.HappeningDoesntExist), ) return@post } val userStudentGroups = getUserStudentGroups(user[User.email]) - val happeningStudentGroups = transaction { - StudentGroupHappeningRegistration.select { - StudentGroupHappeningRegistration.happeningSlug eq happening[Happening.slug] - }.toList().map { it[StudentGroupHappeningRegistration.studentGroupName] } - } + val happeningStudentGroups = + transaction { + StudentGroupHappeningRegistration.select { + StudentGroupHappeningRegistration.happeningSlug eq happening[Happening.slug] + }.toList().map { it[StudentGroupHappeningRegistration.studentGroupName] } + } if (happening[Happening.onlyForStudentGroups] && !userStudentGroups.any { happeningStudentGroups.contains(it) }) { call.respond( HttpStatusCode.Forbidden, - resToJson(RegistrationResponse.OnlyOpenForStudentGroups, studentGroups = happeningStudentGroups) + resToJson(RegistrationResponse.OnlyOpenForStudentGroups, studentGroups = happeningStudentGroups), ) return@post } if (DateTime(happening[Happening.registrationDate]).isAfterNow) { - if (happening[Happening.studentGroupRegistrationDate] != null && DateTime(happening[Happening.studentGroupRegistrationDate]).isAfterNow) { + if (happening[Happening.studentGroupRegistrationDate] != null && + DateTime(happening[Happening.studentGroupRegistrationDate]).isAfterNow + ) { call.respond( HttpStatusCode.Forbidden, resToJson( RegistrationResponse.TooEarly, - regDate = happening[Happening.registrationDate].toString() - ) + regDate = happening[Happening.registrationDate].toString(), + ), ) return@post } @@ -258,8 +275,8 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { HttpStatusCode.Forbidden, resToJson( RegistrationResponse.TooEarly, - regDate = happening[Happening.registrationDate].toString() - ) + regDate = happening[Happening.registrationDate].toString(), + ), ) return@post } @@ -268,7 +285,7 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { if (DateTime(happening[Happening.happeningDate]).isBeforeNow) { call.respond( HttpStatusCode.Forbidden, - resToJson(RegistrationResponse.TooLate) + resToJson(RegistrationResponse.TooLate), ) return@post } @@ -278,51 +295,59 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { val canSkipDegreeYearCheck = "bedkom" in userStudentGroups && HAPPENING_TYPE.valueOf(happening[Happening.happeningType]) == HAPPENING_TYPE.BEDPRES - val correctRange = spotRanges.firstOrNull { - (user[User.degreeYear] in it.minDegreeYear..it.maxDegreeYear) || canSkipDegreeYearCheck - } + val correctRange = + spotRanges.firstOrNull { + (user[User.degreeYear] in it.minDegreeYear..it.maxDegreeYear) || canSkipDegreeYearCheck + } if (correctRange == null) { call.respond( HttpStatusCode.Forbidden, - resToJson(RegistrationResponse.NotInRange, spotRanges = spotRanges) + resToJson(RegistrationResponse.NotInRange, spotRanges = spotRanges), ) return@post } - val countRegsInSpotRange = countRegistrationsDegreeYear( - registration.slug, - correctRange.minDegreeYear..correctRange.maxDegreeYear, - Status.REGISTERED - ) - val countRegsInSpotRangeWaitList = countRegistrationsDegreeYear( - registration.slug, - correctRange.minDegreeYear..correctRange.maxDegreeYear, - Status.WAITLIST - ) + val countRegsInSpotRange = + countRegistrationsDegreeYear( + registration.slug, + correctRange.minDegreeYear..correctRange.maxDegreeYear, + Status.REGISTERED, + ) + val countRegsInSpotRangeWaitList = + countRegistrationsDegreeYear( + registration.slug, + correctRange.minDegreeYear..correctRange.maxDegreeYear, + Status.WAITLIST, + ) val totalRegCount = countRegistrationsDegreeYear(registration.slug, 1..5, Status.REGISTERED) val totalSpotsCount = spotRanges.sumOf { it.spots } val waitList = - correctRange.spots in 1..countRegsInSpotRange || countRegsInSpotRangeWaitList > 0 || (totalRegCount >= totalSpotsCount && correctRange.spots != 0) + correctRange.spots in 1..countRegsInSpotRange || + countRegsInSpotRangeWaitList > 0 || + (totalRegCount >= totalSpotsCount && correctRange.spots != 0) val waitListSpot = countRegsInSpotRangeWaitList + 1 - val oldReg = transaction { - Registration.select { - Registration.userEmail.lowerCase() eq registration.email.lowercase() and (Registration.happeningSlug eq registration.slug) - }.firstOrNull() - } + val oldReg = + transaction { + Registration.select { + Registration.userEmail.lowerCase() eq registration.email.lowercase() and + (Registration.happeningSlug eq registration.slug) + }.firstOrNull() + } if (oldReg != null) { if (oldReg[Registration.registrationStatus] != Status.DEREGISTERED) { - val responseCode = when (oldReg[Registration.registrationStatus]) { - Status.WAITLIST -> RegistrationResponse.AlreadySubmittedWaitList - else -> RegistrationResponse.AlreadySubmitted - } + val responseCode = + when (oldReg[Registration.registrationStatus]) { + Status.WAITLIST -> RegistrationResponse.AlreadySubmittedWaitList + else -> RegistrationResponse.AlreadySubmitted + } call.respond( HttpStatusCode.UnprocessableEntity, - resToJson(responseCode) + resToJson(responseCode), ) return@post } @@ -330,7 +355,9 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { if (oldReg != null) { transaction { - Registration.update({ Registration.userEmail eq registration.email.lowercase() and (Registration.happeningSlug eq registration.slug) }) { + Registration.update( + { Registration.userEmail eq registration.email.lowercase() and (Registration.happeningSlug eq registration.slug) }, + ) { it[degree] = userDegree.toString() it[degreeYear] = userDegreeYear it[registrationStatus] = if (waitList) Status.WAITLIST else Status.REGISTERED @@ -369,14 +396,18 @@ fun Route.postRegistration(sendGridApiKey: String?, sendEmail: Boolean) { } call.respond( HttpStatusCode.Accepted, - resToJson(RegistrationResponse.WaitList, waitListSpot = waitListSpot.toLong()) + resToJson(RegistrationResponse.WaitList, waitListSpot = waitListSpot.toLong()), ) if (sendGridApiKey == null || !sendEmail) { return@post } - sendConfirmationEmail(sendGridApiKey, registration.copy(email = user[User.alternateEmail] ?: user[User.email]), waitListSpot.toLong()) + sendConfirmationEmail( + sendGridApiKey, + registration.copy(email = user[User.alternateEmail] ?: user[User.email]), + waitListSpot.toLong(), + ) } else { call.respond(HttpStatusCode.OK, resToJson(RegistrationResponse.OK)) @@ -408,13 +439,15 @@ fun Route.deleteRegistration() { val paramEmail = toDelete.email - val decodedParamEmail = withContext(Dispatchers.IO) { - URLDecoder.decode(paramEmail, "utf-8") - }.lowercase() + val decodedParamEmail = + withContext(Dispatchers.IO) { + URLDecoder.decode(paramEmail, "utf-8") + }.lowercase() - val hap = transaction { - Happening.select { Happening.slug eq slug }.firstOrNull() - } + val hap = + transaction { + Happening.select { Happening.slug eq slug }.firstOrNull() + } if (hap == null) { call.respond(HttpStatusCode.NotFound) @@ -427,11 +460,12 @@ fun Route.deleteRegistration() { } try { - val reg = transaction { - Registration.select { - Registration.happeningSlug eq hap[Happening.slug] and (Registration.userEmail.lowerCase() eq decodedParamEmail) - }.firstOrNull() - } + val reg = + transaction { + Registration.select { + Registration.happeningSlug eq hap[Happening.slug] and (Registration.userEmail.lowerCase() eq decodedParamEmail) + }.firstOrNull() + } if (reg == null) { call.respond(HttpStatusCode.BadRequest, "reg is null") @@ -441,7 +475,9 @@ fun Route.deleteRegistration() { val strikes = toDelete.strikes transaction { - Registration.update({ Registration.happeningSlug eq hap[Happening.slug] and (Registration.userEmail.lowerCase() eq decodedParamEmail) }) { + Registration.update( + { Registration.happeningSlug eq hap[Happening.slug] and (Registration.userEmail.lowerCase() eq decodedParamEmail) }, + ) { it[registrationStatus] = Status.DEREGISTERED it[reason] = toDelete.reason it[deregistrationDate] = DateTime.now() @@ -457,7 +493,7 @@ fun Route.deleteRegistration() { if (reg[Registration.registrationStatus] == Status.WAITLIST) { call.respond( HttpStatusCode.OK, - "Registration with email = $decodedParamEmail and slug = ${hap[Happening.slug]} was deregistered." + "Registration with email = $decodedParamEmail and slug = ${hap[Happening.slug]} was deregistered.", ) transaction { WaitingListUUID.deleteWhere { @@ -471,7 +507,7 @@ fun Route.deleteRegistration() { call.respond( HttpStatusCode.OK, - "Registration with email = $decodedParamEmail and slug = ${hap[Happening.slug]} deleted." + "Registration with email = $decodedParamEmail and slug = ${hap[Happening.slug]} deleted.", ) return@delete } catch (e: Exception) { @@ -486,18 +522,19 @@ fun Route.postRegistrationCount() { try { val slugs = call.receive().slugs - val registrationCounts = transaction { - slugs.map { - val count = countRegistrationsDegreeYear(it, 1..5, Status.REGISTERED) - val waitListCount = countRegistrationsDegreeYear(it, 1..5, Status.WAITLIST) + val registrationCounts = + transaction { + slugs.map { + val count = countRegistrationsDegreeYear(it, 1..5, Status.REGISTERED) + val waitListCount = countRegistrationsDegreeYear(it, 1..5, Status.WAITLIST) - RegistrationCountJson(it, count, waitListCount) + RegistrationCountJson(it, count, waitListCount) + } } - } call.respond( HttpStatusCode.OK, - registrationCounts + registrationCounts, ) } catch (e: Exception) { call.respond(HttpStatusCode.InternalServerError, "Error getting registration counts.") @@ -509,9 +546,10 @@ fun Route.getUserRegistrations() { get("/user/{email}/registrations") { val email = call.principal()?.payload?.getClaim("email")?.asString()?.lowercase() - val userEmail = withContext(Dispatchers.IO) { - URLDecoder.decode(call.parameters["email"], "UTF-8") - } + val userEmail = + withContext(Dispatchers.IO) { + URLDecoder.decode(call.parameters["email"], "UTF-8") + } if (email == null || userEmail == null) { call.respond(HttpStatusCode.BadRequest, "NO EMAIL") return@get @@ -522,13 +560,14 @@ fun Route.getUserRegistrations() { return@get } - val userRegistrations = transaction { - (Registration leftJoin Happening).select { - Registration.userEmail eq email and (Registration.registrationStatus inList listOf(Status.WAITLIST, Status.REGISTERED)) - }.orderBy(Happening.registrationDate to SortOrder.DESC).map { - UserRegistrationJson(it[Happening.slug], it[Registration.registrationStatus]) - }.toList() - } + val userRegistrations = + transaction { + (Registration leftJoin Happening).select { + Registration.userEmail eq email and (Registration.registrationStatus inList listOf(Status.WAITLIST, Status.REGISTERED)) + }.orderBy(Happening.registrationDate to SortOrder.DESC).map { + UserRegistrationJson(it[Happening.slug], it[Registration.registrationStatus]) + }.toList() + } call.respond(userRegistrations) } diff --git a/backend/src/main/kotlin/no/uib/echo/routes/SanityRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/SanityRoutes.kt index 5e1e622ab..e68667c47 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/SanityRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/SanityRoutes.kt @@ -18,7 +18,7 @@ import no.uib.echo.schema.insertOrUpdateHappening @Serializable data class SanityResponse( val query: String, - val result: List + val result: List, ) fun Application.sanityRoutes(env: Environment) { @@ -39,14 +39,16 @@ fun Route.sanitySync() { return@get } - val client = SanityClient( - projectId = "pgq2pd26", - dataset = dataset, - apiVersion = "v2021-10-21", - useCdn = false - ) + val client = + SanityClient( + projectId = "pgq2pd26", + dataset = dataset, + apiVersion = "v2021-10-21", + useCdn = false, + ) - val query = """ + val query = + """ *[_type == 'happening' && ( (defined(registrationDate) && defined(spotRanges) && count(spotRanges) > 0) || @@ -69,20 +71,21 @@ fun Route.sanitySync() { "type": happeningType, studentGroupName } - """.trimIndent() + """.trimIndent() val response = client.fetch(query).body() - val result = response.result.map { - val (code, string) = insertOrUpdateHappening(it) + val result = + response.result.map { + val (code, string) = insertOrUpdateHappening(it) - if (code != HttpStatusCode.OK && code != HttpStatusCode.Accepted) { - call.respond(code, string) - return@get - } + if (code != HttpStatusCode.OK && code != HttpStatusCode.Accepted) { + call.respond(code, string) + return@get + } - string - } + string + } call.respond(HttpStatusCode.OK, result) } diff --git a/backend/src/main/kotlin/no/uib/echo/routes/StudentGroupRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/StudentGroupRoutes.kt index 58e2e0989..53e0a75cd 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/StudentGroupRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/StudentGroupRoutes.kt @@ -43,7 +43,7 @@ fun Route.studentGroup() { if (group == null || userEmail == null) { call.respond( HttpStatusCode.BadRequest, - "Expected values for query parameters 'group' and 'user'. Got 'group'=$group and 'user'=$userEmail" + "Expected values for query parameters 'group' and 'user'. Got 'group'=$group and 'user'=$userEmail", ) return@put } diff --git a/backend/src/main/kotlin/no/uib/echo/routes/UserRoutes.kt b/backend/src/main/kotlin/no/uib/echo/routes/UserRoutes.kt index 284fdb405..de7c26669 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/UserRoutes.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/UserRoutes.kt @@ -40,7 +40,7 @@ fun Application.userRoutes( audience: String, issuer: String, secret: String?, - jwtConfig: String + jwtConfig: String, ) { routing { getToken(env, audience, issuer, secret) @@ -67,9 +67,10 @@ fun Route.getUser() { return@get } - val user = transaction { - User.select { User.email eq email }.firstOrNull() - } + val user = + transaction { + User.select { User.email eq email }.firstOrNull() + } if (user == null) { call.respond(HttpStatusCode.NotFound, "User with email not found (email = $email).") @@ -89,8 +90,8 @@ fun Route.getUser() { memberships, user[User.strikes], user[User.createdAt].toString(), - user[User.modifiedAt].toString() - ) + user[User.modifiedAt].toString(), + ), ) } } @@ -114,9 +115,10 @@ fun Route.postUser() { return@post } - val existingUser = transaction { - User.select { User.email eq email }.firstOrNull() - } + val existingUser = + transaction { + User.select { User.email eq email }.firstOrNull() + } if (existingUser != null) { call.respond(HttpStatusCode.Conflict, "User already exists.") @@ -132,7 +134,7 @@ fun Route.postUser() { call.respond( HttpStatusCode.OK, - "New user created with email = $email and name = ${user.name}." + "New user created with email = $email and name = ${user.name}.", ) } catch (e: Exception) { call.respond(HttpStatusCode.InternalServerError) @@ -150,7 +152,7 @@ fun Route.putUser() { if (email == null) { call.respond( HttpStatusCode.Unauthorized, - "Det har skjedd en feil. Vennligst prøv å logg inn og ut igjen." + "Det har skjedd en feil. Vennligst prøv å logg inn og ut igjen.", ) return@put } @@ -180,22 +182,24 @@ fun Route.putUser() { return@put } - val result = transaction { - User.select { User.email eq email }.firstOrNull() - } + val result = + transaction { + User.select { User.email eq email }.firstOrNull() + } if (result == null) { - val newUser = transaction { - User.insert { - it[User.email] = email - it[name] = user.name - it[User.alternateEmail] = alternateEmail - it[degree] = user.degree.toString() - it[degreeYear] = user.degreeYear - } + val newUser = + transaction { + User.insert { + it[User.email] = email + it[name] = user.name + it[User.alternateEmail] = alternateEmail + it[degree] = user.degree.toString() + it[degreeYear] = user.degreeYear + } - User.select { User.email eq email }.first() - } + User.select { User.email eq email }.first() + } call.respond( HttpStatusCode.OK, UserJson( @@ -207,23 +211,24 @@ fun Route.putUser() { emptyList(), newUser[User.strikes], newUser[User.createdAt].toString(), - newUser[User.modifiedAt].toString() - ) + newUser[User.modifiedAt].toString(), + ), ) return@put } - val updatedUser = transaction { - User.update({ User.email eq email }) { - it[name] = user.name - it[User.alternateEmail] = alternateEmail - it[degree] = user.degree.toString() - it[degreeYear] = user.degreeYear - it[modifiedAt] = DateTime.now() - } + val updatedUser = + transaction { + User.update({ User.email eq email }) { + it[name] = user.name + it[User.alternateEmail] = alternateEmail + it[degree] = user.degree.toString() + it[degreeYear] = user.degreeYear + it[modifiedAt] = DateTime.now() + } - User.select { User.email eq email }.first() - } + User.select { User.email eq email }.first() + } val memberships = getUserStudentGroups(email) @@ -238,8 +243,8 @@ fun Route.putUser() { memberships, updatedUser[User.strikes], updatedUser[User.createdAt].toString(), - updatedUser[User.modifiedAt].toString() - ) + updatedUser[User.modifiedAt].toString(), + ), ) } catch (e: Exception) { call.respond(HttpStatusCode.InternalServerError) @@ -264,27 +269,28 @@ fun Route.getAllUsers() { return@get } - val users = transaction { - User.select { User.email like "%@student.uib.no" or (User.email like "%@uib.no") } - .map { - UserJson( - it[User.email], - it[User.name], - it[User.alternateEmail], - it[User.degreeYear], - nullableStringToDegree(it[User.degree]), - StudentGroupMembership.select { - StudentGroupMembership.userEmail eq it[User.email] - } - .toList() - .map { it[StudentGroupMembership.studentGroupName] } - .ifEmpty { emptyList() }, - it[User.strikes], - it[User.createdAt].toString(), - it[User.modifiedAt].toString() - ) - } - } + val users = + transaction { + User.select { User.email like "%@student.uib.no" or (User.email like "%@uib.no") } + .map { + UserJson( + it[User.email], + it[User.name], + it[User.alternateEmail], + it[User.degreeYear], + nullableStringToDegree(it[User.degree]), + StudentGroupMembership.select { + StudentGroupMembership.userEmail eq it[User.email] + } + .toList() + .map { it[StudentGroupMembership.studentGroupName] } + .ifEmpty { emptyList() }, + it[User.strikes], + it[User.createdAt].toString(), + it[User.modifiedAt].toString(), + ) + } + } call.respond(HttpStatusCode.OK, users) } @@ -310,39 +316,45 @@ fun Route.getAllUsersPaginated() { val page = call.parameters["page"]?.toIntOrNull() ?: 1 val searchTerm = call.parameters["searchTerm"]?.lowercase() ?: "" - val users = transaction { - User.select { - (User.email like "%@student.uib.no" or (User.email like "%@uib.no")) and - (User.email like "%$searchTerm%" or (User.name like "%$searchTerm%")) - } - .orderBy(User.modifiedAt, SortOrder.DESC) - .limit(pageSize, (page - 1L) * pageSize) - .map { - UserJson( - it[User.email], - it[User.name], - it[User.alternateEmail], - it[User.degreeYear], - nullableStringToDegree(it[User.degree]), - StudentGroupMembership.select { - StudentGroupMembership.userEmail eq it[User.email] - } - .toList() - .map { it[StudentGroupMembership.studentGroupName] } - .ifEmpty { emptyList() }, - it[User.strikes], - it[User.createdAt].toString(), - it[User.modifiedAt].toString() - ) + val users = + transaction { + User.select { + (User.email like "%@student.uib.no" or (User.email like "%@uib.no")) and + (User.email like "%$searchTerm%" or (User.name like "%$searchTerm%")) } - } + .orderBy(User.modifiedAt, SortOrder.DESC) + .limit(pageSize, (page - 1L) * pageSize) + .map { + UserJson( + it[User.email], + it[User.name], + it[User.alternateEmail], + it[User.degreeYear], + nullableStringToDegree(it[User.degree]), + StudentGroupMembership.select { + StudentGroupMembership.userEmail eq it[User.email] + } + .toList() + .map { it[StudentGroupMembership.studentGroupName] } + .ifEmpty { emptyList() }, + it[User.strikes], + it[User.createdAt].toString(), + it[User.modifiedAt].toString(), + ) + } + } call.respond(HttpStatusCode.OK, users) } } /** Used for testing purposes */ -fun Route.getToken(env: Environment, audience: String, issuer: String, secret: String?) { +fun Route.getToken( + env: Environment, + audience: String, + issuer: String, + secret: String?, +) { get("/token/{email}") { val email = call.parameters["email"] @@ -376,11 +388,12 @@ fun Route.getWhitelist() { return@get } - val whitelist = transaction { - Whitelist.select { - Whitelist.email eq email - }.firstOrNull() - } + val whitelist = + transaction { + Whitelist.select { + Whitelist.email eq email + }.firstOrNull() + } if (whitelist == null) { call.respond(HttpStatusCode.NotFound) diff --git a/backend/src/main/kotlin/no/uib/echo/routes/WaitinglistRoute.kt b/backend/src/main/kotlin/no/uib/echo/routes/WaitinglistRoute.kt index 2a88c63a9..21381d04c 100644 --- a/backend/src/main/kotlin/no/uib/echo/routes/WaitinglistRoute.kt +++ b/backend/src/main/kotlin/no/uib/echo/routes/WaitinglistRoute.kt @@ -28,7 +28,10 @@ import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update -fun Application.waitinglistRoutes(jwtConfig: String, sendGridApiKey: String?) { +fun Application.waitinglistRoutes( + jwtConfig: String, + sendGridApiKey: String?, +) { routing { if (sendGridApiKey != null) { authenticate(jwtConfig) { @@ -48,11 +51,12 @@ fun Route.promoteFromWaitingListWithoutValidation() { return@post } - val waitingListResult = transaction { - WaitingListUUID.select { - WaitingListUUID.uuid eq uuid - }.firstOrNull() - } + val waitingListResult = + transaction { + WaitingListUUID.select { + WaitingListUUID.uuid eq uuid + }.firstOrNull() + } if (waitingListResult == null) { call.respond(HttpStatusCode.BadRequest, "the UUID '$uuid' was not found in the database") return@post @@ -62,7 +66,10 @@ fun Route.promoteFromWaitingListWithoutValidation() { val email = waitingListResult[userEmail] if (!isPromotionLegal(happeningSlug) || !isPersonLegalToPromote(happeningSlug, email)) { - call.respond(HttpStatusCode.Accepted, "user ($email) was denied promotion from the waiting list, person or promotion was illegal") + call.respond( + HttpStatusCode.Accepted, + "user ($email) was denied promotion from the waiting list, person or promotion was illegal", + ) return@post } @@ -92,11 +99,12 @@ fun Route.promoteFromWaitingList(sendGridApiKey: String) { return@get } - val slug = transaction { - Happening.select { - Happening.slug eq happeningSlug - }.firstOrNull() - } + val slug = + transaction { + Happening.select { + Happening.slug eq happeningSlug + }.firstOrNull() + } if (slug == null) { call.respond(HttpStatusCode.NotFound, "could not find event") return@get @@ -123,11 +131,12 @@ fun Route.promoteFromWaitingList(sendGridApiKey: String) { return@post } - val slug = transaction { - Happening.select { - Happening.slug eq happeningSlug - }.firstOrNull() - } + val slug = + transaction { + Happening.select { + Happening.slug eq happeningSlug + }.firstOrNull() + } if (slug == null) { call.respond(HttpStatusCode.NotFound, "could not find event") @@ -168,11 +177,12 @@ fun Route.promoteFromWaitingList(sendGridApiKey: String) { return@post } - val slug = transaction { - Happening.select { - Happening.slug eq happeningSlug - }.firstOrNull() - } + val slug = + transaction { + Happening.select { + Happening.slug eq happeningSlug + }.firstOrNull() + } if (slug == null) { call.respond(HttpStatusCode.NotFound, "Slug was not found in database") @@ -184,13 +194,14 @@ fun Route.promoteFromWaitingList(sendGridApiKey: String) { return@post } - val reg = transaction { - Registration.select { - Registration.happeningSlug eq happeningSlug and( - Registration.userEmail eq email + val reg = + transaction { + Registration.select { + Registration.happeningSlug eq happeningSlug and( + Registration.userEmail eq email ) - }.firstOrNull() - } + }.firstOrNull() + } if (reg == null) { call.respond(HttpStatusCode.NotFound, "the email was not registered to the slug") diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Answer.kt b/backend/src/main/kotlin/no/uib/echo/schema/Answer.kt index 7028886ea..4a2ca8841 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Answer.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Answer.kt @@ -8,7 +8,7 @@ import org.jetbrains.exposed.sql.Table @Serializable data class AnswerJson( val question: String, - val answer: String + val answer: String, ) object Answer : Table() { @@ -25,7 +25,7 @@ object Answer : Table() { happeningSlug to Registration.happeningSlug, registrationEmail to Registration.userEmail, onUpdate = ReferenceOption.RESTRICT, - onDelete = ReferenceOption.RESTRICT + onDelete = ReferenceOption.RESTRICT, ) } } diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Degree.kt b/backend/src/main/kotlin/no/uib/echo/schema/Degree.kt index e80171308..8e0c701df 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Degree.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Degree.kt @@ -16,7 +16,7 @@ enum class Degree { // they are only here for backwards compatibility. MISC, IKT, - KOGNI + KOGNI, } val bachelors: List = listOf(Degree.DTEK, Degree.DSIK, Degree.DVIT, Degree.BINF, Degree.IMO, Degree.DSC) diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Feedback.kt b/backend/src/main/kotlin/no/uib/echo/schema/Feedback.kt index 0986c6658..ca8ee2afc 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Feedback.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Feedback.kt @@ -17,12 +17,12 @@ data class FeedbackResponseJson( val name: String?, val message: String, val sentAt: String, - val isRead: Boolean + val isRead: Boolean, ) enum class FeedbackResponse { EMPTY, - SUCCESS + SUCCESS, } object Feedback : Table() { diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Happening.kt b/backend/src/main/kotlin/no/uib/echo/schema/Happening.kt index 9b1efea20..263c5eb98 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Happening.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Happening.kt @@ -14,8 +14,10 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update import org.joda.time.DateTime +@Suppress("ktlint:standard:class-naming") enum class HAPPENING_TYPE { - BEDPRES, EVENT + BEDPRES, + EVENT, } @Serializable @@ -29,12 +31,12 @@ data class HappeningJson( val studentGroupName: String, val studentGroupRegistrationDate: String? = null, val studentGroups: List = emptyList(), - val onlyForStudentGroups: Boolean? = null + val onlyForStudentGroups: Boolean? = null, ) @Serializable data class HappeningInfoJson( - val spotRanges: List + val spotRanges: List, ) object Happening : Table() { @@ -54,34 +56,35 @@ object StudentGroupHappeningRegistration : Table("student_group_happening_regist val studentGroupName: Column = text("student_group_name").references(StudentGroup.name) val happeningSlug: Column = text("happening_slug").references(Happening.slug) - override val primaryKey: PrimaryKey = PrimaryKey( - StudentGroupHappeningRegistration.studentGroupName, - StudentGroupHappeningRegistration.happeningSlug - ) + override val primaryKey: PrimaryKey = + PrimaryKey( + StudentGroupHappeningRegistration.studentGroupName, + StudentGroupHappeningRegistration.happeningSlug, + ) } -fun insertOrUpdateHappening( - newHappening: HappeningJson -): Pair { +fun insertOrUpdateHappening(newHappening: HappeningJson): Pair { if (newHappening.spotRanges.isEmpty()) { return Pair( HttpStatusCode.BadRequest, - "No spot range given for happening with slug ${newHappening.slug}." + "No spot range given for happening with slug ${newHappening.slug}.", ) } - val happening = transaction { - Happening.select { - Happening.slug eq newHappening.slug - }.firstOrNull() - } + val happening = + transaction { + Happening.select { + Happening.slug eq newHappening.slug + }.firstOrNull() + } val spotRanges = selectSpotRanges(newHappening.slug) - val studentGroups = transaction { - StudentGroupHappeningRegistration.select { - StudentGroupHappeningRegistration.happeningSlug eq newHappening.slug - }.toList().map { it[StudentGroupHappeningRegistration.studentGroupName] } - } + val studentGroups = + transaction { + StudentGroupHappeningRegistration.select { + StudentGroupHappeningRegistration.happeningSlug eq newHappening.slug + }.toList().map { it[StudentGroupHappeningRegistration.studentGroupName] } + } if (happening == null) { transaction { @@ -108,20 +111,22 @@ fun insertOrUpdateHappening( return Pair( HttpStatusCode.OK, - "${newHappening.type.toString().lowercase()} submitted with slug = ${newHappening.slug}." + "${newHappening.type.toString().lowercase()} submitted with slug = ${newHappening.slug}.", ) } - if (happening[Happening.slug] == newHappening.slug && happening[Happening.title] == newHappening.title && DateTime( - happening[Happening.registrationDate] - ) == DateTime(newHappening.registrationDate) && DateTime(happening[Happening.happeningDate]) == DateTime( - newHappening.happeningDate - ) && spotRanges == newHappening.spotRanges && happening[Happening.studentGroupName]?.lowercase() == newHappening.studentGroupName.lowercase() && happening[Happening.studentGroupRegistrationDate] == DateTime( - newHappening.studentGroupRegistrationDate - ) && studentGroups == newHappening.studentGroups && happening[Happening.onlyForStudentGroups] == newHappening.onlyForStudentGroups - + if (happening[Happening.slug] == newHappening.slug && + happening[Happening.title] == newHappening.title && + DateTime(happening[Happening.registrationDate]) == DateTime(newHappening.registrationDate) && + DateTime(happening[Happening.happeningDate]) == DateTime(newHappening.happeningDate) && + spotRanges == newHappening.spotRanges && + happening[Happening.studentGroupName]?.lowercase() == newHappening.studentGroupName.lowercase() && + happening[Happening.studentGroupRegistrationDate] == DateTime(newHappening.studentGroupRegistrationDate) && + studentGroups == newHappening.studentGroups && + happening[Happening.onlyForStudentGroups] == newHappening.onlyForStudentGroups ) { - val message = """ + val message = + """ Happening with slug = ${newHappening.slug}, title = ${newHappening.title}, @@ -132,11 +137,11 @@ fun insertOrUpdateHappening( studentGroups = ${newHappening.studentGroups.joinToString(",", prefix = "[", postfix = "[")}, onlyForStudentGroups = ${newHappening.onlyForStudentGroups} and studentGroupName = ${newHappening.studentGroupName} has already been submitted." - """.trimIndent() + """.trimIndent() return Pair( HttpStatusCode.Accepted, - message + message, ) } @@ -171,7 +176,8 @@ fun insertOrUpdateHappening( } } - val message = """ + val message = + """ Updated ${newHappening.type} with slug = ${newHappening.slug} to title = ${newHappening.title}, registrationDate = ${newHappening.registrationDate}, @@ -180,18 +186,18 @@ fun insertOrUpdateHappening( studentGroupRegistrationDate = ${newHappening.studentGroupRegistrationDate}, studentGroups = ${newHappening.studentGroups.joinToString(",", prefix = "[", postfix = "]")} and studentGroupName = ${newHappening.studentGroupName}. - """.trimIndent() + """.trimIndent() return Pair( HttpStatusCode.OK, - message + message, ) } fun spotRangesToString(spotRanges: List): String { return "[ ${ - spotRanges.map { - "(spots = ${it.spots}, minDegreeYear = ${it.minDegreeYear}, maxDegreeYear = ${it.maxDegreeYear}), " - } + spotRanges.map { + "(spots = ${it.spots}, minDegreeYear = ${it.minDegreeYear}, maxDegreeYear = ${it.maxDegreeYear}), " + } } ]" } diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Reaction.kt b/backend/src/main/kotlin/no/uib/echo/schema/Reaction.kt index 99e8d3d1f..eca7518b0 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Reaction.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Reaction.kt @@ -9,7 +9,7 @@ enum class ReactionType { ROCKET, BEER, EYES, - FIX + FIX, } @Serializable @@ -19,7 +19,7 @@ data class ReactionsJson( val beer: Int, val eyes: Int, val fix: Int, - val reactedTo: List + val reactedTo: List, ) object Reaction : Table() { diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Registration.kt b/backend/src/main/kotlin/no/uib/echo/schema/Registration.kt index 007517ab7..be754a858 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Registration.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Registration.kt @@ -14,7 +14,7 @@ import org.joda.time.DateTime data class FormRegistrationJson( val email: String, val slug: String, - val answers: List + val answers: List, ) @Serializable @@ -22,13 +22,13 @@ data class FormDeregistrationJson( val email: String, val slug: String, val reason: String, - val strikes: Int? = null + val strikes: Int? = null, ) @Serializable data class UserRegistrationJson( val slug: String, - val status: Status + val status: Status, ) @Serializable @@ -44,10 +44,13 @@ data class RegistrationJson( val reason: String? = null, val deregistrationDate: String? = null, val answers: List = emptyList(), - val memberships: List = emptyList() + val memberships: List = emptyList(), ) + enum class Status { - REGISTERED, DEREGISTERED, WAITLIST + REGISTERED, + DEREGISTERED, + WAITLIST, } object Registration : Table() { @@ -66,7 +69,7 @@ object Registration : Table() { fun countRegistrationsDegreeYear( slug: String, range: IntRange, - status: Status + status: Status, ): Int { return transaction { Registration.select { @@ -77,7 +80,10 @@ fun countRegistrationsDegreeYear( }.toInt() } -fun toCsv(regs: List, testing: Boolean = false): String { +fun toCsv( + regs: List, + testing: Boolean = false, +): String { if (regs.isEmpty()) { return "" } diff --git a/backend/src/main/kotlin/no/uib/echo/schema/SpotRange.kt b/backend/src/main/kotlin/no/uib/echo/schema/SpotRange.kt index 7d6327450..29c8a8de8 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/SpotRange.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/SpotRange.kt @@ -13,7 +13,7 @@ import org.jetbrains.exposed.sql.transactions.transaction data class SpotRangeJson( val spots: Int, val minDegreeYear: Int, - val maxDegreeYear: Int + val maxDegreeYear: Int, ) @Serializable @@ -22,7 +22,7 @@ data class SpotRangeWithCountJson( val minDegreeYear: Int, val maxDegreeYear: Int, val regCount: Int, - val waitListCount: Int + val waitListCount: Int, ) object SpotRange : Table() { @@ -37,14 +37,14 @@ object SpotRange : Table() { @Serializable data class SlugJson( - val slugs: List + val slugs: List, ) @Serializable data class RegistrationCountJson( val slug: String, val count: Int, - val waitListCount: Int + val waitListCount: Int, ) fun selectSpotRanges(slug: String): List { @@ -56,7 +56,7 @@ fun selectSpotRanges(slug: String): List { SpotRangeJson( it[spots], it[minDegreeYear], - it[maxDegreeYear] + it[maxDegreeYear], ) } } diff --git a/backend/src/main/kotlin/no/uib/echo/schema/StudentGroup.kt b/backend/src/main/kotlin/no/uib/echo/schema/StudentGroup.kt index 04cd48f94..09ba9ceb0 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/StudentGroup.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/StudentGroup.kt @@ -9,9 +9,10 @@ import org.jetbrains.exposed.sql.transactions.transaction val validStudentGroups = listOf("webkom", "bedkom", "gnist", "tilde", "hovedstyret", "hyggkom", "esc", "makerspace", "programmerbar") object StudentGroup : Table("student_group") { - val name: Column = text("group_name").check("valid_student_group") { - it inList validStudentGroups - } + val name: Column = + text("group_name").check("valid_student_group") { + it inList validStudentGroups + } override val primaryKey: PrimaryKey = PrimaryKey(name) } @@ -36,6 +37,7 @@ fun getGroupMembers(group: String?): List { } } +@Suppress("ktlint:standard:function-naming") fun _getGroupMembers(group: String?): List { if (group == null) { return emptyList() @@ -48,12 +50,13 @@ fun _getGroupMembers(group: String?): List { } } -fun getUserStudentGroups(email: String): List = transaction { - StudentGroupMembership.select { - StudentGroupMembership.userEmail eq email - }.toList().map { - it[StudentGroupMembership.studentGroupName] - }.ifEmpty { - emptyList() +fun getUserStudentGroups(email: String): List = + transaction { + StudentGroupMembership.select { + StudentGroupMembership.userEmail eq email + }.toList().map { + it[StudentGroupMembership.studentGroupName] + }.ifEmpty { + emptyList() + } } -} diff --git a/backend/src/main/kotlin/no/uib/echo/schema/User.kt b/backend/src/main/kotlin/no/uib/echo/schema/User.kt index 9eb291a90..091d1842c 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/User.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/User.kt @@ -19,7 +19,7 @@ data class UserJson( val memberships: List = emptyList(), val strikes: Int, val createdAt: String, - val modifiedAt: String + val modifiedAt: String, ) object User : Table() { @@ -35,6 +35,7 @@ object User : Table() { override val primaryKey: PrimaryKey = PrimaryKey(email) } -fun getAllUserEmails(): List = transaction { - User.selectAll().toList().map { it[User.email].lowercase() } -} +fun getAllUserEmails(): List = + transaction { + User.selectAll().toList().map { it[User.email].lowercase() } + } diff --git a/backend/src/main/kotlin/no/uib/echo/schema/WaitinglistUUID.kt b/backend/src/main/kotlin/no/uib/echo/schema/WaitinglistUUID.kt index 310968d08..70ca79f0e 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/WaitinglistUUID.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/WaitinglistUUID.kt @@ -16,43 +16,53 @@ data class WaitinglistUUIDJson( val uuid: String, val userEmail: String, val happeningSlug: String, - val lastNotified: String + val lastNotified: String, ) object WaitingListUUID : Table("waiting_list_uuid") { val uuid: Column = text("uuid").uniqueIndex() val userEmail: Column = text("user_email") references User.email val happeningSlug: Column = text("happening_slug") references Happening.slug - val lastNotified: Column = datetime("last_notified").default(DateTime(0)) // default value is January 1st, 1970 (1970-01-01T01:00:00.000+01:00) + val lastNotified: Column = + datetime( + "last_notified", + ).default(DateTime(0)) // default value is January 1st, 1970 (1970-01-01T01:00:00.000+01:00) init { uniqueIndex(userEmail, happeningSlug) } + override val primaryKey: PrimaryKey = PrimaryKey(uuid) } -suspend fun notifyWaitinglistPerson(slug: String, email: String, sendGridApiKey: String): Boolean { +suspend fun notifyWaitinglistPerson( + slug: String, + email: String, + sendGridApiKey: String, +): Boolean { if (!isPromotionLegal(slug)) { return false } val person = getPersonToNotify(slug, email) ?: return false - val user = transaction { - User.select { - User.email eq person.userEmail - }.firstOrNull() - } ?: return false + val user = + transaction { + User.select { + User.email eq person.userEmail + }.firstOrNull() + } ?: return false if (!isPersonLegalToNotify(slug, user[User.email])) { return false } - val emailSent = sendWaitingListEmail( - sendGridApiKey = sendGridApiKey, - email = user[User.alternateEmail] ?: user[User.email], - slug = slug, - uuid = person.uuid - ) + val emailSent = + sendWaitingListEmail( + sendGridApiKey = sendGridApiKey, + email = user[User.alternateEmail] ?: user[User.email], + slug = slug, + uuid = person.uuid, + ) if (!emailSent) { return false @@ -70,44 +80,48 @@ suspend fun notifyWaitinglistPerson(slug: String, email: String, sendGridApiKey: return true } -fun getPersonToNotify(slug: String, email: String): WaitinglistUUIDJson? { - val person = transaction { - WaitingListUUID.select { - WaitingListUUID.happeningSlug eq slug and - (WaitingListUUID.userEmail eq email) - }.firstOrNull() - } +fun getPersonToNotify( + slug: String, + email: String, +): WaitinglistUUIDJson? { + val person = + transaction { + WaitingListUUID.select { + WaitingListUUID.happeningSlug eq slug and + (WaitingListUUID.userEmail eq email) + }.firstOrNull() + } if (person != null) { return WaitinglistUUIDJson( person[WaitingListUUID.uuid], person[WaitingListUUID.userEmail], person[WaitingListUUID.happeningSlug], - person[WaitingListUUID.lastNotified].toString() + person[WaitingListUUID.lastNotified].toString(), ) } return null } fun isPromotionLegal(slug: String): Boolean { - val happening = transaction { - Happening.select { - Happening.slug eq slug - }.firstOrNull() - }?.let { - HappeningJson( - it[Happening.slug], - it[Happening.title], - it[Happening.registrationDate].toString(), - it[Happening.happeningDate].toString(), - selectSpotRanges(slug), - HAPPENING_TYPE.BEDPRES, - it[Happening.studentGroupName] ?: "", - it[Happening.studentGroupRegistrationDate].toString(), - emptyList(), - it[Happening.onlyForStudentGroups] - - ) - } ?: return false + val happening = + transaction { + Happening.select { + Happening.slug eq slug + }.firstOrNull() + }?.let { + HappeningJson( + it[Happening.slug], + it[Happening.title], + it[Happening.registrationDate].toString(), + it[Happening.happeningDate].toString(), + selectSpotRanges(slug), + HAPPENING_TYPE.BEDPRES, + it[Happening.studentGroupName] ?: "", + it[Happening.studentGroupRegistrationDate].toString(), + emptyList(), + it[Happening.onlyForStudentGroups], + ) + } ?: return false if (DateTime(happening.happeningDate).isBeforeNow) { return false @@ -123,14 +137,18 @@ fun isPromotionLegal(slug: String): Boolean { return true } -fun isPersonLegalToNotify(slug: String, userEmail: String): Boolean { +fun isPersonLegalToNotify( + slug: String, + userEmail: String, +): Boolean { val minutesBetweenNotifications = 30 - val lastNotified = transaction { - WaitingListUUID.select { - WaitingListUUID.happeningSlug eq slug - WaitingListUUID.userEmail eq userEmail - }.firstOrNull() - }?.let { res -> res[WaitingListUUID.lastNotified] } + val lastNotified = + transaction { + WaitingListUUID.select { + WaitingListUUID.happeningSlug eq slug + WaitingListUUID.userEmail eq userEmail + }.firstOrNull() + }?.let { res -> res[WaitingListUUID.lastNotified] } if (lastNotified != null && lastNotified.plusMinutes(minutesBetweenNotifications).isAfterNow) { return false @@ -140,7 +158,10 @@ fun isPersonLegalToNotify(slug: String, userEmail: String): Boolean { return true } -fun isPersonLegalToPromote(slug: String, userEmail: String): Boolean { +fun isPersonLegalToPromote( + slug: String, + userEmail: String, +): Boolean { // denne kan brukes til å sjekke trinn og prikker, hvis vi trenger det. return true } diff --git a/backend/src/main/kotlin/no/uib/echo/schema/Whitelist.kt b/backend/src/main/kotlin/no/uib/echo/schema/Whitelist.kt index ceeb05969..99e00ff85 100644 --- a/backend/src/main/kotlin/no/uib/echo/schema/Whitelist.kt +++ b/backend/src/main/kotlin/no/uib/echo/schema/Whitelist.kt @@ -7,7 +7,7 @@ import org.jetbrains.exposed.sql.jodatime.datetime @Serializable data class WhitelistJson( val email: String, - val expiresAt: String + val expiresAt: String, ) object Whitelist : Table("whitelist") { diff --git a/backend/src/test/kotlin/no/uib/echo/CommonData.kt b/backend/src/test/kotlin/no/uib/echo/CommonData.kt index 7cbbd7580..fabf7e708 100644 --- a/backend/src/test/kotlin/no/uib/echo/CommonData.kt +++ b/backend/src/test/kotlin/no/uib/echo/CommonData.kt @@ -13,10 +13,11 @@ import org.joda.time.DateTime val everyoneSpotRange = listOf(SpotRangeJson(50, 1, 5)) val oneTwoSpotRange = listOf(SpotRangeJson(50, 1, 2)) val threeFiveSpotRange = listOf(SpotRangeJson(50, 3, 5)) -val everyoneSplitSpotRange = listOf( - SpotRangeJson(5, 1, 2), - SpotRangeJson(5, 3, 5) -) +val everyoneSplitSpotRange = + listOf( + SpotRangeJson(5, 1, 2), + SpotRangeJson(5, 3, 5), + ) val everyoneInfiniteSpotRange = listOf(SpotRangeJson(0, 1, 5)) val onlyOneSpotRange = listOf(SpotRangeJson(1, 1, 5)) val fewSpotRange = listOf(SpotRangeJson(5, 1, 5)) @@ -29,7 +30,7 @@ val hap1: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-04-29T20:43:29Z", everyoneSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -41,7 +42,7 @@ val hap2: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-07-29T20:10:11Z", everyoneSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -53,7 +54,7 @@ val hap3: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2038-01-01T20:10:11Z", everyoneSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -65,7 +66,7 @@ val hap4: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-05-29T20:00:11Z", oneTwoSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -77,7 +78,7 @@ val hap5: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-06-29T18:07:31Z", threeFiveSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -89,7 +90,7 @@ val hap6: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-06-29T18:07:31Z", everyoneSplitSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -101,7 +102,7 @@ val hap7: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-06-29T18:07:31Z", everyoneInfiniteSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -113,7 +114,7 @@ val hap8: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-06-29T18:07:31Z", onlyOneSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -125,7 +126,7 @@ val hap9: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2030-02-18T16:27:05Z", fewSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -137,7 +138,7 @@ val hap10: (type: HAPPENING_TYPE) -> HappeningJson = { type -> "2020-02-28T16:15:00Z", fewSpotRange, type, - if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde" + if (type == HAPPENING_TYPE.BEDPRES) "bedkom" else "tilde", ) } @@ -151,8 +152,8 @@ val exReg: (slug: String, user: UserJson) -> FormRegistrationJson = { slug, user slug, listOf( AnswerJson("Skal du ha mat?", "Nei"), - AnswerJson("Har du noen allergier?", "Ja masse allergier ass 100") - ) + AnswerJson("Har du noen allergier?", "Ja masse allergier ass 100"), + ), ) } @@ -160,127 +161,138 @@ val deReg: (slug: String, user: UserJson) -> FormDeregistrationJson = { slug, us FormDeregistrationJson( user.email, slug, - "" + "", ) } -val user1 = UserJson( - "bast1@student.uib.no", - "Bachelor Student #1", - "bachelor.student1@gmail.com", - 2, - Degree.DSIK, - listOf("tilde"), - 0, - DateTime.now().toString(), - DateTime.now().toString() -) -val user2 = UserJson( - "bast2@student.uib.no", - "Bachelor Student #2", - "bachelor.student2@gmail.com", - 3, - Degree.DTEK, - listOf("webkom"), - 0, - DateTime.now().toString(), - DateTime.now().toString() -) -val user3 = UserJson( - "bast3@student.uib.no", - "Bachelor Student #3", - null, - 1, - Degree.DVIT, - listOf("bedkom", "tilde"), - 0, - DateTime.now().toString(), - DateTime.now().toString() -) -val user4 = UserJson( - "bast4@student.uib.no", - "Bachelor Student #4", - "bachelor.student4@gmail.com", - 2, - Degree.BINF, - strikes = 4, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) -val user5 = UserJson( - "bast5@student.uib.no", - "Bachelor Student #5", - "bachelor.student5@gmail.com", - 3, - Degree.IMO, - strikes = 2, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) +val user1 = + UserJson( + "bast1@student.uib.no", + "Bachelor Student #1", + "bachelor.student1@gmail.com", + 2, + Degree.DSIK, + listOf("tilde"), + 0, + DateTime.now().toString(), + DateTime.now().toString(), + ) +val user2 = + UserJson( + "bast2@student.uib.no", + "Bachelor Student #2", + "bachelor.student2@gmail.com", + 3, + Degree.DTEK, + listOf("webkom"), + 0, + DateTime.now().toString(), + DateTime.now().toString(), + ) +val user3 = + UserJson( + "bast3@student.uib.no", + "Bachelor Student #3", + null, + 1, + Degree.DVIT, + listOf("bedkom", "tilde"), + 0, + DateTime.now().toString(), + DateTime.now().toString(), + ) +val user4 = + UserJson( + "bast4@student.uib.no", + "Bachelor Student #4", + "bachelor.student4@gmail.com", + 2, + Degree.BINF, + strikes = 4, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) +val user5 = + UserJson( + "bast5@student.uib.no", + "Bachelor Student #5", + "bachelor.student5@gmail.com", + 3, + Degree.IMO, + strikes = 2, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) -val user6 = UserJson( - "mast1@student.uib.no", - "Master Student #1", - "master.student1@gmail.com", - 4, - Degree.INF, - strikes = 2, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) -val user7 = UserJson( - "mast2@student.uib.no", - "Master Student #2", - null, - 5, - Degree.PROG, - strikes = 2, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) -val user8 = UserJson( - "mast3@student.uib.no", - "Master Student #3", - "master.student3@gmail.com", - 5, - Degree.INF, - strikes = 2, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) +val user6 = + UserJson( + "mast1@student.uib.no", + "Master Student #1", + "master.student1@gmail.com", + 4, + Degree.INF, + strikes = 2, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) +val user7 = + UserJson( + "mast2@student.uib.no", + "Master Student #2", + null, + 5, + Degree.PROG, + strikes = 2, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) +val user8 = + UserJson( + "mast3@student.uib.no", + "Master Student #3", + "master.student3@gmail.com", + 5, + Degree.INF, + strikes = 2, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) -val user9 = UserJson( - "post@student.uib.no", - "Post Student", - "post.student@gmail.com", - 3, - Degree.POST, - strikes = 2, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) -val user10 = UserJson( - "arinf@student.uib.no", - "Årinf Student", - "arinf.student@gmail.com", - 1, - Degree.ARMNINF, - strikes = 2, - createdAt = DateTime.now().toString(), - modifiedAt = DateTime.now().toString() -) +val user9 = + UserJson( + "post@student.uib.no", + "Post Student", + "post.student@gmail.com", + 3, + Degree.POST, + strikes = 2, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) +val user10 = + UserJson( + "arinf@student.uib.no", + "Årinf Student", + "arinf.student@gmail.com", + 1, + Degree.ARMNINF, + strikes = 2, + createdAt = DateTime.now().toString(), + modifiedAt = DateTime.now().toString(), + ) -val adminUser = UserJson( - "admin@student.uib.no", - "Admin Dude", - "admin@gmail.com", - 5, - Degree.INF, - listOf("webkom"), - 0, - DateTime.now().toString(), - DateTime.now().toString() -) +val adminUser = + UserJson( + "admin@student.uib.no", + "Admin Dude", + "admin@gmail.com", + 5, + Degree.INF, + listOf("webkom"), + 0, + DateTime.now().toString(), + DateTime.now().toString(), + ) val users = listOf(user1, user2, user3, user4, user5, user6, user7, user8, user9, user10) val usersWithAdmin = users.plus(listOf(adminUser)) diff --git a/backend/src/test/kotlin/no/uib/echo/happening/DeleteHappeningTest.kt b/backend/src/test/kotlin/no/uib/echo/happening/DeleteHappeningTest.kt index 79375085b..4e9ff3661 100644 --- a/backend/src/test/kotlin/no/uib/echo/happening/DeleteHappeningTest.kt +++ b/backend/src/test/kotlin/no/uib/echo/happening/DeleteHappeningTest.kt @@ -26,12 +26,13 @@ import kotlin.test.Test class DeleteHappeningTest { companion object { - val db = DatabaseHandler( - env = Environment.PREVIEW, - migrateDb = false, - dbUrl = URI(System.getenv("DATABASE_URL")), - mbMaxPoolSize = null - ) + val db = + DatabaseHandler( + env = Environment.PREVIEW, + migrateDb = false, + dbUrl = URI(System.getenv("DATABASE_URL")), + mbMaxPoolSize = null, + ) } @BeforeTest @@ -51,16 +52,18 @@ class DeleteHappeningTest { @Test fun `When trying to delete a happening, server should respond with OK`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } for (t in be) { - val testCall = client.delete("/happening/${hap1(t).slug}") { - basicAuth("admin", System.getenv("ADMIN_KEY")) - } + val testCall = + client.delete("/happening/${hap1(t).slug}") { + basicAuth("admin", System.getenv("ADMIN_KEY")) + } testCall.status shouldBe HttpStatusCode.OK } @@ -69,16 +72,18 @@ class DeleteHappeningTest { @Test fun `When trying to delete a happening with wrong Authorization header, server should respond with UNAUTHORIZED`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } for (t in be) { - val testCall = client.delete("/happening/${hap1(t).slug}") { - basicAuth("admin", "wrong-password") - } + val testCall = + client.delete("/happening/${hap1(t).slug}") { + basicAuth("admin", "wrong-password") + } testCall.status shouldBe HttpStatusCode.Unauthorized } diff --git a/backend/src/test/kotlin/no/uib/echo/lib/UserValidationTest.kt b/backend/src/test/kotlin/no/uib/echo/lib/UserValidationTest.kt index 3ce970441..77dc16ab5 100644 --- a/backend/src/test/kotlin/no/uib/echo/lib/UserValidationTest.kt +++ b/backend/src/test/kotlin/no/uib/echo/lib/UserValidationTest.kt @@ -6,22 +6,23 @@ import org.junit.jupiter.api.Test data class TestCase( val degree: Degree?, val degreeYear: Int?, - val expected: Boolean + val expected: Boolean, ) class UserValidationTest { companion object { - val cases = listOf( - TestCase(Degree.DTEK, 1, true), - TestCase(Degree.DTEK, 4, false), - TestCase(Degree.DTEK, null, false), - TestCase(null, 1, false), - TestCase(null, null, false), - TestCase(Degree.ARMNINF, 1, true), - TestCase(Degree.ARMNINF, 2, false), - TestCase(Degree.DSC, 1, true), - TestCase(Degree.DSC, 4, true) - ) + val cases = + listOf( + TestCase(Degree.DTEK, 1, true), + TestCase(Degree.DTEK, 4, false), + TestCase(Degree.DTEK, null, false), + TestCase(null, 1, false), + TestCase(null, null, false), + TestCase(Degree.ARMNINF, 1, true), + TestCase(Degree.ARMNINF, 2, false), + TestCase(Degree.DSC, 1, true), + TestCase(Degree.DSC, 4, true), + ) } @Test diff --git a/backend/src/test/kotlin/no/uib/echo/registration/DeleteRegistrationsTest.kt b/backend/src/test/kotlin/no/uib/echo/registration/DeleteRegistrationsTest.kt index 10017375d..cdc02a30c 100644 --- a/backend/src/test/kotlin/no/uib/echo/registration/DeleteRegistrationsTest.kt +++ b/backend/src/test/kotlin/no/uib/echo/registration/DeleteRegistrationsTest.kt @@ -53,12 +53,13 @@ import kotlin.test.Test class DeleteRegistrationsTest { companion object { - val db = DatabaseHandler( - env = Environment.PREVIEW, - migrateDb = false, - dbUrl = URI(System.getenv("DATABASE_URL")), - mbMaxPoolSize = null - ) + val db = + DatabaseHandler( + env = Environment.PREVIEW, + migrateDb = false, + dbUrl = URI(System.getenv("DATABASE_URL")), + mbMaxPoolSize = null, + ) } @BeforeTest @@ -78,12 +79,13 @@ class DeleteRegistrationsTest { @Test fun `Should delete registrations properly`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val usersSublist = listOf(user1, user2, user3, user4, user5) val waitListUsers = listOf(user6, user7, user8, user9, user10) @@ -100,11 +102,12 @@ class DeleteRegistrationsTest { getTokenCall.status shouldBe HttpStatusCode.OK val token: String = getTokenCall.body() - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap9(t).slug, u)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap9(t).slug, u)) + } submitRegCall.status shouldBe HttpStatusCode.OK val res: RegistrationResponseJson = submitRegCall.body() @@ -118,11 +121,12 @@ class DeleteRegistrationsTest { getTokenCall.status shouldBe HttpStatusCode.OK val token: String = getTokenCall.body() - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap9(t).slug, u)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap9(t).slug, u)) + } submitRegCall.status shouldBe HttpStatusCode.Accepted val res: RegistrationResponseJson = submitRegCall.body() @@ -131,15 +135,16 @@ class DeleteRegistrationsTest { } for (u in usersSublist) { - val deleteRegCall = client.delete("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(adminToken) - setBody(deReg(hap9(t).slug, u)) - } + val deleteRegCall = + client.delete("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(adminToken) + setBody(deReg(hap9(t).slug, u)) + } deleteRegCall.status shouldBe HttpStatusCode.OK deleteRegCall.bodyAsText() shouldContain "Registration with email = ${u.email} and slug = ${ - hap9(t).slug + hap9(t).slug } deleted" } } diff --git a/backend/src/test/kotlin/no/uib/echo/registration/GetRegistrationsTest.kt b/backend/src/test/kotlin/no/uib/echo/registration/GetRegistrationsTest.kt index 3930b1479..b00503e76 100644 --- a/backend/src/test/kotlin/no/uib/echo/registration/GetRegistrationsTest.kt +++ b/backend/src/test/kotlin/no/uib/echo/registration/GetRegistrationsTest.kt @@ -57,12 +57,13 @@ import kotlin.test.Test class GetRegistrationsTest { companion object { - val db = DatabaseHandler( - env = Environment.PREVIEW, - migrateDb = false, - dbUrl = URI(System.getenv("DATABASE_URL")), - mbMaxPoolSize = null - ) + val db = + DatabaseHandler( + env = Environment.PREVIEW, + migrateDb = false, + dbUrl = URI(System.getenv("DATABASE_URL")), + mbMaxPoolSize = null, + ) } @BeforeTest @@ -82,12 +83,13 @@ class GetRegistrationsTest { @Test fun `Should get correct count of registrations and wait list registrations, and produce correct CSV list`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val usersSublist = listOf(user1, user2, user3, user4, user5) val waitListUsers = listOf(user6, user7, user8, user9, user10) @@ -114,8 +116,8 @@ class GetRegistrationsTest { null, null, newReg.answers, - u.memberships - ) + u.memberships, + ), ) val getTokenCall = client.get("/token/${u.email}") @@ -123,11 +125,12 @@ class GetRegistrationsTest { getTokenCall.status shouldBe HttpStatusCode.OK val token: String = getTokenCall.body() - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(newReg) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(newReg) + } if (u in usersSublist) { submitRegCall.status shouldBe HttpStatusCode.OK @@ -142,9 +145,10 @@ class GetRegistrationsTest { } } - val getHappeningInfoCall = client.get("/happening/${hap9(t).slug}") { - basicAuth("admin", System.getenv("ADMIN_KEY")) - } + val getHappeningInfoCall = + client.get("/happening/${hap9(t).slug}") { + basicAuth("admin", System.getenv("ADMIN_KEY")) + } getHappeningInfoCall.status shouldBe HttpStatusCode.OK val happeningInfo: HappeningInfoJson = getHappeningInfoCall.body() @@ -152,16 +156,18 @@ class GetRegistrationsTest { happeningInfo.spotRanges[0].regCount shouldBe hap9(t).spotRanges[0].spots happeningInfo.spotRanges[0].waitListCount shouldBe waitListUsers.size - val getRegistrationsListCall = client.get("/registration/${hap9(t).slug}?download=y&testing=y") { - bearerAuth(adminToken) - } + val getRegistrationsListCall = + client.get("/registration/${hap9(t).slug}?download=y&testing=y") { + bearerAuth(adminToken) + } getRegistrationsListCall.status shouldBe HttpStatusCode.OK getRegistrationsListCall.bodyAsText() shouldBe toCsv(regsList, testing = true) - val getRegistrationsListJsonCall = client.get("/registration/${hap9(t).slug}?json=y&testing=y") { - bearerAuth(adminToken) - } + val getRegistrationsListJsonCall = + client.get("/registration/${hap9(t).slug}?json=y&testing=y") { + bearerAuth(adminToken) + } getRegistrationsListJsonCall.status shouldBe HttpStatusCode.OK val registrationsList: List = getRegistrationsListJsonCall.body() @@ -175,16 +181,18 @@ class GetRegistrationsTest { @Test fun `Should respond properly when given invalid slug of happening when happening info is requested`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } for (t in be) { - val getHappeningInfoCall = client.get("/happening/random-slug-som-ikke-finnes") { - basicAuth("admin", System.getenv("ADMIN_KEY")) - } + val getHappeningInfoCall = + client.get("/happening/random-slug-som-ikke-finnes") { + basicAuth("admin", System.getenv("ADMIN_KEY")) + } getHappeningInfoCall.status shouldBe HttpStatusCode.NotFound getHappeningInfoCall.bodyAsText() shouldBe "Happening doesn't exist." diff --git a/backend/src/test/kotlin/no/uib/echo/registration/PostRegistrationsTest.kt b/backend/src/test/kotlin/no/uib/echo/registration/PostRegistrationsTest.kt index 784773734..1e02489eb 100644 --- a/backend/src/test/kotlin/no/uib/echo/registration/PostRegistrationsTest.kt +++ b/backend/src/test/kotlin/no/uib/echo/registration/PostRegistrationsTest.kt @@ -54,12 +54,13 @@ import kotlin.test.Test class PostRegistrationsTest { companion object { - val db = DatabaseHandler( - env = Environment.PREVIEW, - migrateDb = false, - dbUrl = URI(System.getenv("DATABASE_URL")), - mbMaxPoolSize = null - ) + val db = + DatabaseHandler( + env = Environment.PREVIEW, + migrateDb = false, + dbUrl = URI(System.getenv("DATABASE_URL")), + mbMaxPoolSize = null, + ) } @BeforeTest @@ -79,12 +80,13 @@ class PostRegistrationsTest { @Test fun `Registrations with valid data should submit correctly`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } for (u in users) { val getTokenCall = client.get("/token/${u.email}") @@ -93,11 +95,12 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap1(t).slug, u)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap1(t).slug, u)) + } u.degree shouldNotBe null @@ -112,12 +115,13 @@ class PostRegistrationsTest { @Test fun `The same user should be able to sign up for two different happenings`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") getTokenCall.status shouldBe HttpStatusCode.OK @@ -125,11 +129,12 @@ class PostRegistrationsTest { for (t in be) { for (slug in listOf(hap1(t).slug, hap2(t).slug)) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(slug, user1)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(slug, user1)) + } submitRegCall.status shouldBe HttpStatusCode.OK val res: RegistrationResponseJson = submitRegCall.body() @@ -142,12 +147,13 @@ class PostRegistrationsTest { @Test fun `Registration with valid data and empty question list should submit correctly`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") @@ -155,11 +161,12 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap1(t).slug, user1).copy(answers = emptyList())) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap1(t).slug, user1).copy(answers = emptyList())) + } submitRegCall.status shouldBe HttpStatusCode.OK val res: RegistrationResponseJson = submitRegCall.body() @@ -171,12 +178,13 @@ class PostRegistrationsTest { @Test fun `You should not be able to sign up for a happening more than once`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") @@ -184,22 +192,24 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap1(t).slug, user1)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap1(t).slug, user1)) + } submitRegCall.status shouldBe HttpStatusCode.OK val res: RegistrationResponseJson = submitRegCall.body() res.code shouldBe RegistrationResponse.OK - val submitRegAgainCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap1(t).slug, user1)) - } + val submitRegAgainCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap1(t).slug, user1)) + } submitRegAgainCall.status shouldBe HttpStatusCode.UnprocessableEntity val resAgain: RegistrationResponseJson = submitRegAgainCall.body() @@ -211,12 +221,13 @@ class PostRegistrationsTest { @Test fun `You should not be able to sign up for a happening more than once (wait list)`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall1 = client.get("/token/${user1.email}") @@ -229,33 +240,36 @@ class PostRegistrationsTest { val token2: String = getTokenCall2.body() for (t in be) { - val fillUpRegsCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token1) - setBody(exReg(hap8(t).slug, user1)) - } + val fillUpRegsCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token1) + setBody(exReg(hap8(t).slug, user1)) + } fillUpRegsCall.status shouldBe HttpStatusCode.OK val fillUpRes: RegistrationResponseJson = fillUpRegsCall.body() fillUpRes.code shouldBe RegistrationResponse.OK - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token2) - setBody(exReg(hap8(t).slug, user2)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token2) + setBody(exReg(hap8(t).slug, user2)) + } submitRegCall.status shouldBe HttpStatusCode.Accepted val res: RegistrationResponseJson = submitRegCall.body() res.code shouldBe RegistrationResponse.WaitList - val submitRegAgainCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token2) - setBody(exReg(hap8(t).slug, user2)) - } + val submitRegAgainCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token2) + setBody(exReg(hap8(t).slug, user2)) + } submitRegAgainCall.status shouldBe HttpStatusCode.UnprocessableEntity val resAgain: RegistrationResponseJson = submitRegAgainCall.body() @@ -267,12 +281,13 @@ class PostRegistrationsTest { @Test fun `You should not be able to sign up for a happening before the registration date`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") @@ -280,11 +295,12 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap3(t).slug, user1)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap3(t).slug, user1)) + } submitRegCall.status shouldBe HttpStatusCode.Forbidden val res: RegistrationResponseJson = submitRegCall.body() @@ -296,23 +312,25 @@ class PostRegistrationsTest { @Test fun `You should not be able to sign up for a happening after the happening date`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") getTokenCall.status shouldBe HttpStatusCode.OK val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap10(t).slug, user1)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap10(t).slug, user1)) + } submitRegCall.status shouldBe HttpStatusCode.Forbidden val res: RegistrationResponseJson = submitRegCall.body() @@ -324,12 +342,13 @@ class PostRegistrationsTest { @Test fun `You should not be able to sign up for a happening that doesn't exist`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") @@ -354,12 +373,13 @@ class PostRegistrationsTest { @Test fun `If a happening has filled up every spot, a registration should be put on the wait list`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user1.email}") @@ -367,11 +387,12 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap8(t).slug, user1)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap8(t).slug, user1)) + } submitRegCall.status shouldBe HttpStatusCode.OK val res: RegistrationResponseJson = submitRegCall.body() @@ -384,11 +405,12 @@ class PostRegistrationsTest { getOtherTokenCall.status shouldBe HttpStatusCode.OK val otherToken: String = getOtherTokenCall.body() - val submitRegWaitListCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(otherToken) - setBody(exReg(hap8(t).slug, u)) - } + val submitRegWaitListCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(otherToken) + setBody(exReg(hap8(t).slug, u)) + } submitRegWaitListCall.status shouldBe HttpStatusCode.Accepted val resAgain: RegistrationResponseJson = submitRegWaitListCall.body() @@ -401,12 +423,13 @@ class PostRegistrationsTest { @Test fun `You should not be able to sign up for a happening if you are not inside the degree year range`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall1 = client.get("/token/${user1.email}") @@ -419,22 +442,24 @@ class PostRegistrationsTest { val token2: String = getTokenCall2.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token1) - setBody(exReg(hap5(t).slug, user1)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token1) + setBody(exReg(hap5(t).slug, user1)) + } submitRegCall.status shouldBe HttpStatusCode.Forbidden val res: RegistrationResponseJson = submitRegCall.body() res.code shouldBe RegistrationResponse.NotInRange - val submitRegCall2 = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token2) - setBody(exReg(hap4(t).slug, user6)) - } + val submitRegCall2 = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token2) + setBody(exReg(hap4(t).slug, user6)) + } submitRegCall2.status shouldBe HttpStatusCode.Forbidden val res2: RegistrationResponseJson = submitRegCall.body() @@ -446,12 +471,13 @@ class PostRegistrationsTest { @Test fun `Should accept registrations for happening with infinite spots`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } for (u in users) { val getTokenCall = client.get("/token/${u.email}") @@ -459,11 +485,12 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap7(t).slug, u)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap7(t).slug, u)) + } submitRegCall.status shouldBe HttpStatusCode.OK val res: RegistrationResponseJson = submitRegCall.body() @@ -476,12 +503,13 @@ class PostRegistrationsTest { @Test fun `Should skip degreeYear check if user is in Bedkom and happeningType is BEDPRES`() = testApplication { - val client = createClient { - install(Logging) - install(ContentNegotiation) { - json() + val client = + createClient { + install(Logging) + install(ContentNegotiation) { + json() + } } - } val getTokenCall = client.get("/token/${user3.email}") @@ -489,11 +517,12 @@ class PostRegistrationsTest { val token: String = getTokenCall.body() for (t in be) { - val submitRegCall = client.post("/registration") { - contentType(ContentType.Application.Json) - bearerAuth(token) - setBody(exReg(hap5(t).slug, user3)) - } + val submitRegCall = + client.post("/registration") { + contentType(ContentType.Application.Json) + bearerAuth(token) + setBody(exReg(hap5(t).slug, user3)) + } if (t == HAPPENING_TYPE.BEDPRES) { submitRegCall.status shouldBe HttpStatusCode.OK