Better handle database login errors (#321)

* logging errors for database login ops

* clarified types of messages to expect

* TeardownConnection handled
This commit is contained in:
Fate-JH 2020-01-10 19:40:15 -05:00 committed by pschord
parent d08911d07c
commit 58b45a85a9

View file

@ -46,7 +46,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
var canonicalHostName : String = "" var canonicalHostName : String = ""
var port : Int = 0 var port : Int = 0
val serverName = WorldConfig.Get[String]("worldserver.ServerName"); val serverName = WorldConfig.Get[String]("worldserver.ServerName")
// This MUST be an IP address. The client DOES NOT do name resolution // This MUST be an IP address. The client DOES NOT do name resolution
var serverHost : String = if (WorldConfig.Get[String]("worldserver.Hostname") != "") var serverHost : String = if (WorldConfig.Get[String]("worldserver.Hostname") != "")
@ -110,6 +110,9 @@ class LoginSessionActor extends Actor with MDCContextAware {
val serverTick = Math.abs(System.nanoTime().toInt) // limit the size to prevent encoding error val serverTick = Math.abs(System.nanoTime().toInt) // limit the size to prevent encoding error
sendResponse(PacketCoding.CreateControlPacket(ControlSyncResp(diff, serverTick, fa, fb, fb, fa))) sendResponse(PacketCoding.CreateControlPacket(ControlSyncResp(diff, serverTick, fa, fb, fb, fa)))
case TeardownConnection(_) =>
sendResponse(DropSession(sessionId, "client requested session termination"))
case default => case default =>
log.error(s"Unhandled ControlPacket $default") log.error(s"Unhandled ControlPacket $default")
} }
@ -142,7 +145,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
log.debug(s"Unhandled GamePacket $pkt") log.debug(s"Unhandled GamePacket $pkt")
} }
def startAccountLogin(username: String, password: String) = { def startAccountLogin(username: String, password: String) : Unit = {
val newToken = this.generateToken() val newToken = this.generateToken()
Database.getConnection.connect.onComplete { Database.getConnection.connect.onComplete {
case Success(connection) => case Success(connection) =>
@ -165,7 +168,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
} }
} }
def startAccountAuthentication() : Receive = { def startAccountAuthentication : Receive = {
case StartAccountAuthentication(connection, username, password, newToken, queryResult) => case StartAccountAuthentication(connection, username, password, newToken, queryResult) =>
queryResult match { queryResult match {
@ -202,10 +205,11 @@ class LoginSessionActor extends Actor with MDCContextAware {
self ! FinishAccountLogin(connection, username, newToken, false) self ! FinishAccountLogin(connection, username, newToken, false)
} }
} }
case default => failWithError(s"Invalid message '$default' received in startAccountAuthentication") case default =>
failWithError(s"Invalid message '$default' received in startAccountAuthentication")
} }
def createNewAccount() : Receive = { def createNewAccount : Receive = {
case CreateNewAccount(connection, username, password, newToken) => case CreateNewAccount(connection, username, password, newToken) =>
log.info(s"Account $username does not exist, creating new account...") log.info(s"Account $username does not exist, creating new account...")
val bcryptPassword : String = password.bcrypt(numBcryptPasses) val bcryptPassword : String = password.bcrypt(numBcryptPasses)
@ -230,18 +234,30 @@ class LoginSessionActor extends Actor with MDCContextAware {
context.become(finishAccountLogin) context.become(finishAccountLogin)
self ! FinishAccountLogin(connection, username, newToken, false) self ! FinishAccountLogin(connection, username, newToken, false)
} }
case _ => case default =>
log.error(s"Error creating new account for $username") log.error(s"Error creating new account for $username - $default")
context.become(finishAccountLogin) context.become(finishAccountLogin)
self ! FinishAccountLogin(connection, username, newToken, false) self ! FinishAccountLogin(connection, username, newToken, false)
} }
case _ => failWithError("Something to do ?") case Failure(e : com.github.mauricio.async.db.postgresql.exceptions.GenericDatabaseException) =>
log.error(s"Error creating new account - ${e.errorMessage.message}")
context.become(finishAccountLogin)
self ! FinishAccountLogin(connection, username, newToken, false)
case Failure(e : java.sql.SQLException) =>
log.error(s"Error creating new account - ${e.getMessage}")
context.become(finishAccountLogin)
self ! FinishAccountLogin(connection, username, newToken, false)
case _ =>
failWithError(s"Something to do?")
} }
case default => failWithError(s"Invalid message '$default' received in createNewAccount") case default =>
failWithError(s"Invalid message '$default' received in createNewAccount")
} }
// Essentially keeps a record of this individual login occurrence // Essentially keeps a record of this individual login occurrence
def logTheLoginOccurrence() : Receive = { def logTheLoginOccurrence : Receive = {
case LogTheLoginOccurrence(connection, username, newToken, isSuccessfulLogin, accountId) => case LogTheLoginOccurrence(connection, username, newToken, isSuccessfulLogin, accountId) =>
connection.get.inTransaction { connection.get.inTransaction {
c => c.sendPreparedStatement( c => c.sendPreparedStatement(
@ -249,14 +265,14 @@ class LoginSessionActor extends Actor with MDCContextAware {
Array(accountId, new java.sql.Timestamp(System.currentTimeMillis), ipAddress, canonicalHostName, hostName, port) Array(accountId, new java.sql.Timestamp(System.currentTimeMillis), ipAddress, canonicalHostName, hostName, port)
) )
}.onComplete { }.onComplete {
case _ => _ =>
context.become(finishAccountLogin) context.become(finishAccountLogin)
self ! FinishAccountLogin(connection, username, newToken, isSuccessfulLogin) self ! FinishAccountLogin(connection, username, newToken, isSuccessfulLogin)
} }
case default => failWithError(s"Invalid message '$default' received in logTheLoginOccurrence") case default => failWithError(s"Invalid message '$default' received in logTheLoginOccurrence")
} }
def finishAccountLogin() : Receive = { def finishAccountLogin : Receive = {
case FinishAccountLogin(connection, username, newToken, isSuccessfulLogin, isInactive) => case FinishAccountLogin(connection, username, newToken, isSuccessfulLogin, isInactive) =>
if(isSuccessfulLogin) { // Login OK if(isSuccessfulLogin) { // Login OK
loginSuccessfulResponse(username, newToken) loginSuccessfulResponse(username, newToken)
@ -336,7 +352,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
def generateToken() = { def generateToken() = {
val r = new scala.util.Random val r = new scala.util.Random
val sb = new StringBuilder val sb = new StringBuilder
for (i <- 1 to 31) { for (_ <- 1 to 31) {
sb.append(r.nextPrintableChar) sb.append(r.nextPrintableChar)
} }
sb.toString sb.toString