From bf1fc33469ffab02810830c1ef13a0a15c697aba Mon Sep 17 00:00:00 2001 From: efim Date: Sun, 23 Jul 2023 20:05:27 +0000 Subject: [PATCH] feat: setting auth cookie and index page logic --- build.sbt | 2 + src/main/scala/example/AuthService.scala | 112 ++++++++++++++++---- src/main/scala/example/pocketbase/Api.scala | 2 +- 3 files changed, 94 insertions(+), 22 deletions(-) diff --git a/build.sbt b/build.sbt index 1b1f678..49c579b 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,7 @@ ThisBuild / scalaVersion := "3.3.0" +fork := true + libraryDependencies += "com.lihaoyi" %% "upickle" % "3.1.2" libraryDependencies += "com.lihaoyi" %% "requests" % "0.8.0" libraryDependencies += "com.lihaoyi" %% "cask" % "0.9.1" diff --git a/src/main/scala/example/AuthService.scala b/src/main/scala/example/AuthService.scala index d5762ab..8de9380 100644 --- a/src/main/scala/example/AuthService.scala +++ b/src/main/scala/example/AuthService.scala @@ -4,27 +4,79 @@ import AuthService._ import example.pocketbase.Api import upickle.default._ import example.pocketbase.Models._ +import java.time.Instant case class AuthService()(implicit cc: castor.Context, log: cask.Logger) extends cask.Routes { @cask.get("/") def getIndex(request: cask.Request) = { - println("hellololo") val authCookieOpt = request.cookies.get(authCookieName) + println(s"getting index with auth cookie: $authCookieOpt") authCookieOpt match { case None => - cask.Redirect("/login") + println("cookie was None") + val redirectingHtml = """ + + + + + + +

You will be redirected to w3docs.com soon!

+ + +""" + cask.Response( + redirectingHtml, + 200, + Seq( + "Content-Type" -> "text/html;charset=UTF-8", + "Cache-Control" -> "Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate" + ) + ) case Some(authCookie) => val jwt = authCookie.value - ??? + val refreshedSession = pocketbaseApi.refreshSession(jwt) + refreshedSession match { + case Right(freshAuth) => + val indexHtml = s""" +

Ok, good

+

user should be already created, current jwt : ${freshAuth.token}

+

the account is on ${freshAuth.record.email} and ${freshAuth.record.username}

+""" + cask.Response( + indexHtml, + headers = Seq("Content-Type" -> "text/html;charset=UTF-8"), + cookies = + Seq(cask.Cookie(name = authCookieName, value = freshAuth.token)) + ) + case Left(err) => + val indexHtml = """ +

Ok, not good at all

+

For some reason error during authorization

+

You can try again here +""" + cask.Response( + indexHtml, + headers = Seq("Content-Type" -> "text/html;charset=UTF-8"), + cookies = Seq( + cask.Cookie( + name = authCookieName, + value = "", + expires = Instant.EPOCH + ) + ) + ) + } } } @cask.get("/login") def getLoginPage() = { // render auth page with the available oauth providers + println("landed on login page") val authOptions = pocketbaseApi.listAuthMethods() val options = s"got following auth opitons: $authOptions" @@ -47,7 +99,9 @@ case class AuthService()(implicit cc: castor.Context, log: cask.Logger) cask.Response( html, headers = Seq("Content-Type" -> "text/html;charset=UTF-8"), - cookies = Seq(cask.Cookie(name = oauthVerifiersCookieName, value = yoyo)) + cookies = Seq( + cask.Cookie(name = oauthVerifiersCookieName, value = yoyo, path = "/") + ) ) } @@ -88,16 +142,43 @@ case class AuthService()(implicit cc: castor.Context, log: cask.Logger) val okMessageFirst = resultOpt match { case None => // i guess with the SSR i'll need to return message about unsuccessful auth? - s""" + val unsuccessHtml = s"""

Auth unsuccessful

""" + cask.Response( + unsuccessHtml, + headers = Seq("Content-Type" -> "text/html;charset=UTF-8") + ) case Some(result) => // this is already fully successful auth - s""" -

Ok, good

-

user should be already created, current jwt : ${result.token}

-

the account is on ${result.record.email} and ${result.record.username}

+ val redirectingHtml = """ + + + + + + +

Successful authorization, you will be redirected to main page soon.

+ + """ + cask.Response( + redirectingHtml, + headers = Seq("Content-Type" -> "text/html;charset=UTF-8"), + cookies = Seq( + cask.Cookie( + name = authCookieName, + value = result.token, + path = "/" + ), + cask.Cookie( + name = oauthVerifiersCookieName, + value = "", + expires = Instant.EPOCH, + path = "/" + ) + ) + ) } /* @@ -112,18 +193,7 @@ and delete the state\verifiers cookie but then what? i guess call for redirect to root page again? which should trigger auth check and main page render? */ - import java.time.Instant - cask.Response( - okMessageFirst, - headers = Seq("Content-Type" -> "text/html;charset=UTF-8"), - cookies = Seq( - cask.Cookie( - name = oauthVerifiersCookieName, - value = "", - expires = Instant.now() - ) - ) - ) + okMessageFirst } initialize() diff --git a/src/main/scala/example/pocketbase/Api.scala b/src/main/scala/example/pocketbase/Api.scala index 76ea9e2..c9679a5 100644 --- a/src/main/scala/example/pocketbase/Api.scala +++ b/src/main/scala/example/pocketbase/Api.scala @@ -7,7 +7,7 @@ import requests.Response final case class Api(pocketbaseUrl: String, usersCollection: String = "users") { def refreshSession(jwt: String): Either[Error, AuthReply] = { - val path = s"/api/collections/${pocketbaseUrl}/auth-refresh" + val path = s"/api/collections/${usersCollection}/auth-refresh" val refreshResult = requests.post( url = pocketbaseUrl ++ path,