Advertisement
Guest User

Untitled

a guest
Oct 13th, 2017
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.78 KB | None | 0 0
  1. package ca.schwitzer.muddo.server.fsm
  2.  
  3. import java.net.InetSocketAddress
  4.  
  5. import akka.actor.{ActorRef, FSM, Props}
  6. import akka.io.Tcp
  7. import ca.schwitzer.muddo.db.daos.UserDAO
  8. import ca.schwitzer.muddo.mud.User
  9. import ca.schwitzer.muddo.server.connection.{ConnectionManager, Protocol, Protocols}
  10. import ca.schwitzer.muddo.server.fsm.LoginFSM._
  11. import ca.schwitzer.muddo.server.login.Authentication
  12.  
  13. import scala.concurrent.ExecutionContext
  14. import scala.util.{Failure, Success}
  15.  
  16. class LoginFSM(parent: ActorRef,
  17.                connection: ActorRef,
  18.                remote: InetSocketAddress)
  19.               (implicit userDAO: UserDAO,
  20.  
  21.                authenticator: Authentication,
  22.                ec: ExecutionContext) extends FSM[State, Data] {
  23.   def dbError(err: Throwable): Unit = {
  24.     log.error(s"Could not access DB. More info: ${err.getMessage}")
  25.     val msg = {
  26.       """Muddo could not access it's database! Sorry!! Please report this to an administrator!
  27.        |Terminating...""".stripMargin
  28.     }
  29.  
  30.     self ! Protocol.prepareResponse(msg)
  31.     Thread.sleep(500)
  32.     context.stop(connection)
  33.     context.stop(self)
  34.   }
  35.  
  36.   startWith(UninitializedState, UninitializedData)
  37.  
  38.   when(UninitializedState) {
  39.     case Event(StartMachine, _) => goto(UsernameInput)
  40.   }
  41.  
  42.   when(UsernameInput) {
  43.     case Event(Tcp.Received(data), _) =>
  44.       val username = Protocol.sanitizeResponse(data)
  45.  
  46.       userDAO.getByUsername(username) onComplete {
  47.         case Success(opt) => opt match {
  48.           case Some(user) => self ! UserFound(user)
  49.           case None       => self ! UserNotFound(username)
  50.         }
  51.         case Failure(err) => dbError(err)
  52.       }
  53.  
  54.       goto(AwaitingCallback)
  55.   }
  56.  
  57.   when(PasswordInput) {
  58.     case Event(Tcp.Received(data), UserData(user)) =>
  59.       val password = Protocol.sanitizeResponse(data)
  60.  
  61.       if (authenticator.authenticateUser(user, password)) {
  62.         parent ! ConnectionManager.SetToUserMenuPipeline(user)
  63.         stay
  64.       }
  65.       else {
  66.         val msg = "Invalid password."
  67.  
  68.         self ! Protocol.prepareResponse(msg)
  69.         goto(UsernameInput)
  70.       }
  71.   }
  72.  
  73.   when(AwaitingCallback) {
  74.     case Event(UserFound(user), _) =>
  75.       goto(PasswordInput) using UserData(user)
  76.  
  77.     case Event(UserNotFound(username), _) =>
  78.       parent ! ConnectionManager.SetToUserCreationPipeline(username)
  79.       stay
  80.   }
  81.  
  82.   onTransition {
  83.     case _ -> UsernameInput =>
  84.       val msg = "What is your username?"
  85.       self ! Protocol.prepareResponse(msg)
  86.  
  87.     case _ -> PasswordInput =>
  88.       val msg = "And what is your password?"
  89.       self ! Protocol.prepareResponse(msg)
  90.   }
  91.  
  92.   whenUnhandled {
  93.     case Event(Protocols.Send(data), _) =>
  94.       connection ! Tcp.Write(data)
  95.  
  96.       stay
  97.  
  98.     case Event(Protocols.Disconnect, _) =>
  99.       connection ! Tcp.Close
  100.  
  101.       stay
  102.  
  103.     case Event(Tcp.Closed, _) |
  104.          Event(Tcp.PeerClosed, _) =>
  105.       log.info(s"Client disconnected: $remote")
  106.       context.stop(self)
  107.  
  108.       stay
  109.   }
  110. }
  111.  
  112. object LoginFSM {
  113.   def props(parent: ActorRef, connection: ActorRef, remote: InetSocketAddress)
  114.            (implicit auth: Authentication, ec: ExecutionContext, userDAO: UserDAO): Props = {
  115.     Props(new LoginFSM(parent, connection, remote))
  116.   }
  117.  
  118.   sealed trait State
  119.   case object UninitializedState extends State
  120.   case object UsernameInput extends State
  121.   case object PasswordInput extends State
  122.   case object AwaitingCallback extends State
  123.  
  124.   sealed trait Data
  125.   case object UninitializedData extends Data
  126.   case class UserData(user: User) extends Data
  127.   case class UsernameData(username: String) extends Data
  128.  
  129.   sealed trait Event
  130.   case object StartMachine extends Event
  131.  
  132.   case class UserFound(user: User) extends Event
  133.   case class UserNotFound(username: String) extends Event
  134. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement