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 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( roomName: String, roomPassword: String, nickName: String, nickPassword: String ): F[Either[Unit, ResponseCookie]] def deleteSession( sessionId: Long ): F[Unit] } object Auth { def pureBadStub = new Auth[IO] { override def authUser = Kleisli((req: Request[IO]) => OptionT.liftF( IO(println(s"authUser: $req")) >> IO( PlayerID(14) -> RoomID("testroom") ) ) ) override def joinRoom( roomName: String, roomPassword: String, nickName: String, nickPassword: String ) = IO( println( s"> access room for $roomName $roomPassword $nickName, to return stub 111" ) ) >> IO.pure(Right(ResponseCookie("authcookie", "1"))) override def deleteSession(sessionId: Long): IO[Unit] = IO(s"got request to leave for $sessionId") } type SessionsMap = Map[Long, (RoomID, PlayerID)] class SimpleAuth[F[_]: Sync]( sessions: Ref[F, SessionsMap], roomService: RoomService[F] ) extends Auth[F] { override def joinRoom( roomName: String, roomPassword: String, nickName: String, nickPassword: String ): F[Either[Unit, ResponseCookie]] = { for { joinedRoom <- roomService.joinRoom(RoomID(roomName), nickName, nickPassword, roomPassword) } yield () ??? } override def authUser : Kleisli[[A] =>> cats.data.OptionT[F, A], Request[F], (PlayerID, RoomID)] = { // check authcookie presence, exchange it for playerID ad roomID ??? } override def deleteSession(sessionId: Long): F[Unit] = { // i suppose leaving the room should just be authed route & method ??? } } def make[F[_]: Sync](roomsService: RoomService[F]): F[Auth[F]] = for { sessionsMap <- Ref.of[F, SessionsMap]( Map(1L -> (RoomID("testroom"), PlayerID(1L))) ) } yield new SimpleAuth(sessionsMap, roomsService) }