Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #6 from javaBin/bruker-registrering
Browse files Browse the repository at this point in the history
Merge bruker-registrering
  • Loading branch information
LemurP authored Feb 10, 2024
2 parents e87eea6 + 1a0ca38 commit 82b4024
Show file tree
Hide file tree
Showing 34 changed files with 532 additions and 242 deletions.
43 changes: 33 additions & 10 deletions backend/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ repositories {
}

dependencies {
implementation("io.ktor:ktor-server-sessions-jvm:2.3.6")
val ktor_version = "2.3.6"
val logback_version = "1.4.11"
val slf4j_version = "2.0.9"
Expand All @@ -31,16 +30,14 @@ dependencies {
val flyway_version = "10.6.0"
val hikari_version = "5.1.0"
val postgres_version = "42.7.1"
val exposed_version = "0.41.1"
val h2_version = "2.1.214"

// Use the Kotlin JUnit 5 integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")

// Use the JUnit 5 integration.
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")

implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")
testImplementation("io.ktor:ktor-server-test-host:$ktor_version")

runtimeOnly("ch.qos.logback:logback-classic:$logback_version")
Expand All @@ -49,13 +46,37 @@ dependencies {

// Auth
implementation("io.ktor:ktor-server-auth:$ktor_version")
implementation("io.ktor:ktor-server-auth-jvm:$ktor_version")
implementation("io.ktor:ktor-server-sessions:$ktor_version")
implementation("io.ktor:ktor-server-auth:jvm$ktor_version")
implementation("io.ktor:ktor-server-auth-jwt:$ktor_version")

// Ktor server dependencies
implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
implementation("io.ktor:ktor-server-resources:$ktor_version")
implementation("io.ktor:ktor-server-metrics-jvm:$ktor_version")
implementation("io.ktor:ktor-server-config-yaml:$ktor_version")
implementation("io.ktor:ktor-server-cors-jvm:$ktor_version")
implementation("io.ktor:ktor-server-sessions-jvm:$ktor_version")


//Ktor client dependencies
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-java:$ktor_version")
implementation("io.ktor:ktor-client-encoding:$ktor_version")

// Serialization
implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
implementation("io.ktor:ktor-client-content-negotiation-jvm:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:$ktor_version")

// Logging
implementation("io.ktor:ktor-server-call-logging-jvm:$ktor_version")
implementation("io.ktor:ktor-client-logging:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version")

// Auth
implementation("io.ktor:ktor-server-auth:$ktor_version")
implementation("io.ktor:ktor-server-auth-jwt:$ktor_version")

// Kotlin Query
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version")
Expand All @@ -66,7 +87,9 @@ dependencies {
// https://mvnrepository.com/artifact/org.flywaydb/flyway-core - database migrations
implementation("org.flywaydb:flyway-core:$flyway_version")
implementation("org.flywaydb:flyway-database-postgresql:$flyway_version")

implementation("org.jetbrains.exposed:exposed-core:$exposed_version")
implementation("org.jetbrains.exposed:exposed-jdbc:$exposed_version")
implementation("com.h2database:h2:$h2_version")
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP - connection pooling
implementation("com.zaxxer:HikariCP:$hikari_version")
// https://mvnrepository.com/artifact/org.postgresql/postgresql - database driver
Expand Down
52 changes: 19 additions & 33 deletions backend/app/src/main/kotlin/backend/App.kt
Original file line number Diff line number Diff line change
@@ -1,45 +1,34 @@
package backend

import backend.admin.AdminRepository
import backend.admin.adminRoutes
import backend.user.UserRepository
import backend.user.userRoutes
import backend.config.configureAuth
import backend.route.adminRoutes
import backend.route.userRoutes
import backend.repository.AdminRepository
import backend.repository.UserRepository
import com.inventy.plugins.DatabaseFactory
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun server() = embeddedServer(factory = Netty, port = 8080) {
createServer()
}

private fun Application.createServer() {
runMigration()
fun main(args: Array<String>): Unit =
io.ktor.server.netty.EngineMain.main(args)

fun Application.module() {
DatabaseFactory(
dbHost = environment.config.property("database.host").getString(),
dbPort = environment.config.property("database.port").getString(),
dbUser = environment.config.property("database.user").getString(),
dbPassword = environment.config.property("database.password").getString(),
databaseName = environment.config.property("database.databaseName").getString(),
embedded = environment.config.property("database.embedded").getString().toBoolean(),
).init()
configureAuth()
configureRouting()
}

class CustomPrincipal(val userId: Int) : Principal

fun Application.configureAuth() {
authentication {
basic(name = "basic") {
realm = "Ktor Server"
validate { credentials ->
if (credentials.name == "user" && credentials.password == "password") {
CustomPrincipal(1)
} else {
null
}
}
}
}
}


fun Application.configureRouting() {
val userRepository = UserRepository()
Expand All @@ -50,7 +39,7 @@ fun Application.configureRouting() {
}
routing {
userRoutes(userRepository)
adminRoutes(adminRepository)
adminRoutes(adminRepository, userRepository)
healthz()

get {
Expand All @@ -69,6 +58,3 @@ private fun Routing.healthz() {
}
}

fun main() {
server().start(wait = true)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package backend

import backend.domain.WorkshopRegistration
import backend.user.UserRepository
import backend.model.WorkshopRegistration
import backend.repository.UserRepository

class ViewRegisteredWorkshops(private val userRepository: UserRepository) {
fun viewRegisteredWorkshops(userId: Int): List<WorkshopRegistration> {
Expand Down

This file was deleted.

51 changes: 51 additions & 0 deletions backend/app/src/main/kotlin/backend/config/Auth.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package backend.config

import backend.repository.UserRepository
import com.auth0.jwk.JwkProviderBuilder
import com.auth0.jwt.interfaces.Payload
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import java.util.concurrent.TimeUnit

class CustomPrincipal(payload: Payload, val userId: Int): Principal, JWTPayloadHolder(payload)

fun Application.configureAuth() {
fun validateCreds(credential: JWTCredential): CustomPrincipal? {
val containsAudience = credential.payload.audience.contains(environment.config.property("auth0.audience").getString())

if (containsAudience) {
val userRepository = UserRepository()

val subject = credential.payload.subject
val providerId = subject.split("|")[1]
val provider = userRepository.findProviderById(providerId) ?: throw Exception("Provider not found")
return CustomPrincipal(credential.payload, provider.userId)
}

return null
}

val issuer = environment.config.property("auth0.issuer").getString()
val jwkProvider = JwkProviderBuilder(issuer)
.cached(10, 24, TimeUnit.HOURS)
.rateLimited(10, 1, TimeUnit.MINUTES)
.build()

install(Authentication) {
jwt("auth0") {
verifier(jwkProvider, issuer)
validate { credential -> validateCreds(credential) }
}
basic("basic-auth0") {
realm = "Used by auth0 for creating users"
validate { credentials ->
if (credentials.name == "auth0" && credentials.password == "password") {
UserIdPrincipal(credentials.name)
} else {
null
}
}
}
}
}
33 changes: 33 additions & 0 deletions backend/app/src/main/kotlin/backend/config/Client.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package backend.config

import io.ktor.client.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.http.*
import io.ktor.http.HttpHeaders.ContentEncoding
import io.ktor.serialization.kotlinx.json.*
import io.netty.handler.codec.compression.StandardCompressionOptions.deflate
import io.netty.handler.codec.compression.StandardCompressionOptions.gzip
import kotlinx.serialization.json.Json

fun HttpClientConfig<*>.defaultClient() {
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}

install(ContentEncoding){
gzip()
deflate()
}

install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
sanitizeHeader { header -> header == HttpHeaders.Authorization }
}
// Add all the common configuration here.
}
66 changes: 66 additions & 0 deletions backend/app/src/main/kotlin/backend/config/DatabaseFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.inventy.plugins

import com.zaxxer.hikari.HikariDataSource
import java.util.concurrent.TimeUnit.MINUTES
import org.jetbrains.exposed.sql.*
import kotlinx.coroutines.*
import org.flywaydb.core.Flyway
import org.postgresql.ds.PGSimpleDataSource
import org.h2.jdbcx.JdbcDataSource
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction

class DatabaseFactory(
private val dbHost: String,
private val dbPort: String,
private val dbUser: String,
private val dbPassword: String,
private val databaseName: String,
private val embedded: Boolean = false
) {

companion object {
suspend fun <T> dbQuery(block: suspend () -> T): T =
newSuspendedTransaction(Dispatchers.IO) { block() }
}

fun init() {
Database.connect(hikari())
val flyway = Flyway.configure()
.dataSource(hikari())
.load()
flyway.migrate()
}

private fun hikari(): HikariDataSource {
if (embedded) {
return HikariDataSource().apply {
dataSourceClassName = JdbcDataSource::class.qualifiedName
addDataSourceProperty("url", "jdbc:h2:mem:inventy;DB_CLOSE_DELAY=-1")
addDataSourceProperty("user", "root")
addDataSourceProperty("password", "")
maximumPoolSize = 10
minimumIdle = 1
idleTimeout = 100000
connectionTimeout = 100000
maxLifetime = MINUTES.toMillis(30)
}
} else {
return HikariDataSource().apply {
dataSourceClassName = PGSimpleDataSource::class.qualifiedName
addDataSourceProperty("serverName", dbHost)
addDataSourceProperty("portNumber", dbPort)
addDataSourceProperty("user", dbUser)
addDataSourceProperty("password", dbPassword)
addDataSourceProperty("databaseName", databaseName)
maximumPoolSize = 10
minimumIdle = 1
idleTimeout = 100000
connectionTimeout = 100000
maxLifetime = MINUTES.toMillis(30)
}
}


}

}
43 changes: 43 additions & 0 deletions backend/app/src/main/kotlin/backend/config/TestData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package backend.config

import backend.model.*


class TestData {
companion object {
val provider1 = listOf(Provider(1, 1, ProviderType.GOOGLE.id, "1234567890"))

val user1 = User(1, "John", "Doe", "[email protected]", "", provider1)
val user2 = User(2, "Jane", "Doe", "[email protected]","", provider1)
val user3 = User(3, "John", "Smith", "[email protected]","", provider1)

val workshop1 = Workshop(1, "Kotlin", "John Doe")
val workshop2 = Workshop(2, "Ktor", "Jane Doe")
val workshop3 = Workshop(3, "Kotlin Multiplatform", "John Doe")


val userMap =
mutableMapOf(
1 to user1,
2 to user2,
3 to user3,
)

val registrationMap =
mutableMapOf(
1 to WorkshopRegistration(1, user1, workshop1, WorkshopRegistrationState.APPROVED),
2 to WorkshopRegistration(2, user1, workshop2, WorkshopRegistrationState.APPROVED),
3 to WorkshopRegistration(3, user2, workshop1, WorkshopRegistrationState.APPROVED),
4 to WorkshopRegistration(4, user3, workshop3, WorkshopRegistrationState.APPROVED),
)

val workshopMap: MutableMap<Int, Workshop> =
mutableMapOf(
1 to workshop1,
2 to workshop2,
3 to workshop3,
)

}
}

3 changes: 0 additions & 3 deletions backend/app/src/main/kotlin/backend/domain/User.kt

This file was deleted.

3 changes: 0 additions & 3 deletions backend/app/src/main/kotlin/backend/domain/Workshop.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package backend.admin
package backend.dto

import backend.dto.AdminWorkshopRegistrationDTO
import kotlinx.serialization.Serializable

@Serializable
data class AdminWorkshopDTO(
val title: String,
val teacherName: String,
val registrations: List<AdminWorkshopRegistration>,
val registrations: List<AdminWorkshopRegistrationDTO>,
)
Loading

0 comments on commit 82b4024

Please sign in to comment.