85 lines
3.4 KiB
Scala
85 lines
3.4 KiB
Scala
package industries.sunshine.planningpoker
|
|
|
|
import cats.effect._
|
|
import cats.syntax.all._
|
|
import org.http4s._, org.http4s.dsl.io._, org.http4s.implicits._
|
|
import org.http4s.websocket.WebSocketFrame
|
|
import io.circe.syntax._
|
|
import org.http4s.circe.CirceEntityDecoder._
|
|
import scala.concurrent.duration._
|
|
import org.http4s.server.websocket.WebSocketBuilder
|
|
import fs2._
|
|
import industries.sunshine.planningpoker.common.Models.RoomID
|
|
import industries.sunshine.planningpoker.common.Models.PlayerID
|
|
import org.http4s.server.AuthMiddleware.apply
|
|
import org.http4s.server.AuthMiddleware
|
|
|
|
object MyHttpService {
|
|
def create(auth: Auth[IO], roomService: RoomService[IO])(
|
|
wsb: WebSocketBuilder[IO]
|
|
): HttpApp[cats.effect.IO] = {
|
|
|
|
val authedRoomRoutes: AuthedRoutes[(PlayerID, RoomID), IO] =
|
|
AuthedRoutes.of {
|
|
case GET -> Root / "subscribe" as (playerId, roomId) => {
|
|
val send: Stream[IO, WebSocketFrame] =
|
|
roomService
|
|
.subscribe(roomId)
|
|
.map(state => WebSocketFrame.Text(state.getViewFor(playerId).asJson.noSpaces))
|
|
|
|
val receive: Pipe[IO, WebSocketFrame, Unit] = _.evalMap {
|
|
case WebSocketFrame.Text(text, _) => Sync[IO].delay(println(text))
|
|
case other => Sync[IO].delay(println(other))
|
|
}
|
|
IO(println(s"got ws request from $playerId in $roomId")) >>
|
|
wsb.build(send, receive)
|
|
}
|
|
case GET -> Root / "vote" / vote as (playerId, roomId) => {
|
|
IO(println(s">> got $vote from $playerId in $roomId")) >>
|
|
roomService.acceptVote(roomId, playerId, vote) >> Ok()
|
|
}
|
|
case GET -> Root / "end-voting" as (playerId, roomId) => {
|
|
IO(println(s">> got request to end voting from $playerId in $roomId")) >>
|
|
roomService.endVoting(roomId, playerId) >> Ok()
|
|
}
|
|
case GET -> Root / "new-poll" as (playerId, roomId) => {
|
|
IO(println(s">> got request to start new voting from $playerId in $roomId")) >>
|
|
roomService.startNewPoll(roomId, playerId) >> Ok()
|
|
}
|
|
case GET -> Root / "logout" as (playerId, roomId) => {
|
|
for {
|
|
_ <- IO(println(s">> got request to logout from $playerId in $roomId"))
|
|
_ <- roomService.leaveRoom(roomId, playerId)
|
|
cookie = ResponseCookie(name = Auth.authcookieName, content = "").clearCookie
|
|
} yield (Response(Status.Ok).addCookie(cookie))
|
|
}
|
|
}
|
|
|
|
val authMiddleware = AuthMiddleware(auth.authUser)
|
|
val aa = authMiddleware(authedRoomRoutes)
|
|
|
|
import cats.data.EitherT
|
|
val authenticationRoute = HttpRoutes
|
|
.of[IO] {
|
|
case req @ POST -> Root / "login" => {
|
|
val responseOrError = for {
|
|
data <- EitherT.right(req.as[Requests.LogIn])
|
|
Requests.LogIn(roomName, nickName, roomPassword, nickPassword) = data
|
|
roomId = RoomID(roomName)
|
|
playerId <- EitherT(roomService.joinRoom(roomId, nickName, nickPassword, roomPassword))
|
|
authCookie <- EitherT.liftF(auth.joinRoom(roomId, playerId))
|
|
_ <- EitherT.liftF(IO(println(s"> logging in $nickName to $roomName")))
|
|
resp <- EitherT.liftF(Ok().flatTap(resp => IO(resp.addCookie(authCookie))))
|
|
} yield resp
|
|
|
|
val response = responseOrError.leftSemiflatMap(error => Forbidden(error.toString())).merge
|
|
|
|
response
|
|
}
|
|
}
|
|
|
|
(authenticationRoute <+> authMiddleware(authedRoomRoutes)).orNotFound
|
|
}
|
|
|
|
}
|