package industries.sunshine.planningpoker import cats.effect._ import cats.syntax.all._ import cats.data.Kleisli import cats.data.OptionT import org.http4s.Request import industries.sunshine.planningpoker.common.Models.PlayerID import java.util.UUID import industries.sunshine.planningpoker.common.Models.{RoomID, Room} import org.http4s.ResponseCookie import cats.data.EitherT import scala.util.Random trait Auth[F[_]] { /** for middleware that converts sessionId into PlayerId */ def authUser: Kleisli[[A] =>> cats.data.OptionT[F, A], Request[F], (PlayerID, RoomID)] /** Get sessionId for accessing a room * @param roomPassword * \- requirement to get access to the room * * check that room exists, password is valid call to add user to the players create session * mapping and return cookie */ def joinRoom(roomId: RoomID, playerId: PlayerID): F[ResponseCookie] def deleteSession(sessionId: Long): F[ResponseCookie] } object Auth { type SessionsMap = Map[Long, (RoomID, PlayerID)] // TODO make "remove session usable from authed route" val authcookieName = "authcookie" class SimpleAuth[F[_]: Sync](sessions: Ref[F, SessionsMap]) extends Auth[F] { override def joinRoom(roomId: RoomID, playerId: PlayerID): F[ResponseCookie] = { // TODO check for existing session for same room // and do i want to logout if existing session for another room? ugh // newSessionId = Random.nextLong() // TODO return after i stop mocking RoomService val newSessionId = TestModels.testSessionId sessions .update(_.updated(newSessionId, (roomId, playerId))) .as( ResponseCookie( name = authcookieName, content = newSessionId.toString(), secure = true ) ) } override def authUser : Kleisli[[A] =>> cats.data.OptionT[F, A], Request[F], (PlayerID, RoomID)] = { Kleisli { (request: Request[F]) => OptionT(sessions.get.map { sessionsMap => for { authcookie <- request.cookies.find(_.name == authcookieName) sessionId <- authcookie.content.toLongOption (roomId, playerId) <- sessionsMap.get(sessionId) } yield (playerId, roomId) }) } } override def deleteSession(sessionId: Long): F[ResponseCookie] = { sessions .update(_.removed(sessionId)) .as( ResponseCookie( name = authcookieName, content = "", secure = true ).clearCookie ) } } def make[F[_]: Sync](): F[Auth[F]] = for { sessionsMap <- Ref.of[F, SessionsMap](TestModels.testSessions) } yield new SimpleAuth(sessionsMap) }