Implemented login

This commit is contained in:
2026-07-09 18:21:23 +03:00
parent e06c53a9ff
commit 5aa6e30c90
7 changed files with 135 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
package dao
import jakarta.inject.Inject
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.jdbc.PostgresProfile
import slick.jdbc.PostgresProfile.api._
import java.nio.ByteBuffer
import java.security.SecureRandom
import java.util.Base64
import java.time.{Instant, Duration}
import scala.concurrent.{ExecutionContext, Future}
import models.AuthToken
import schemas.AuthTokens
class AuthTokensDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit val ec: ExecutionContext) extends HasDatabaseConfigProvider[PostgresProfile] {
private lazy val random = SecureRandom()
private lazy val base64 = Base64.getEncoder
private final lazy val tokenValidDuration = Duration.ofDays(30)
def createToken(user: models.User): Future[AuthToken] = {
val tokenRaw = ByteBuffer.allocate(10)
random.nextBytes(tokenRaw.array())
val token = AuthToken(
id = None,
userId = user.id.get,
token = base64.encodeToString(tokenRaw.array()),
createdAt = Instant.now,
expiresAt = Instant.now.plus(tokenValidDuration)
)
db.run((AuthTokens returning AuthTokens.map(_.id)) += token).map { tokenId => token.copy(id = Some(tokenId)) }
}
}
+31
View File
@@ -0,0 +1,31 @@
package dao
import de.mkammerer.argon2.Argon2Factory
import execution.CryptoExecutionContext
import jakarta.inject.Inject
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.jdbc.PostgresProfile
import slick.jdbc.PostgresProfile.api.*
import scala.concurrent.{ExecutionContext, Future}
import models.User
import schemas.Users
class UsersDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider, private val cryptoEC: CryptoExecutionContext)(implicit val ec: ExecutionContext)
extends HasDatabaseConfigProvider[PostgresProfile] {
private val argon2 = Argon2Factory.create()
def authenticate(username: String, password: String): Future[Option[User]] = {
val query = Users.filter(_.username === username).take(1).result.headOption
val userFuture = db.run(query)
userFuture.map { userOption =>
for {
user <- userOption
digest <- user.passwordDigest
if argon2.verify(digest, password.getBytes("UTF-8"))
} yield user
}(using cryptoEC)
}
}