package be.simplenotes.app.controllers import be.simplenotes.app.extensions.html import be.simplenotes.app.extensions.isSecure import be.simplenotes.app.extensions.redirect import be.simplenotes.app.views.UserView import be.simplenotes.domain.security.JwtPayload import be.simplenotes.domain.usecases.UserService import be.simplenotes.domain.usecases.users.login.* import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm import be.simplenotes.domain.usecases.users.register.RegisterForm import be.simplenotes.domain.usecases.users.register.UserExists import be.simplenotes.shared.config.JwtConfig import org.http4k.core.Method.GET import org.http4k.core.Request import org.http4k.core.Response import org.http4k.core.Status.Companion.OK import org.http4k.core.body.form import org.http4k.core.cookie.Cookie import org.http4k.core.cookie.SameSite import org.http4k.core.cookie.cookie import org.http4k.core.cookie.invalidateCookie import java.util.concurrent.TimeUnit class UserController( private val userService: UserService, private val userView: UserView, private val jwtConfig: JwtConfig, ) { fun register(request: Request, jwtPayload: JwtPayload?): Response { if (request.method == GET) return Response(OK).html( userView.register(jwtPayload) ) val result = userService.register(request.registerForm()) return result.fold( { val html = when (it) { UserExists -> userView.register( jwtPayload, error = "User already exists" ) is InvalidRegisterForm -> userView.register( jwtPayload, validationErrors = it.validationErrors ) } Response(OK).html(html) }, { Response.redirect("/login") } ) } private fun Request.registerForm() = RegisterForm(form("username"), form("password")) private fun Request.loginForm(): LoginForm = registerForm() fun login(request: Request, jwtPayload: JwtPayload?): Response { if (request.method == GET) return Response(OK).html( userView.login(jwtPayload) ) val result = userService.login(request.loginForm()) return result.fold( { val html = when (it) { Unregistered -> userView.login( jwtPayload, error = "User does not exist" ) WrongPassword -> userView.login( jwtPayload, error = "Wrong password" ) is InvalidLoginForm -> userView.login( jwtPayload, validationErrors = it.validationErrors ) } Response(OK).html(html) }, { token -> Response.redirect("/").loginCookie(token, request.isSecure()) } ) } private fun Response.loginCookie(token: Token, secure: Boolean): Response { val validityInSeconds = TimeUnit.SECONDS.convert(jwtConfig.validity, jwtConfig.timeUnit) return this.cookie( Cookie( name = "Bearer", value = token, path = "/", httpOnly = true, sameSite = SameSite.Lax, maxAge = validityInSeconds, secure = secure ) ) } fun logout(@Suppress("UNUSED_PARAMETER") request: Request) = Response.redirect("/") .invalidateCookie("Bearer") }