without it app starts in same jvm and we're told that Ctrl+C will not always kill the Ember server: https://typelevel.org/cats-effect/docs/2.x/datatypes/ioapp WARNING: If you run your IOApp program from sbt, you may observe cancellation and resource releasing is not happening. This is due to sbt, by default, running programs in the same JVM as sbt, so when your program is canceled sbt avoids stopping its own JVM. To properly allow cancellation, ensure your progam is forked into its own JVM via a setting like fork := true in your sbt configuration.
81 lines
2.8 KiB
Scala
81 lines
2.8 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.generic.auto._
|
|
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)(
|
|
wsb: WebSocketBuilder[cats.effect.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] =
|
|
Stream
|
|
.emits(TestModels.testChangesList)
|
|
.covary[IO].metered(1.second).map(state => WebSocketFrame.Text(state.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))
|
|
}
|
|
wsb.build(send, receive)
|
|
}
|
|
case GET -> Root / "vote" / vote as (playerId, roomId) => {
|
|
// TODO forward these to the service implementation
|
|
IO(println(s">> got $vote from $playerId in $roomId")) >> Ok()
|
|
}
|
|
case GET -> Root / "end-voting" as (playerId, roomId) => {
|
|
IO(println(s">> got request to end voting from $playerId in $roomId")) >> Ok()
|
|
}
|
|
case GET -> Root / "new-poll" as (playerId, roomId) => {
|
|
IO(println(s">> got request to start new voting from $playerId in $roomId")) >> Ok()
|
|
}
|
|
}
|
|
|
|
val authMiddleware = AuthMiddleware(auth.authUser)
|
|
val aa = authMiddleware(authedRoomRoutes)
|
|
|
|
val authenticationRoute = HttpRoutes
|
|
.of[IO] {
|
|
case req @ POST -> Root / "login" => {
|
|
for {
|
|
data <- req.as[Requests.LogIn]
|
|
authResult <- auth.accessRoom(
|
|
data.roomName,
|
|
data.password,
|
|
data.nickname
|
|
)
|
|
resp <- authResult match {
|
|
case Left(error) =>
|
|
Forbidden(error)
|
|
case Right(sessionId) => {
|
|
Ok("Logged in!").map(
|
|
_.addCookie(
|
|
ResponseCookie("authcookie", sessionId.toString())
|
|
)
|
|
)
|
|
}
|
|
}
|
|
} yield resp
|
|
}
|
|
}
|
|
|
|
(authenticationRoute <+> authMiddleware(authedRoomRoutes)).orNotFound
|
|
}
|
|
|
|
}
|