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.{Duration, Instant} import scala.concurrent.{ExecutionContext, Future} import models.AuthToken import schemas.AuthTokens import utils.Random import scala.language.postfixOps class AuthTokensDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit val ec: ExecutionContext) extends HasDatabaseConfigProvider[PostgresProfile] { private final lazy val tokenValidDuration = Duration.ofDays(30) def find(token: String): Future[Option[AuthToken]] = { val query = AuthTokens.filter(row => row.token === token && row.expiresAt > Instant.now()).take(1).result.headOption db.run(query) } def createToken(user: models.User): Future[AuthToken] = { val token = AuthToken( id = None, userId = user.id.get, token = Random.randomBase64(12), createdAt = Instant.now, expiresAt = Instant.now.plus(tokenValidDuration) ) db.run((AuthTokens returning AuthTokens.map(_.id)) += token).map { tokenId => token.copy(id = Some(tokenId)) } } def getUser(token: AuthToken): Future[Option[models.User]] = { val query = schemas.Users.filter(_.id === token.userId).take(1).result.headOption db.run(query) } def destroy(token: AuthToken): Future[Unit] = { val q = AuthTokens.filter(_.token === token.token).delete db.run(q).map{ _ => () } } }