aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/byspel/Service.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/byspel/Service.scala')
-rw-r--r--src/main/scala/byspel/Service.scala69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/main/scala/byspel/Service.scala b/src/main/scala/byspel/Service.scala
new file mode 100644
index 0000000..1d1e841
--- /dev/null
+++ b/src/main/scala/byspel/Service.scala
@@ -0,0 +1,69 @@
+package byspel
+
+import app.DatabaseApi
+import java.sql.Timestamp
+import java.time.Instant
+import java.util.UUID
+import scala.concurrent.{ExecutionContext, Future}
+import scala.concurrent.duration._
+
+trait Service { self: DatabaseApi =>
+ import profile.api._
+
+ implicit def executionContext: ExecutionContext
+
+ def login(id: String,
+ password: String): Future[Option[(UsersRow, SessionsRow)]] = {
+ val query = for {
+ user <- Users
+ if user.primaryEmail === id || user.id === id
+ shadow <- Shadow
+ if shadow.userId === user.id
+ } yield {
+ user -> shadow.hash
+ }
+ val userResult = database.run(query.result.headOption).map {
+ case Some((user, hash)) if PasswordHash.verify(password, hash) =>
+ Some(user)
+ case _ =>
+ // dummy password hash to avoid timing attacks
+ PasswordHash.verify(
+ password,
+ "$argon2i$v=19$m=65536,t=10,p=1$gFZ4l8R2rpuhfqXDFuugNg$fOvTwLSaOMahD/5AfWlbRsSMj4E6k34VpGyl5xe24yA")
+ None
+ }
+
+ userResult.flatMap {
+ case Some(u) =>
+ val newSession = SessionsRow(
+ UUID.randomUUID().toString,
+ u.id,
+ Timestamp.from(Instant.now.plusSeconds(60 * 60 * 24))
+ )
+ database
+ .run(
+ Sessions += newSession
+ )
+ .map(_ => Some(u -> newSession))
+ case None => Future.successful(None)
+ }
+ }
+
+ def checkSession(sessionId: String): Future[Option[UsersRow]] = database.run {
+ val query = for {
+ session <- Sessions
+ if session.sessionId === sessionId
+ if session.expires > Timestamp.from(Instant.now())
+ user <- Users
+ if user.id === session.userId
+ } yield {
+ user
+ }
+ query.result.headOption
+ }
+
+ def endSession(sessionId: String) = database.run {
+ Sessions.filter(_.sessionId === sessionId).delete
+ }
+
+}