package controllers.authentication import dao.{AuthTokensDAO, UsersDAO} import jakarta.inject.{Inject, Singleton} import models.AuthToken import play.api.libs.json.* import play.api.libs.functional.syntax.* import play.api.mvc.{AbstractController, ControllerComponents} import scala.concurrent.{ExecutionContext, Future} object SessionsController { case class LoginData(username: String, password: String) given Reads[LoginData] = Json.reads[LoginData] } @Singleton class SessionsController @Inject()( controllerComponents: ControllerComponents, usersDAO: UsersDAO, authTokensDAO: AuthTokensDAO, authenticatedAction: AuthenticatedAction) (implicit val ec: ExecutionContext) extends AbstractController(controllerComponents) { import SessionsController.{LoginData, given} def login() = Action.async(parse.json) { implicit request => val loginDataResult = request.body.validate[LoginData] loginDataResult.fold( errors => Future.successful(BadRequest(JsError.toJson(errors))), loginData => { usersDAO.authenticate(loginData.username, loginData.password).flatMap { userOption => userOption.fold( Future.successful(UnprocessableEntity(Json.obj("message" -> "Invalid authentication"))) ){ user => authTokensDAO.createToken(user).map { token => val json = Json.toJsObject(token) ++ Json.obj( "userId" -> user.id.get, "userGid" -> user.gid ) Ok(json) } } } } ) } def logout = authenticatedAction.async { request => authTokensDAO.destroy(request.token).map{ _ => Ok("") } } }