diff --git a/backend/src/main/scala/industries/sunshine/planningpoker/Auth.scala b/backend/src/main/scala/industries/sunshine/planningpoker/Auth.scala index d250e8e..47b6f57 100644 --- a/backend/src/main/scala/industries/sunshine/planningpoker/Auth.scala +++ b/backend/src/main/scala/industries/sunshine/planningpoker/Auth.scala @@ -10,6 +10,7 @@ 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[_]] { @@ -29,7 +30,7 @@ trait Auth[F[_]] { roomPassword: String, nickName: String, nickPassword: String - ): F[Either[Unit, ResponseCookie]] + ): F[Either[String, ResponseCookie]] def deleteSession( sessionId: Long @@ -70,16 +71,27 @@ object Auth { roomService: RoomService[F] ) extends Auth[F] { + val authcookie = "authcookie" + 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 () - ??? + ): F[Either[String, ResponseCookie]] = { + // TODO check for existing session for same room + // and do i want to logout if existing session for another room? ugh + val roomId = RoomID(roomName) + val result = for { + playerId <- EitherT( + roomService.joinRoom(roomId, nickName, nickPassword, roomPassword) + ) + .leftMap(_.toString()) + newSessionId = Random.nextLong() + _ <- EitherT.liftF(sessions.update(_.updated(newSessionId, (roomId, playerId)))) + } yield ResponseCookie(name = authcookie, content = newSessionId.toString(), secure = true) + + result.value } override def authUser diff --git a/backend/src/main/scala/industries/sunshine/planningpoker/RoomService.scala b/backend/src/main/scala/industries/sunshine/planningpoker/RoomService.scala index 1da27c9..f1da656 100644 --- a/backend/src/main/scala/industries/sunshine/planningpoker/RoomService.scala +++ b/backend/src/main/scala/industries/sunshine/planningpoker/RoomService.scala @@ -20,7 +20,7 @@ trait RoomService[F[_]] { nickName: String, nickPassword: String, roomPassword: String - ): F[Either[RoomError, Room]] + ): F[Either[RoomError, PlayerID]] def deleteRoom(roomID: RoomID): F[Unit] def getRoom(roomID: RoomID): F[Option[Room]] } @@ -49,8 +49,29 @@ class InMemoryRoomService[F[_]: Sync](stateRef: Ref[F, Map[RoomID, Room]]) exten nickName: String, nickPassword: String, roomPassword: String - ): F[Either[RoomError, Room]] = stateRef.modify[Either[RoomError, Room]] { rooms => - val joinedRoom = for { + ): F[Either[RoomError, PlayerID]] = stateRef.modify { rooms => + // need to cover cases: + // - player already present, then return as is, i guess + // - nick not known - add new player and new nick-password mapping + // - nick known - add new player + + def addPlayer(room: Room): (PlayerID, Room) = { + room.players.find(_.name == nickName) match { + case Some(player) => player.id -> room + case None => // player is not present, but potentially was previously + val addingPlayer = Player.create(nickPassword) + val roomWithPlayer = room.copy(players = addingPlayer :: room.players) + room.playersPasswords.get(nickName) match { + case Some(_) => addingPlayer.id -> roomWithPlayer + case None => + addingPlayer.id -> roomWithPlayer.copy(playersPasswords = + roomWithPlayer.playersPasswords.updated(nickName, nickPassword) + ) + } + } + } + + val joiningWithChecks = for { room <- rooms.get(id).toRight(RoomError.RoomMissing(id.name)) _ <- Either.cond(room.password == roomPassword, (), RoomError.RoomPassIncorrect) isNickPassCorrect = room.playersPasswords @@ -61,10 +82,10 @@ class InMemoryRoomService[F[_]: Sync](stateRef: Ref[F, Map[RoomID, Room]]) exten (), RoomError.NickPassIncorrect ) - updatedRoom = room - } yield updatedRoom + (playerId, updatedRoom) = addPlayer(room) + } yield playerId - rooms -> joinedRoom + rooms -> joiningWithChecks } } diff --git a/common/src/main/scala/industries/sunshine/planningpoker/Models.scala b/common/src/main/scala/industries/sunshine/planningpoker/Models.scala index fc87f7a..ebab018 100644 --- a/common/src/main/scala/industries/sunshine/planningpoker/Models.scala +++ b/common/src/main/scala/industries/sunshine/planningpoker/Models.scala @@ -2,6 +2,7 @@ package industries.sunshine.planningpoker.common import java.util.UUID import io.circe._ +import scala.util.Random object Models { @@ -53,6 +54,9 @@ object Models { final case class PlayerID(id: Long) derives Codec.AsObject final case class Player(name: String, id: PlayerID) derives Codec.AsObject + object Player { + def create(name: String) = Player(name, PlayerID(Random.nextLong)) + } final case class RoomID(name: String) derives Codec.AsObject