From f742acd6f90cf6a857129152443414c760f2612c Mon Sep 17 00:00:00 2001 From: efim Date: Sun, 23 Jul 2023 13:34:43 +0000 Subject: [PATCH] feat: routes with github auth & redirect --- build.sbt | 2 + project/plugins.sbt | 1 + project/project/project/metals.sbt | 6 ++ src/main/resources/out.css | 8 --- src/main/scala/example/AuthService.scala | 84 ++++++++++++++++++++++++ src/main/scala/example/Main.scala | 22 ++++++- testing-rest.txt | 3 + 7 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 project/plugins.sbt create mode 100644 project/project/project/metals.sbt create mode 100644 src/main/scala/example/AuthService.scala create mode 100644 testing-rest.txt diff --git a/build.sbt b/build.sbt index 670c0d5..1b1f678 100644 --- a/build.sbt +++ b/build.sbt @@ -2,3 +2,5 @@ ThisBuild / scalaVersion := "3.3.0" libraryDependencies += "com.lihaoyi" %% "upickle" % "3.1.2" libraryDependencies += "com.lihaoyi" %% "requests" % "0.8.0" +libraryDependencies += "com.lihaoyi" %% "cask" % "0.9.1" +libraryDependencies += "com.lihaoyi" %% "mainargs" % "0.5.0" diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..59cd318 --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("io.spray" % "sbt-revolver" % "0.10.0") diff --git a/project/project/project/metals.sbt b/project/project/project/metals.sbt new file mode 100644 index 0000000..05fd2b3 --- /dev/null +++ b/project/project/project/metals.sbt @@ -0,0 +1,6 @@ +// DO NOT EDIT! This file is auto-generated. + +// This file enables sbt-bloop to create bloop config files. + +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6") + diff --git a/src/main/resources/out.css b/src/main/resources/out.css index 4dad71b..ed795c8 100644 --- a/src/main/resources/out.css +++ b/src/main/resources/out.css @@ -578,14 +578,6 @@ video { border-bottom-width: 8px; } -.border-t-8 { - border-top-width: 8px; -} - -.border-r-8 { - border-right-width: 8px; -} - .border-blue-400 { --tw-border-opacity: 1; border-color: rgb(96 165 250 / var(--tw-border-opacity)); diff --git a/src/main/scala/example/AuthService.scala b/src/main/scala/example/AuthService.scala new file mode 100644 index 0000000..38c2428 --- /dev/null +++ b/src/main/scala/example/AuthService.scala @@ -0,0 +1,84 @@ +package example + +import AuthService._ +import example.pocketbase.Api + +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) + + authCookieOpt match { + case None => + cask.Redirect("/login") + case Some(authCookie) => + val jwt = authCookie.value + ??? + } + } + + @cask.get("/login") + def getLoginPage() = { + // render auth page with the available oauth providers + val authOptions = pocketbaseApi.listAuthMethods().authProviders + + val options = s"got following auth opitons: $authOptions" + // save states and verifiers into cookie + + val githubOption = authOptions.find(_.name == "github") + + val githubRedirect = githubOption.map(_.authUrl).getOrElse("") ++ getRedirectUrl("github") + + val html = s""" +

good enough, right

+

$options

+

will use ${githubRedirect}

+Go to github +""" + cask.Response( + html, + headers = Seq("Content-Type" -> "text/html;charset=UTF-8"), + ) + } + + @cask.get(s"${baseRedirectUrl}/:provider") + def receiveOauthRedirect(provider: String, state: String, code: String) = { + println(s"received redirect for $provider with state: $state and code: $code") + /* + * + get provider from path param, get verifiers and state from cookie, +if cookie not present - abort, +if state doesn't fit one from redirect params - abort +issue 'auth with oauth 2' and based on response code - set the cookie with jwt + +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? + */ + s"received redirect for $provider with state: $state and code: $code" + } + + initialize() +} + +object AuthService { + val authCookieName = "auth" + val pocketbaseApi = Api("http://127.0.0.1:8090") + val selfUri = "http://127.0.0.1:8080" + + // i guess TOOD put that into config + val baseRedirectUrl = "/api/oauth2-redirect" + + /* + * let's have separate redirect urls for different providers + * if we'd have same url for all providers, we'll need way to figure out from state which one was called on front end. + * it's possible, but path param looks simpler right now + * github redirect : http://127.0.0.1:8080/api/oauth2-redirect/github + */ + def getRedirectUrl(provider: String): String = + s"${selfUri}${baseRedirectUrl}/${provider}" +} diff --git a/src/main/scala/example/Main.scala b/src/main/scala/example/Main.scala index 248e040..b19796b 100644 --- a/src/main/scala/example/Main.scala +++ b/src/main/scala/example/Main.scala @@ -1,4 +1,22 @@ package example -@main def main(args: String*): Unit = - println(s"Hello ${args.mkString}") +import mainargs.{main, arg, ParserForMethods} + +object Main { + @main def run( + @arg(name="port", short='p', doc="Port on which server will start service") + portArg: Int = 8080, + @arg(name="host", doc="Host on which server will start serving") + hostArg: String = "localhost" + ): Unit = { + println(s"Will start server on ${hostArg}:${portArg}") + val server = new cask.Main { + override def allRoutes: Seq[cask.main.Routes] = Seq(AuthService()) + override def port: Int = portArg + override def host: String = hostArg + } + server.main(Array.empty) + } + + def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) +} diff --git a/testing-rest.txt b/testing-rest.txt new file mode 100644 index 0000000..648da2c --- /dev/null +++ b/testing-rest.txt @@ -0,0 +1,3 @@ + + # let's check root redirect to auth +GET http://localhost:8080/