working on login
continuous-integration/drone/push Build is failing Details

drone-setup
Override-6 2 years ago
parent f9ba0b9af3
commit e5cd7b897a

@ -1,27 +0,0 @@
version = "3.6.1"
runner.dialect = "scala3"
assumeStandardLibraryStripMargin = true
newlines.source = keep
rewrite.scala3 {
convertToNewSyntax = yes
removeOptionalBraces = yes
}
align {
preset = some
openParenCallSite = false
stripMargin = true
}
continuationIndent {
callSite = 2
defnSite = 4
}
docstrings {
style = Asterisk
oneline = keep
wrap = no
}

@ -0,0 +1,3 @@
#may not be a public url
emitter.url=localhost:4454
eme=dzq=d=qzd=qz=d

@ -13,13 +13,12 @@ object EndpointSetup:
private final val EndpointPort = "endpoint.port"
private final val EndpointPortDefault = "48485"
def setupEndpoint(config: Properties, db: ZioContext[SqliteDialect, Literal]): Endpoint =
def setupEndpoint(config: Properties): Endpoint =
Main.LOG.debug("Initializing API endpoint...")
val endpoint = createEndpoint(config)
endpoint.bind("counter")(IncrementHandler)
endpoint.bind("login")(new LoginHandler(sessions, db))
endpoint.bind("login")(new LoginHandler())
endpoint
private def createEndpoint(config: Properties): Endpoint =

@ -14,10 +14,10 @@ import scala.util.control.NonFatal
object Main extends ZIOAppDefault:
final val LOG = LogManager.getLogger("Core")
override def run: ZIO[Main.Environment with ZIOAppArgs with Scope, Any, Any] =
override def run =
val config = retrieveConfig
val db = new Database(config)
EndpointSetup.setupEndpoint(config, db.layer).run
EndpointSetup.setupEndpoint(config).run.provideLayer(db.layer)
private def retrieveConfig: Properties =
val configFile = Path.of("server.properties")

@ -0,0 +1,23 @@
package org.tbasket.auth
import io.netty.channel.ChannelHandlerContext
import org.tbasket.db.schemas.User
import pdi.jwt.JwtClaim
import zio.http.{Client, Request, URL}
import zio.*
import java.io.ByteArrayInputStream
class JWTClient(url: URL) {
private def mkRequest(user: User): JwtClaim = {
Request.get(url)
.body
.write(new ByteArrayInputStream(Array.emptyByteArray))
}
def requestJwt(user: User): Task[JwtClaim] = {
}
}

@ -1,7 +0,0 @@
package org.tbasket.auth
import org.tbasket.db.schemas.User
import java.util.UUID
case class UserSession(user: User, token: UUID, expirationDate: Long)

@ -1,25 +1,23 @@
package org.tbasket.handler
import io.getquill.*
import io.getquill.context.qzio.ZioContext
import org.tbasket.api.compute.APIRequestHandler
import org.tbasket.auth.JWTClient
import org.tbasket.db.Database.ctx.*
import org.tbasket.db.schemas.User
import org.tbasket.auth.{UserSession, UserSessionHandler}
import org.tbasket.handler.HandlerUtils.errorBody
import org.tbasket.handler.LoginError.{InvalidRequest, *}
import zio.http.model.{Cookie, Header, Headers, Status}
import zio.http.{Body, Request, Response}
import zio.http.{Body, Client, Request, Response, URL}
import zio.json.*
import zio.json.ast.Json.Str
import zio.json.ast.{Json, JsonCursor}
import zio.{ZEnvironment, ZIO}
import zio.*
import io.getquill.context.qzio.ZioContext
import org.tbasket.handler.HandlerUtils.errorBody
import org.tbasket.handler.LoginError.InvalidRequest
import zio.{ZEnvironment, ZIO, *}
import javax.sql.DataSource
import java.sql.SQLException
import java.util.UUID
import javax.sql.DataSource
enum LoginError:
case TokenNotFound(token: UUID)
@ -29,14 +27,13 @@ enum LoginError:
case InternalError(t: Throwable)
import LoginError.*
class LoginHandler(sessions: UserSessionHandler, ctx: ZioContext[SqliteDialect, Literal]) extends APIRequestHandler:
class LoginHandler extends APIRequestHandler:
private def getUser(json: Json) =
val r =
ZIO.serviceWithZIO[ZioContext[SqliteDialect, Literal]] { ctx =>
import ctx.*
private def getUser(json: Json): IO[LoginError, User] =
val r: ZIO[DataSource, LoginError, Option[User]] = for
for
mail <-
ZIO.fromEither(json.get[Str](JsonCursor.field("mail").isString).map(_.value))
.mapError(InvalidRequest("Missing or invalid field mail", _))
@ -50,39 +47,52 @@ class LoginHandler(sessions: UserSessionHandler, ctx: ZioContext[SqliteDialect,
)
}).mapError(InternalError.apply)
yield result.headOption
r.someOrFail(InvalidPassword).provideSome(ZLayer.succeed(ctx))
}
r.someOrFail(InvalidPassword)
override def post(request: Request): URIO[Console, Response] =
val bindSession: ZIO[Console, LoginError, UserSession] =
override def post(request: Request): Task[Response] =
val bindSession =
for
body <- request
.body
.asString
.tapError(Console.printError(_))
.mapError(s => InvalidRequest("Wrong request body", s.getMessage)): IO[LoginError, String]
.mapError(s =>
InvalidRequest("Wrong request body", s.getMessage)
)
json <- ZIO.fromEither(body.fromJson[Json])
.mapError(InvalidRequest("Invalid JSON body", _)): IO[LoginError, Json]
.mapError(InvalidRequest("Invalid JSON body", _))
user <- getUser(json): IO[LoginError, User]
session <- sessions.bind(user): IO[LoginError, UserSession]
yield session
user <- getUser(json)
jwt <- ZIO.serviceWithZIO[JWTClient](_.requestJwt(user))
yield (user, jwt)
bindSession.map { sess =>
Response(
status = Status.Ok,
body = Body.fromString(s"""{"token": "${sess.token}"}"""),
status = Status.Found,
headers = Headers.location("/") ++ //login successful, go back to main page
Headers.setCookie(Cookie(
"JWT", "Jw"
))
)
}.mapError {
} fold( {
_ match
case TokenNotFound(_) => Response(
status = Status.Unauthorized,
body = errorBody("unauthorized", "unknown token"),
headers = Headers(Headers.location("/login")) //send back caller to login panel
headers =
Headers(
Headers.location("/login")
) // send back caller to login panel
)
case UserNotFound(_) => Response(
status = Status.Unauthorized,
body = errorBody("unauthorized", "unknown user email"),
headers = Headers(Headers.location("/register")) //send back caller to register panel
headers =
Headers(
Headers.location("/register")
) // send back caller to register panel
)
case InvalidPassword => Response(
status = Status.Unauthorized,
@ -96,5 +106,4 @@ class LoginHandler(sessions: UserSessionHandler, ctx: ZioContext[SqliteDialect,
status = Status.InternalServerError,
body = errorBody("internal", "internal error, please contact support")
)
}
}, x => x)

@ -0,0 +1,19 @@
package org.tbasket.handler
import org.tbasket.api.compute.APIRequestHandler
import zio.*
import zio.http.model.Status
import zio.http.{Request, Response}
trait LoginRequiredRequestHandler extends APIRequestHandler:
override final def get: Task[Response] =
ZIO.succeed(Response(Status.MethodNotAllowed))
override final def post: Task[Response] = {
ZIO.succeed(Response(Status.MethodNotAllowed))
}
protected def authGet: Task[Response]
protected def authPost: Task[Response]

@ -1,6 +1,6 @@
CREATE TABLE user
(
id int PRIMARY KEY,
id varchar(32) PRIMARY KEY,
name varchar(30) NOT NULL,
mail_address varchar NOT NULL UNIQUE,
forename varchar(30) NOT NULL,

@ -11,25 +11,14 @@ import javax.sql
class Database(config: Properties):
private val source = new SQLiteDataSource() with Closeable:
override def close(): Unit = ()
private val source = new SQLiteDataSource()
source.setUrl(config.getProperty("database.url"))
val layer = DataSourceLayer.fromDataSource(source)
val layer = ZLayer.succeed(source)
object Database:
val ctx = new SqliteZioJdbcContext(Literal)
import ctx.*
/* override def run = {
DataService.getPeople
.provide(
DataService.live,
Quill.Postgres.fromNamingStrategy(SnakeCase),
Quill.DataSource.fromPrefix("myDatabaseConfig")
)
.debug("Results")
.exitCode
}
*/

@ -3,13 +3,16 @@ package org.tbasket.db.schemas
import io.getquill.*
import org.tbasket.db.Database
import java.util.UUID
case class User(
id: Int,
id : UUID,
name : String,
forename : String,
passwordHash: Int,
mailAddress : String
)
object User:
import Database.ctx.*