/app/xivo/services/XivoDirectory.scala

https://gitlab.com/winckell.benjamin.isart/xucserver · Scala · 205 lines · 179 code · 26 blank · 0 comment · 5 complexity · 942210ca4071b3a352d89ba103e9ab4b MD5 · raw file

  1. package xivo.services
  2. import akka.actor.{ActorRef, Actor, ActorLogging, Props}
  3. import play.api.libs.json._
  4. import services.directory.DirectoryTransformer
  5. import DirectoryTransformer.RawDirectoryResult
  6. import services.config.ConfigRepository
  7. import services.request._
  8. import xivo.network.XiVOWSdef
  9. import xivo.services.XivoDirectory.Action.Action
  10. import xivo.services.XivoDirectory._
  11. import xivo.xuc.XucConfig
  12. import models.{XivoUser, DirSearchResult, Token}
  13. import scala.concurrent.Await
  14. import scala.concurrent.duration._
  15. import play.api.libs.ws.{WSResponse, WSRequestHolder}
  16. object XivoDirectory {
  17. def props(xauth: ActorRef, dirTransformer: ActorRef, configRepo: ConfigRepository, xivoWS: XiVOWSdef): Props =
  18. Props(new XivoDirectory(xauth, dirTransformer, configRepo, xivoWS))
  19. sealed trait XivoDirectoryMsg
  20. case class DirLookupResult(result: DirSearchResult) extends XucRequest with XivoDirectoryMsg
  21. case class Favorites(result: DirSearchResult) extends XucRequest with XivoDirectoryMsg
  22. object Action extends Enumeration {
  23. type Action = Value
  24. val Added = Value
  25. val AddFail = Value
  26. val Removed = Value
  27. val RemoveFail = Value
  28. implicit val actionWrites = new Writes[Action] {
  29. def writes(enum: Action) = JsString(enum.toString)
  30. }
  31. }
  32. case class FavoriteUpdated(action: Action, contactId: String, source: String) extends XucRequest with XivoDirectoryMsg
  33. object FavoriteUpdated {
  34. implicit val writes = new Writes[FavoriteUpdated] {
  35. def writes(f: FavoriteUpdated): JsValue =
  36. JsObject(
  37. Seq("action" -> JsString(f.action.toString),
  38. "contact_id" -> JsString(f.contactId),
  39. "source" -> JsString(f.source)
  40. )
  41. )
  42. }
  43. }
  44. case object TokenRetrievalTimeout extends XucRequest with XivoDirectoryMsg
  45. case object XivoAuthTimeout extends XucRequest with XivoDirectoryMsg
  46. case object XivoAuthError extends XucRequest with XivoDirectoryMsg
  47. case object XivoDirdTimeout extends XucRequest with XivoDirectoryMsg
  48. }
  49. class XivoDirectory(xauth: ActorRef, dirTransformer: ActorRef, configRepo: ConfigRepository, xivoWS: XiVOWSdef)
  50. extends Actor with ActorLogging {
  51. def receive: Receive = {
  52. case UserBaseRequest(ref, request: DirectoryRequest, user) =>
  53. configRepo.getUser(user.ctiUsername) match {
  54. case None =>
  55. log.error(s"Got directory look up for unknown user ${user.ctiUsername}")
  56. case Some(user) =>
  57. log.debug(s"Received $request by user ${user.id}")
  58. getToken(user, BaseRequest(ref, request))
  59. }
  60. case (t: Token, BaseRequest(ref, DirectoryLookUp(term))) =>
  61. search(term, t) match {
  62. case r: DirLookupResult =>
  63. dirTransformer ! RawDirectoryResult(ref, r)
  64. case other =>
  65. ref ! other
  66. }
  67. case (t: Token, BaseRequest(ref, GetFavorites)) =>
  68. getFavorites(t) match {
  69. case f: Favorites =>
  70. dirTransformer ! RawDirectoryResult(ref, f)
  71. case other =>
  72. ref ! other
  73. }
  74. case (t: Token, BaseRequest(ref, AddFavorite(contactId, directory))) =>
  75. setFavorite(contactId, directory, t) match {
  76. case r: FavoriteUpdated =>
  77. log.debug(s"sending $r")
  78. dirTransformer ! RawDirectoryResult(ref, r)
  79. case other =>
  80. log.debug(s"sending $other")
  81. ref ! other
  82. }
  83. case (t: Token, BaseRequest(ref, RemoveFavorite(contactId, directory))) =>
  84. removeFavorite(contactId, directory, t) match {
  85. case r: FavoriteUpdated =>
  86. dirTransformer ! RawDirectoryResult(ref, r)
  87. case other =>
  88. ref ! other
  89. }
  90. case any =>
  91. log.debug(s"Received unprocessed message $any")
  92. }
  93. private def getToken(user: XivoUser, baseRequest: BaseRequest): Unit = {
  94. val replyTo = self
  95. context.actorOf(Props(new Actor() {
  96. xauth ! XivoAuthentication.GetToken(user.id)
  97. def receive: Receive = {
  98. case TokenRetrievalTimeout =>
  99. log.error("Get token timeout")
  100. baseRequest.requester ! XivoAuthTimeout
  101. context.stop(self)
  102. case t: Token =>
  103. log.debug(s"Got token, searching")
  104. replyTo ! (t, baseRequest)
  105. timeout.cancel()
  106. context.stop(self)
  107. case any =>
  108. log.error(s"Received unexpected response $any")
  109. baseRequest.requester ! XivoAuthError
  110. context.stop(self)
  111. }
  112. import context.dispatcher
  113. val timeout = context.system.scheduler.scheduleOnce(XucConfig.defaultWSTimeout) {
  114. self ! TokenRetrievalTimeout
  115. }
  116. }))
  117. }
  118. private def search(term: String, t: Token): XivoDirectoryMsg = {
  119. val searchURI = s"${XucConfig.XivoDir.searchURI}/${XucConfig.XivoDir.defaultProfile}${XucConfig.XivoDir.searchArg}$term"
  120. val request = xivoWS.get(XucConfig.xivoHost, searchURI, headers=Map("X-Auth-Token"-> t.token),
  121. port=Some(XucConfig.XivoDir.port))
  122. executeSearchRequest(request, t)
  123. }
  124. private def getFavorites(t: Token): XivoDirectoryMsg = {
  125. val requestURI = s"${XucConfig.XivoDir.favoriteURI}/${XucConfig.XivoDir.defaultProfile}"
  126. val request = xivoWS.get(XucConfig.xivoHost, requestURI, headers=Map("X-Auth-Token"-> t.token),
  127. port=Some(XucConfig.XivoDir.port))
  128. executeSearchRequest(request, t, true)
  129. }
  130. private def executeSearchRequest(request: WSRequestHolder, t: Token, favorites: Boolean = false): XivoDirectoryMsg = {
  131. import context.dispatcher
  132. val wsResult = request.execute().map(resp => DirSearchResult.parse(resp.json))
  133. val searchResult = Await.result(wsResult, XucConfig.defaultWSTimeout)
  134. searchResult match {
  135. case r: DirSearchResult =>
  136. log.debug(s"Got dird result: $r")
  137. if (!favorites) {
  138. DirLookupResult(r)
  139. }
  140. else {
  141. Favorites(r)
  142. }
  143. case _ =>
  144. log.debug(s"Timeout when searching directory by user: ${t.xivoUserUuid}")
  145. XivoDirdTimeout
  146. }
  147. }
  148. private def setFavorite(contactId: String, directory: String, t: Token): XivoDirectoryMsg = {
  149. val requestURI = s"${XucConfig.XivoDir.favoriteURI}/$directory/$contactId"
  150. val request = xivoWS.put(XucConfig.xivoHost, requestURI, headers = Map("X-Auth-Token" -> t.token),
  151. port = Some(XucConfig.XivoDir.port))
  152. processFavoriteRequest(request, contactId, directory, Action.Added, Action.AddFail)
  153. }
  154. private def removeFavorite(contactId: String, directory: String, t: Token): XivoDirectoryMsg = {
  155. val requestURI = s"${XucConfig.XivoDir.favoriteURI}/$directory/$contactId"
  156. val request = xivoWS.del(XucConfig.xivoHost, requestURI, headers=Map("X-Auth-Token"-> t.token),
  157. port=Some(XucConfig.XivoDir.port))
  158. processFavoriteRequest(request, contactId, directory, Action.Removed,
  159. Action.RemoveFail)
  160. }
  161. private def processFavoriteRequest(request: WSRequestHolder, contactId: String, directory: String,
  162. actionSuccess: Action, actionFail: Action): XivoDirectoryMsg = {
  163. val wsResult = request.execute()
  164. val searchResult = Await.result(wsResult, XucConfig.defaultWSTimeout)
  165. searchResult match {
  166. case r: WSResponse =>
  167. log.debug(s"Got set favorite result: ${r.status}")
  168. if (r.status == 204) {
  169. FavoriteUpdated(actionSuccess, contactId, directory)
  170. }
  171. else {
  172. FavoriteUpdated(actionFail, contactId, directory)
  173. }
  174. case _ =>
  175. log.debug(s"Timeout when processing favorite action ${actionSuccess} for $contactId/$directory")
  176. XivoDirdTimeout
  177. }
  178. }
  179. }