From a8431d5e391f37fcd1ad55007a1a12c3d3f8674f Mon Sep 17 00:00:00 2001 From: Sheikh Hosseini Date: Sun, 30 Oct 2016 08:43:15 +0330 Subject: [PATCH 1/3] Add IR/Magfa sms gateway --- .../activation/magfa/MagfaProvider.scala | 60 +++++++++++++++++++ .../im/actor/server/sms/MagfaClient.scala | 50 ++++++++++++++++ .../im/actor/server/sms/MagfaSmsEngine.scala | 7 +++ 3 files changed, 117 insertions(+) create mode 100644 actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala create mode 100644 actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala create mode 100644 actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaSmsEngine.scala diff --git a/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala b/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala new file mode 100644 index 0000000000..ba9639e9c4 --- /dev/null +++ b/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala @@ -0,0 +1,60 @@ +package im.actor.server.activation.magfa + +import akka.actor.ActorSystem +import akka.pattern.ask +import akka.util.Timeout +import cats.data.Xor +import im.actor.config.ActorConfig +import im.actor.server.activation.common.ActivationStateActor.{ ForgetSentCode, Send, SendAck } +import im.actor.server.activation.common._ +import im.actor.server.db.DbExtension +import im.actor.server.model.AuthPhoneTransaction +import im.actor.server.persist.auth.AuthTransactionRepo +import im.actor.server.sms._ +import im.actor.util.misc.PhoneNumberUtils.isTestPhone + +import scala.concurrent.Future +import scala.concurrent.duration._ + +private[activation] final class MagfaProvider(implicit system: ActorSystem) extends ActivationProvider with CommonAuthCodes { + + protected val activationConfig = ActivationConfig.load.getOrElse(throw new RuntimeException("Failed to load activation config")) + protected val db = DbExtension(system).db + protected implicit val ec = system.dispatcher + + private val telesignClient = new MagfaClient(ActorConfig.load().getConfig("services.magfa")) + private val smsEngine = new MagfaSmsEngine(telesignClient) + + private implicit val timeout = Timeout(20.seconds) + + private val smsStateActor = system.actorOf(ActivationStateActor.props[Long, SmsCode]( + repeatLimit = activationConfig.repeatLimit, + sendAction = (code: SmsCode) ⇒ smsEngine.sendCode(code.phone, code.code), + id = (code: SmsCode) ⇒ code.phone + ), "telesign-sms-state") + + override def send(txHash: String, code: Code): Future[CodeFailure Xor Unit] = code match { + case s: SmsCode ⇒ + for { + resp ← if (isTestPhone(s.phone)) + Future.successful(Xor.right(())) + else + (smsStateActor ? Send(code)).mapTo[SendAck].map(_.result) + _ ← createAuthCodeIfNeeded(resp, txHash, code.code) + } yield resp + case other ⇒ throw new RuntimeException(s"This provider can't handle code of type: ${other.getClass}") + } + + override def cleanup(txHash: String): Future[Unit] = { + for { + ac ← db.run(AuthTransactionRepo.findChildren(txHash)) + _ = ac match { + case Some(x: AuthPhoneTransaction) ⇒ + smsStateActor ! ForgetSentCode.phone(x.phoneNumber) + case _ ⇒ + } + _ ← deleteAuthCode(txHash) + } yield () + } + +} diff --git a/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala new file mode 100644 index 0000000000..71dbfd9d37 --- /dev/null +++ b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala @@ -0,0 +1,50 @@ +package im.actor.server.sms + +import java.net.URLEncoder + +import akka.actor.ActorSystem +import com.ning.http.client.Response +import com.typesafe.config.Config +import dispatch.{ Http, url } + +import scala.concurrent.{ ExecutionContext, Future } +import scala.util.Failure + +final class MagfaClient(config: Config)(implicit system: ActorSystem) { + + private lazy val http = new Http() + private val Utf8Encoding = "UTF-8" + system registerOnTermination http.shutdown() + + private implicit val ec: ExecutionContext = system.dispatcher + + private val BaseUrl = config.getString("url") + // private val ResourcePath = config.getString("/services/send") + private val ResourcePath = "/services/send?" + + def sendSmsCode(phoneNumber: Long, code: String): Future[Unit] = { + postRequest(ResourcePath, Map( + "from" → config.getString("from"), + "to" → phoneNumber.toString, + "message" → code + )) map { _ ⇒ + system.log.debug("Message sent via magfa") + } + } + + private def postRequest(resourcePath: String, params: Map[String, String]): Future[Response] = { + val body = params.map(p ⇒ s"${p._1}=${URLEncoder.encode(p._2, Utf8Encoding)}").mkString("&") + val request = url(BaseUrl + resourcePath + body) + + http(request).map { resp ⇒ + if (resp.getStatusCode < 199 || resp.getStatusCode > 299) { + throw new RuntimeException(s"Response has code ${resp.getStatusCode}. [${resp.getResponseBody}]") + } else { + resp + } + } andThen { + case Failure(e) ⇒ + system.log.error(e, "Failed to make request to telesign") + } + } +} \ No newline at end of file diff --git a/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaSmsEngine.scala b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaSmsEngine.scala new file mode 100644 index 0000000000..40ea64c759 --- /dev/null +++ b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaSmsEngine.scala @@ -0,0 +1,7 @@ +package im.actor.server.sms + +import scala.concurrent.Future + +final class MagfaSmsEngine(magfaSmsClient: MagfaClient) extends AuthSmsEngine { + override def sendCode(phoneNumber: Long, message: String): Future[Unit] = magfaSmsClient.sendSmsCode(phoneNumber, message) +} \ No newline at end of file From ada4d57b5d4f8b25f7cdcd484199ef5065db5924 Mon Sep 17 00:00:00 2001 From: Sheikh Hosseini Date: Tue, 1 Nov 2016 08:25:59 +0330 Subject: [PATCH 2/3] Add IR/Magfa sms gateway --- .../actor-activation/src/main/resources/reference.conf | 8 ++++++++ .../im/actor/server/activation/magfa/MagfaProvider.scala | 8 ++++---- actor-server/actor-sms/src/main/resources/reference.conf | 4 ++++ .../src/main/scala/im/actor/server/sms/MagfaClient.scala | 9 ++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/actor-server/actor-activation/src/main/resources/reference.conf b/actor-server/actor-activation/src/main/resources/reference.conf index bba3b7ac6b..4cb08cde93 100644 --- a/actor-server/actor-activation/src/main/resources/reference.conf +++ b/actor-server/actor-activation/src/main/resources/reference.conf @@ -17,6 +17,14 @@ services { } } + magfa { + service : "" + domain : "" + username: "" + password : "" + from: "" + } + actor-activation { uri: "https://gate.actor.im" auth-token: "" diff --git a/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala b/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala index ba9639e9c4..a10d69fb23 100644 --- a/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala +++ b/actor-server/actor-activation/src/main/scala/im/actor/server/activation/magfa/MagfaProvider.scala @@ -22,8 +22,8 @@ private[activation] final class MagfaProvider(implicit system: ActorSystem) exte protected val db = DbExtension(system).db protected implicit val ec = system.dispatcher - private val telesignClient = new MagfaClient(ActorConfig.load().getConfig("services.magfa")) - private val smsEngine = new MagfaSmsEngine(telesignClient) + private val magfaClient = new MagfaClient(ActorConfig.load().getConfig("services.magfa")) + private val smsEngine = new MagfaSmsEngine(magfaClient) private implicit val timeout = Timeout(20.seconds) @@ -31,7 +31,7 @@ private[activation] final class MagfaProvider(implicit system: ActorSystem) exte repeatLimit = activationConfig.repeatLimit, sendAction = (code: SmsCode) ⇒ smsEngine.sendCode(code.phone, code.code), id = (code: SmsCode) ⇒ code.phone - ), "telesign-sms-state") + ), "magfa-sms-state") override def send(txHash: String, code: Code): Future[CodeFailure Xor Unit] = code match { case s: SmsCode ⇒ @@ -57,4 +57,4 @@ private[activation] final class MagfaProvider(implicit system: ActorSystem) exte } yield () } -} +} \ No newline at end of file diff --git a/actor-server/actor-sms/src/main/resources/reference.conf b/actor-server/actor-sms/src/main/resources/reference.conf index 0bee43de44..140982c73b 100644 --- a/actor-server/actor-sms/src/main/resources/reference.conf +++ b/actor-server/actor-sms/src/main/resources/reference.conf @@ -6,4 +6,8 @@ sms { clickatell { } + + magfa { + + } } diff --git a/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala index 71dbfd9d37..2187fac038 100644 --- a/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala +++ b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala @@ -19,14 +19,17 @@ final class MagfaClient(config: Config)(implicit system: ActorSystem) { private implicit val ec: ExecutionContext = system.dispatcher private val BaseUrl = config.getString("url") - // private val ResourcePath = config.getString("/services/send") - private val ResourcePath = "/services/send?" + private val ResourcePath = "/magfaHttpService?" def sendSmsCode(phoneNumber: Long, code: String): Future[Unit] = { postRequest(ResourcePath, Map( + "service" -> config.getString("service"), + "domain" -> config.getString("domain"), + "username" -> config.getString("username"), + "password" -> config.getString("password"), "from" → config.getString("from"), "to" → phoneNumber.toString, - "message" → code + "message" → "code" )) map { _ ⇒ system.log.debug("Message sent via magfa") } From a992015cdf55fdeef7f8c96f0a980519a6cc187b Mon Sep 17 00:00:00 2001 From: Sheikh Hosseini Date: Tue, 1 Nov 2016 08:27:44 +0330 Subject: [PATCH 3/3] Add IR/Magfa sms gateway --- .../src/main/scala/im/actor/server/sms/MagfaClient.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala index 2187fac038..9c3ba2677e 100644 --- a/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala +++ b/actor-server/actor-sms/src/main/scala/im/actor/server/sms/MagfaClient.scala @@ -29,7 +29,7 @@ final class MagfaClient(config: Config)(implicit system: ActorSystem) { "password" -> config.getString("password"), "from" → config.getString("from"), "to" → phoneNumber.toString, - "message" → "code" + "message" → code )) map { _ ⇒ system.log.debug("Message sent via magfa") }