adding room service, joining room
adding nick password into model, stored in the Room to allow more secure joining for repeated times
This commit is contained in:
parent
2244f38348
commit
1b71c942ec
|
@ -1,7 +1,7 @@
|
||||||
package industries.sunshine.planningpoker
|
package industries.sunshine.planningpoker
|
||||||
|
|
||||||
import cats.effect._
|
import cats.effect._
|
||||||
import cats.syntax._
|
import cats.syntax.all._
|
||||||
import cats.data.Kleisli
|
import cats.data.Kleisli
|
||||||
import cats.data.OptionT
|
import cats.data.OptionT
|
||||||
import org.http4s.Request
|
import org.http4s.Request
|
||||||
|
@ -9,6 +9,7 @@ import industries.sunshine.planningpoker.common.Models.PlayerID
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import industries.sunshine.planningpoker.common.Models.{RoomID, Room}
|
import industries.sunshine.planningpoker.common.Models.{RoomID, Room}
|
||||||
import org.http4s.ResponseCookie
|
import org.http4s.ResponseCookie
|
||||||
|
import cats.data.EitherT
|
||||||
|
|
||||||
trait Auth[F[_]] {
|
trait Auth[F[_]] {
|
||||||
|
|
||||||
|
@ -26,7 +27,8 @@ trait Auth[F[_]] {
|
||||||
def joinRoom(
|
def joinRoom(
|
||||||
roomName: String,
|
roomName: String,
|
||||||
roomPassword: String,
|
roomPassword: String,
|
||||||
nickName: String
|
nickName: String,
|
||||||
|
nickPassword: String
|
||||||
): F[Either[Unit, ResponseCookie]]
|
): F[Either[Unit, ResponseCookie]]
|
||||||
|
|
||||||
def deleteSession(
|
def deleteSession(
|
||||||
|
@ -48,7 +50,8 @@ object Auth {
|
||||||
override def joinRoom(
|
override def joinRoom(
|
||||||
roomName: String,
|
roomName: String,
|
||||||
roomPassword: String,
|
roomPassword: String,
|
||||||
nickName: String
|
nickName: String,
|
||||||
|
nickPassword: String
|
||||||
) =
|
) =
|
||||||
IO(
|
IO(
|
||||||
println(
|
println(
|
||||||
|
@ -61,6 +64,7 @@ object Auth {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionsMap = Map[Long, (RoomID, PlayerID)]
|
type SessionsMap = Map[Long, (RoomID, PlayerID)]
|
||||||
|
|
||||||
class SimpleAuth[F[_]: Sync](
|
class SimpleAuth[F[_]: Sync](
|
||||||
sessions: Ref[F, SessionsMap],
|
sessions: Ref[F, SessionsMap],
|
||||||
roomService: RoomService[F]
|
roomService: RoomService[F]
|
||||||
|
@ -69,8 +73,12 @@ object Auth {
|
||||||
override def joinRoom(
|
override def joinRoom(
|
||||||
roomName: String,
|
roomName: String,
|
||||||
roomPassword: String,
|
roomPassword: String,
|
||||||
nickName: String
|
nickName: String,
|
||||||
|
nickPassword: String
|
||||||
): F[Either[Unit, ResponseCookie]] = {
|
): F[Either[Unit, ResponseCookie]] = {
|
||||||
|
for {
|
||||||
|
joinedRoom <- roomService.joinRoom(RoomID(roomName), nickName, nickPassword, roomPassword)
|
||||||
|
} yield ()
|
||||||
???
|
???
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +94,6 @@ object Auth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import cats.Monad.ops.toAllMonadOps
|
|
||||||
def make[F[_]: Sync](roomsService: RoomService[F]): F[Auth[F]] =
|
def make[F[_]: Sync](roomsService: RoomService[F]): F[Auth[F]] =
|
||||||
for {
|
for {
|
||||||
sessionsMap <- Ref.of[F, SessionsMap](
|
sessionsMap <- Ref.of[F, SessionsMap](
|
||||||
|
|
|
@ -59,8 +59,8 @@ object MyHttpService {
|
||||||
authResult <- auth.joinRoom(
|
authResult <- auth.joinRoom(
|
||||||
data.roomName,
|
data.roomName,
|
||||||
data.password,
|
data.password,
|
||||||
data.nickname
|
data.nickname,
|
||||||
)
|
data.nickPassword)
|
||||||
resp <- authResult match {
|
resp <- authResult match {
|
||||||
case Left(error) =>
|
case Left(error) =>
|
||||||
Forbidden(error)
|
Forbidden(error)
|
||||||
|
|
|
@ -3,14 +3,24 @@ package industries.sunshine.planningpoker
|
||||||
import industries.sunshine.planningpoker.common.Models.*
|
import industries.sunshine.planningpoker.common.Models.*
|
||||||
import cats.effect.{Ref, Sync}
|
import cats.effect.{Ref, Sync}
|
||||||
import cats.syntax.all._
|
import cats.syntax.all._
|
||||||
|
import cats.data.EitherT
|
||||||
|
|
||||||
enum RoomError {
|
enum RoomError {
|
||||||
case RoomAlreadyExists(name: String)
|
case RoomAlreadyExists(name: String)
|
||||||
|
case RoomMissing(name: String)
|
||||||
|
case RoomPassIncorrect
|
||||||
|
case NickPassIncorrect
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RoomService[F[_]] {
|
trait RoomService[F[_]] {
|
||||||
def createRoom(newRoom: Room): F[Either[RoomError, Room]]
|
def createRoom(newRoom: Room): F[Either[RoomError, Room]]
|
||||||
def updateRoom(room: Room): F[Unit]
|
def updateRoom(room: Room): F[Unit]
|
||||||
|
def joinRoom(
|
||||||
|
id: RoomID,
|
||||||
|
nickName: String,
|
||||||
|
nickPassword: String,
|
||||||
|
roomPassword: String
|
||||||
|
): F[Either[RoomError, Room]]
|
||||||
def deleteRoom(roomID: RoomID): F[Unit]
|
def deleteRoom(roomID: RoomID): F[Unit]
|
||||||
def getRoom(roomID: RoomID): F[Option[Room]]
|
def getRoom(roomID: RoomID): F[Option[Room]]
|
||||||
}
|
}
|
||||||
|
@ -26,13 +36,36 @@ class InMemoryRoomService[F[_]: Sync](stateRef: Ref[F, Map[RoomID, Room]]) exten
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def updateRoom(room: Room): F[Unit] = stateRef.update { state =>
|
override def updateRoom(room: Room): F[Unit] = stateRef.update { state =>
|
||||||
state.get(room.id).fold(state)(oldRoom => state.updated(room.id, room))
|
state.get(room.id).fold(state)(oldRoom => state.updated(room.id, room))
|
||||||
}
|
}
|
||||||
|
|
||||||
def deleteRoom(roomID: RoomID): F[Unit] = stateRef.update(_.removed(roomID))
|
override def deleteRoom(roomID: RoomID): F[Unit] = stateRef.update(_.removed(roomID))
|
||||||
|
|
||||||
def getRoom(roomID: RoomID): F[Option[Room]] = stateRef.get.map(_.get(roomID))
|
override def getRoom(roomID: RoomID): F[Option[Room]] = stateRef.get.map(_.get(roomID))
|
||||||
|
|
||||||
|
override def joinRoom(
|
||||||
|
id: RoomID,
|
||||||
|
nickName: String,
|
||||||
|
nickPassword: String,
|
||||||
|
roomPassword: String
|
||||||
|
): F[Either[RoomError, Room]] = stateRef.modify[Either[RoomError, Room]] { rooms =>
|
||||||
|
val joinedRoom = for {
|
||||||
|
room <- rooms.get(id).toRight(RoomError.RoomMissing(id.name))
|
||||||
|
_ <- Either.cond(room.password == roomPassword, (), RoomError.RoomPassIncorrect)
|
||||||
|
isNickPassCorrect = room.playersPasswords
|
||||||
|
.get(nickName)
|
||||||
|
.fold(true)(existingPass => existingPass == nickPassword)
|
||||||
|
_ <- Either.cond(
|
||||||
|
isNickPassCorrect,
|
||||||
|
(),
|
||||||
|
RoomError.NickPassIncorrect
|
||||||
|
)
|
||||||
|
updatedRoom = room
|
||||||
|
} yield updatedRoom
|
||||||
|
|
||||||
|
rooms -> joinedRoom
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
object RoomService {
|
object RoomService {
|
||||||
|
|
|
@ -62,7 +62,8 @@ object Models {
|
||||||
owner: PlayerID,
|
owner: PlayerID,
|
||||||
password: String,
|
password: String,
|
||||||
allowedCards: List[String],
|
allowedCards: List[String],
|
||||||
round: RoundState
|
round: RoundState,
|
||||||
|
playersPasswords: Map[String, String] = Map.empty // nickname into password
|
||||||
) {
|
) {
|
||||||
def toViewFor(playerId: PlayerID): RoomStateView = {
|
def toViewFor(playerId: PlayerID): RoomStateView = {
|
||||||
players
|
players
|
||||||
|
|
|
@ -4,6 +4,6 @@ import io.circe.generic.semiauto._
|
||||||
import io.circe._
|
import io.circe._
|
||||||
|
|
||||||
object Requests {
|
object Requests {
|
||||||
final case class LogIn(roomName: String, nickname: String, password: String)
|
final case class LogIn(roomName: String, nickname: String, password: String, nickPassword: String)
|
||||||
derives Codec.AsObject
|
derives Codec.AsObject
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue