diff --git a/README.md b/README.md new file mode 100644 index 0000000..6cc01af --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ + + + + + + +## User Password Protection + +All the User Passwords are encrypted using Argon2. \ No newline at end of file diff --git a/build.sbt b/build.sbt index 535154e..490def8 100644 --- a/build.sbt +++ b/build.sbt @@ -37,7 +37,8 @@ lazy val knockoutwhistweb = project.in(file("knockoutwhistweb")) .dependsOn(knockoutwhist % "compile->compile;test->test") .settings( commonSettings, - libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "7.0.2" % Test + libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "7.0.2" % Test, + libraryDependencies += "de.mkammerer" % "argon2-jvm" % "2.12" ) lazy val root = (project in file(".")) diff --git a/knockoutwhistweb/app/controllers/HomeController.scala b/knockoutwhistweb/app/controllers/HomeController.scala index 7de648f..4db8838 100644 --- a/knockoutwhistweb/app/controllers/HomeController.scala +++ b/knockoutwhistweb/app/controllers/HomeController.scala @@ -7,6 +7,8 @@ import de.knockoutwhist.components.Configuration import de.knockoutwhist.control.GameState.{InGame, Lobby, SelectTrump, TieBreak} import de.knockoutwhist.control.controllerBaseImpl.BaseGameLogic import di.KnockOutWebConfigurationModule +import logic.PodGameManager +import model.sessions.AdvancedSession import play.api.mvc.* import play.api.* import play.twirl.api.Html @@ -81,13 +83,5 @@ class HomeController @Inject()(val controllerComponents: ControllerComponents) e Action { implicit request => InternalServerError("Oops") } - //if (logic.getCurrentState == Lobby) { - //Action { implicit request => - //Ok(views.html.tui.apply(player, logic)) - //} - //} else { - //Action { implicit request => - //Ok(views.html.tui.apply(player, logic)) - //} } } \ No newline at end of file diff --git a/knockoutwhistweb/app/controllers/WebUI.scala b/knockoutwhistweb/app/controllers/WebUI.scala index 726a1c4..4015d64 100644 --- a/knockoutwhistweb/app/controllers/WebUI.scala +++ b/knockoutwhistweb/app/controllers/WebUI.scala @@ -1,6 +1,5 @@ package controllers -import controllers.sessions.AdvancedSession import de.knockoutwhist.cards.{Card, CardValue, Hand, Suit} import de.knockoutwhist.control.GameLogic import de.knockoutwhist.control.GameState.{InGame, Lobby} @@ -12,6 +11,8 @@ import de.knockoutwhist.rounds.Match import de.knockoutwhist.ui.UI import de.knockoutwhist.utils.CustomThread import de.knockoutwhist.utils.events.{EventListener, SimpleEvent} +import logic.PodGameManager +import model.sessions.AdvancedSession object WebUI extends CustomThread with EventListener with UI { diff --git a/knockoutwhistweb/app/controllers/PodGameManager.scala b/knockoutwhistweb/app/logic/PodGameManager.scala similarity index 92% rename from knockoutwhistweb/app/controllers/PodGameManager.scala rename to knockoutwhistweb/app/logic/PodGameManager.scala index fc9da31..891e046 100644 --- a/knockoutwhistweb/app/controllers/PodGameManager.scala +++ b/knockoutwhistweb/app/logic/PodGameManager.scala @@ -1,7 +1,7 @@ -package controllers +package logic -import controllers.sessions.PlayerSession import de.knockoutwhist.utils.events.SimpleEvent +import model.sessions.PlayerSession import java.util.UUID import scala.collection.mutable diff --git a/knockoutwhistweb/app/logic/user/SessionManager.scala b/knockoutwhistweb/app/logic/user/SessionManager.scala new file mode 100644 index 0000000..c573b23 --- /dev/null +++ b/knockoutwhistweb/app/logic/user/SessionManager.scala @@ -0,0 +1,11 @@ +package logic.user + +import model.users.User + +trait SessionManager { + + def createSession(user: User): String + def getUserBySession(sessionId: String): Option[User] + def invalidateSession(sessionId: String): Unit + +} diff --git a/knockoutwhistweb/app/logic/user/UserManager.scala b/knockoutwhistweb/app/logic/user/UserManager.scala new file mode 100644 index 0000000..69e4481 --- /dev/null +++ b/knockoutwhistweb/app/logic/user/UserManager.scala @@ -0,0 +1,10 @@ +package logic.user + +trait UserManager { + + def addUser(name: String, password: String): Boolean + def authenticate(name: String, password: String): Boolean + def userExists(name: String): Boolean + def removeUser(name: String): Boolean + +} diff --git a/knockoutwhistweb/app/controllers/sessions/AdvancedSession.scala b/knockoutwhistweb/app/model/sessions/AdvancedSession.scala similarity index 91% rename from knockoutwhistweb/app/controllers/sessions/AdvancedSession.scala rename to knockoutwhistweb/app/model/sessions/AdvancedSession.scala index 770e3fb..7a2fe66 100644 --- a/knockoutwhistweb/app/controllers/sessions/AdvancedSession.scala +++ b/knockoutwhistweb/app/model/sessions/AdvancedSession.scala @@ -1,4 +1,4 @@ -package controllers.sessions +package model.sessions import de.knockoutwhist.player.AbstractPlayer import de.knockoutwhist.utils.events.SimpleEvent diff --git a/knockoutwhistweb/app/controllers/sessions/PlayerSession.scala b/knockoutwhistweb/app/model/sessions/PlayerSession.scala similarity index 86% rename from knockoutwhistweb/app/controllers/sessions/PlayerSession.scala rename to knockoutwhistweb/app/model/sessions/PlayerSession.scala index e76ddc2..95c39f5 100644 --- a/knockoutwhistweb/app/controllers/sessions/PlayerSession.scala +++ b/knockoutwhistweb/app/model/sessions/PlayerSession.scala @@ -1,4 +1,4 @@ -package controllers.sessions +package model.sessions import de.knockoutwhist.utils.events.SimpleEvent diff --git a/knockoutwhistweb/app/model/users/User.scala b/knockoutwhistweb/app/model/users/User.scala new file mode 100644 index 0000000..e56c048 --- /dev/null +++ b/knockoutwhistweb/app/model/users/User.scala @@ -0,0 +1,20 @@ +package model.users + +import java.util.UUID + +case class User( + internalId: Long, + id: UUID, + name: String, + passwordHash: String + ) { + + def withName(newName: String): User = { + this.copy(name = newName) + } + + private def withPasswordHash(newPasswordHash: String): User = { + this.copy(passwordHash = newPasswordHash) + } + +} diff --git a/knockoutwhistweb/app/util/UserHash.scala b/knockoutwhistweb/app/util/UserHash.scala new file mode 100644 index 0000000..1c48cab --- /dev/null +++ b/knockoutwhistweb/app/util/UserHash.scala @@ -0,0 +1,23 @@ +package util + +import de.mkammerer.argon2.Argon2Factory +import de.mkammerer.argon2.Argon2Factory.Argon2Types +import model.users.User + +object UserHash { + private val ITERATIONS: Int = 3 + private val MEMORY: Int = 32_768 + private val PARALLELISM: Int = 1 + private val SALT_LENGTH: Int = 32 + private val HASH_LENGTH: Int = 64 + private val ARGON_2 = Argon2Factory.create(Argon2Types.ARGON2id, SALT_LENGTH, HASH_LENGTH) + + def hashPW(password: String): String = { + ARGON_2.hash(ITERATIONS, MEMORY, PARALLELISM, password.toCharArray) + } + + def verifyUser(password: String, user: User): Boolean = { + ARGON_2.verify(user.passwordHash, password.toCharArray) + } + +} diff --git a/knockoutwhistweb/app/views/sessions.scala.html b/knockoutwhistweb/app/views/sessions.scala.html index bf4880f..1336e3c 100644 --- a/knockoutwhistweb/app/views/sessions.scala.html +++ b/knockoutwhistweb/app/views/sessions.scala.html @@ -1,4 +1,5 @@ -@(sessions: List[controllers.sessions.PlayerSession]) +@import model.sessions.PlayerSession +@(sessions: List[PlayerSession]) @main("Sessions") {