From 14aa195bb384eb5ba4acd2c0bbe3e88e33826d1e Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Sun, 12 Apr 2020 02:33:48 +0200 Subject: [PATCH] Implement user creation endpoint + persistance and hash to db --- api/pom.xml | 6 +++ api/src/NotesApplication.kt | 3 ++ api/src/controllers/UserController.kt | 66 +++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index 32470b9..8086402 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -17,6 +17,7 @@ 6.5.4 6.3.3 3.10.2 + 0.4 official UTF-8 @@ -127,6 +128,11 @@ flyway-core ${flyway_version} + + org.mindrot + jbcrypt + ${jbcrypt_version} + ${project.basedir}/src diff --git a/api/src/NotesApplication.kt b/api/src/NotesApplication.kt index 2674808..3264b45 100644 --- a/api/src/NotesApplication.kt +++ b/api/src/NotesApplication.kt @@ -16,6 +16,7 @@ import io.ktor.features.ContentNegotiation import io.ktor.jackson.jackson import io.ktor.locations.Locations import io.ktor.routing.routing +import me.liuwj.ktorm.database.Database import org.kodein.di.Kodein import org.kodein.di.description import org.kodein.di.generic.bind @@ -35,12 +36,14 @@ fun Application.module() { import(configurationModule) bind() with singleton { Migration(this.kodein) } + bind() with singleton { Database.Companion.connect(this.instance()) } } features() log.debug(kodein.container.tree.bindings.description()) + // TODO, clean this (migration) val feature: Feature by kodein.instance() feature.execute() diff --git a/api/src/controllers/UserController.kt b/api/src/controllers/UserController.kt index 717be2a..df03540 100644 --- a/api/src/controllers/UserController.kt +++ b/api/src/controllers/UserController.kt @@ -2,7 +2,9 @@ package be.vandewalleh.controllers import be.vandewalleh.auth.SimpleJWT import be.vandewalleh.auth.UsernamePasswordCredential +import be.vandewalleh.entities.User import be.vandewalleh.errors.ApiError +import be.vandewalleh.tables.Users import io.ktor.application.call import io.ktor.http.HttpStatusCode import io.ktor.locations.Location @@ -10,26 +12,74 @@ import io.ktor.locations.post import io.ktor.request.receive import io.ktor.response.respond import io.ktor.routing.Routing +import me.liuwj.ktorm.database.Database +import me.liuwj.ktorm.dsl.eq +import me.liuwj.ktorm.dsl.from +import me.liuwj.ktorm.dsl.select +import me.liuwj.ktorm.dsl.where +import me.liuwj.ktorm.entity.add +import me.liuwj.ktorm.entity.sequenceOf import org.kodein.di.Kodein import org.kodein.di.generic.instance +import org.mindrot.jbcrypt.BCrypt +import java.time.LocalDateTime class UserController(kodein: Kodein) : KodeinController(kodein) { private val simpleJwt by instance() + private val db by instance() override fun Routing.registerRoutes() { - post { - val post = call.receive() + post { + data class Response(val token: String) - // TODO check db - if (post.username != "test" || post.password != "test") + val credential = call.receive() + + val (email, password) = db.from(Users) + .select(Users.email, Users.password) + .where { Users.username eq credential.username } + .map { row -> row[Users.email]!! to row[Users.password]!! } + .firstOrNull() + ?: return@post call.respond(HttpStatusCode.BadRequest, ApiError.InvalidCredentialError()) + + + if (!BCrypt.checkpw(credential.password, password)) { return@post call.respond(HttpStatusCode.BadRequest, ApiError.InvalidCredentialError()) + } - return@post call.respond(mapOf("token" to simpleJwt.sign("test@test.be"))) + return@post call.respond(Response(simpleJwt.sign(email))) + } + + post { + data class Response(val message: String) + + val user = call.receive() + + // TODO check if user does not already exists + // db won't let you insert it anyway + + val hashedPassword = BCrypt.hashpw(user.password, BCrypt.gensalt()) + + val newUser = User { + this.username = user.username + this.email = user.email + this.password = hashedPassword + this.createdAt = LocalDateTime.now() + } + + db.sequenceOf(Users).add(newUser) + + call.respond(HttpStatusCode.Created, Response("User created successfully")) } } object Routes { - @Location("/auth") - class Auth + @Location("/signin") + class SignIn + + @Location("/signup") + class SignUp + } -} \ No newline at end of file +} + +data class SignUpInfo(val username: String, val email: String, val password: String) \ No newline at end of file