planning-poker-gwargh/backend/src/main/scala/industries/sunshine/planningpoker/Auth.scala

89 lines
2.7 KiB
Scala

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)
}