feat!: implemented multigame support (#34)
Reviewed-on: #34 Co-authored-by: Janis <janis.e.20@gmx.de> Co-committed-by: Janis <janis.e.20@gmx.de>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package logic.user.impl
|
||||
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import com.auth0.jwt.{JWT, JWTVerifier}
|
||||
import com.github.benmanes.caffeine.cache.{Cache, Caffeine}
|
||||
import com.typesafe.config.Config
|
||||
import logic.user.SessionManager
|
||||
import model.users.User
|
||||
import scalafx.util.Duration
|
||||
import services.JwtKeyProvider
|
||||
|
||||
import java.time.Instant
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.{Inject, Singleton}
|
||||
|
||||
@Singleton
|
||||
class BaseSessionManager @Inject()(val keyProvider: JwtKeyProvider, val userManager: StubUserManager, val config: Config) extends SessionManager {
|
||||
|
||||
private val algorithm = Algorithm.RSA512(keyProvider.publicKey, keyProvider.privateKey)
|
||||
private val verifier: JWTVerifier = JWT.require(algorithm)
|
||||
.withIssuer(config.getString("auth.issuer"))
|
||||
.withAudience(config.getString("auth.audience"))
|
||||
.build()
|
||||
|
||||
//TODO reduce cache to a minimum amount, as JWT should be self-contained
|
||||
private val cache: Cache[String, User] = Caffeine.newBuilder()
|
||||
.maximumSize(10_000)
|
||||
.expireAfterWrite(5, TimeUnit.MINUTES).build()
|
||||
|
||||
override def createSession(user: User): String = {
|
||||
//Write session identifier to cache and DB
|
||||
val sessionId = JWT.create()
|
||||
.withIssuer(config.getString("auth.issuer"))
|
||||
.withAudience(config.getString("auth.audience"))
|
||||
.withSubject(user.id.toString)
|
||||
.withClaim("id", user.internalId)
|
||||
.withExpiresAt(Instant.now.plus(7, ChronoUnit.DAYS))
|
||||
.sign(algorithm)
|
||||
//TODO write to Redis and DB
|
||||
cache.put(sessionId, user)
|
||||
|
||||
sessionId
|
||||
}
|
||||
|
||||
override def getUserBySession(sessionId: String): Option[User] = {
|
||||
//TODO verify JWT token instead of looking up in cache
|
||||
val cachedUser = cache.getIfPresent(sessionId)
|
||||
if (cachedUser != null) {
|
||||
Some(cachedUser)
|
||||
} else {
|
||||
val decoded = verifier.verify(sessionId)
|
||||
val user = userManager.userExistsById(decoded.getClaim("id").asLong())
|
||||
user.foreach(u => cache.put(sessionId, u))
|
||||
user
|
||||
}
|
||||
}
|
||||
|
||||
override def invalidateSession(sessionId: String): Unit = {
|
||||
//TODO remove from Redis and DB
|
||||
cache.invalidate(sessionId)
|
||||
}
|
||||
}
|
||||
51
knockoutwhistweb/app/logic/user/impl/StubUserManager.scala
Normal file
51
knockoutwhistweb/app/logic/user/impl/StubUserManager.scala
Normal file
@@ -0,0 +1,51 @@
|
||||
package logic.user.impl
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import logic.user.UserManager
|
||||
import model.users.User
|
||||
import util.UserHash
|
||||
|
||||
import javax.inject.{Inject, Singleton}
|
||||
|
||||
@Singleton
|
||||
class StubUserManager @Inject()(val config: Config) extends UserManager {
|
||||
|
||||
private val user: Map[String, User] = Map(
|
||||
"Janis" -> User(
|
||||
internalId = 1L,
|
||||
id = java.util.UUID.fromString("123e4567-e89b-12d3-a456-426614174000"),
|
||||
name = "Janis",
|
||||
passwordHash = UserHash.hashPW("password123")
|
||||
),
|
||||
"Leon" -> User(
|
||||
internalId = 2L,
|
||||
id = java.util.UUID.fromString("223e4567-e89b-12d3-a456-426614174000"),
|
||||
name = "Leon",
|
||||
passwordHash = UserHash.hashPW("password123")
|
||||
)
|
||||
)
|
||||
|
||||
override def addUser(name: String, password: String): Boolean = {
|
||||
throw new NotImplementedError("StubUserManager.addUser is not implemented")
|
||||
}
|
||||
|
||||
override def authenticate(name: String, password: String): Option[User] = {
|
||||
user.get(name) match {
|
||||
case Some(u) if UserHash.verifyUser(password, u) => Some(u)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
override def userExists(name: String): Option[User] = {
|
||||
user.get(name)
|
||||
}
|
||||
|
||||
override def userExistsById(id: Long): Option[User] = {
|
||||
user.values.find(_.internalId == id)
|
||||
}
|
||||
|
||||
override def removeUser(name: String): Boolean = {
|
||||
throw new NotImplementedError("StubUserManager.removeUser is not implemented")
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user