From 413dcc14468fc1edc4adf92a8862ae3c6e367e1b Mon Sep 17 00:00:00 2001 From: Marko Milic Date: Thu, 30 Mar 2017 11:10:35 +0200 Subject: [PATCH] Nonce separated by Akka --- src/main/scala/bootstrap/liftweb/Boot.scala | 2 +- src/main/scala/code/api/oauth1.0.scala | 53 ++++++++++-------- src/main/scala/code/model/OAuth.scala | 50 +++++++++++++++++ src/main/scala/code/nonce/NonceProvider.scala | 45 ++++++++++++++++ .../code/remotedata/RemotedataActors.scala | 3 +- .../code/remotedata/RemotedataNonces.scala | 32 +++++++++++ .../remotedata/RemotedataNoncesActor.scala | 54 +++++++++++++++++++ .../code/snippet/OAuthAuthorisation.scala | 8 +-- 8 files changed, 218 insertions(+), 29 deletions(-) create mode 100644 src/main/scala/code/nonce/NonceProvider.scala create mode 100644 src/main/scala/code/remotedata/RemotedataNonces.scala create mode 100644 src/main/scala/code/remotedata/RemotedataNoncesActor.scala diff --git a/src/main/scala/bootstrap/liftweb/Boot.scala b/src/main/scala/bootstrap/liftweb/Boot.scala index 510a9ead3..2868ea307 100644 --- a/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/src/main/scala/bootstrap/liftweb/Boot.scala @@ -436,6 +436,7 @@ object ToSchemify { MappedUserCustomerLink, Consumer, Token, + Nonce, MappedCounterparty, MappedCounterpartyMetadata, MappedCounterpartyWhereTag, @@ -448,7 +449,6 @@ object ToSchemify { val models = List( AuthUser, Admin, - Nonce, MappedBank, MappedBankAccount, MappedTransaction, diff --git a/src/main/scala/code/api/oauth1.0.scala b/src/main/scala/code/api/oauth1.0.scala index 121b1e26c..51280fe83 100644 --- a/src/main/scala/code/api/oauth1.0.scala +++ b/src/main/scala/code/api/oauth1.0.scala @@ -30,15 +30,15 @@ import java.util.Date import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec -import code.token.Tokens import code.api.Constant._ import code.api.util.{APIUtil, ErrorMessages} import code.consumer.Consumers -import code.model.{Consumer, Nonce, TokenType, User} +import code.model.{Consumer, TokenType, User} +import code.nonce.Nonces +import code.token.Tokens import net.liftweb.common._ import net.liftweb.http.rest.RestHelper import net.liftweb.http.{InMemoryResponse, PostRequest, Req, S} -import net.liftweb.mapper.By import net.liftweb.util.Helpers import net.liftweb.util.Helpers.{tryo, _} @@ -219,13 +219,11 @@ object OAuthHandshake extends RestHelper with Loggable { * same timestamp, client credentials, and token combinations. */ val token = parameters.get("oauth_token") getOrElse "" - - Nonce.count( - By(Nonce.value,parameters.get("oauth_nonce").get), - By(Nonce.tokenKey, token), - By(Nonce.consumerkey,parameters.get("oauth_consumer_key").get), - By(Nonce.timestamp, new Date(parameters.get("oauth_timestamp").get.toLong)) - ) !=0 + Nonces.nonces.vend.countNonces(consumerKey = parameters.get("oauth_consumer_key").get, + tokenKey = token, + timestamp = new Date(parameters.get("oauth_timestamp").get.toLong), + value = parameters.get("oauth_nonce").get + ) !=0 } def correctSignature(OAuthparameters : Map[String, String], httpMethod : String) = { @@ -433,13 +431,18 @@ object OAuthHandshake extends RestHelper with Loggable { private def saveRequestToken(oAuthParameters : Map[String, String], tokenKey : String, tokenSecret : String) = { - import code.model.{Nonce, TokenType} + import code.model.TokenType - val nonce = Nonce.create - nonce.consumerkey(oAuthParameters.get("oauth_consumer_key").get) - nonce.timestamp(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)) - nonce.value(oAuthParameters.get("oauth_nonce").get) - val nonceSaved = nonce.save() + val nonceSaved = Nonces.nonces.vend.createNonce( + id = None, + consumerKey = Some(oAuthParameters.get("oauth_consumer_key").get), + tokenKey = None, + timestamp = Some(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)), + value = Some(oAuthParameters.get("oauth_nonce").get) + ) match { + case Full(_) => true + case _ => false + } val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(oAuthParameters.get("oauth_consumer_key").get) match { case Full(consumer) => Some(consumer.id.get) @@ -472,14 +475,18 @@ object OAuthHandshake extends RestHelper with Loggable { private def saveAuthorizationToken(oAuthParameters : Map[String, String], tokenKey : String, tokenSecret : String) = { - import code.model.{Nonce, TokenType} + import code.model.TokenType - val nonce = Nonce.create - nonce.consumerkey(oAuthParameters.get("oauth_consumer_key").get) - nonce.timestamp(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)) - nonce.tokenKey(oAuthParameters.get("oauth_token").get) - nonce.value(oAuthParameters.get("oauth_nonce").get) - val nonceSaved = nonce.save() + val nonceSaved = Nonces.nonces.vend.createNonce( + id = None, + consumerKey = Some(oAuthParameters.get("oauth_consumer_key").get), + tokenKey = Some(oAuthParameters.get("oauth_token").get), + timestamp = Some(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)), + value = Some(oAuthParameters.get("oauth_nonce").get) + ) match { + case Full(_) => true + case _ => false + } val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(oAuthParameters.get("oauth_consumer_key").get) match { case Full(consumer) => Some(consumer.id.get) diff --git a/src/main/scala/code/model/OAuth.scala b/src/main/scala/code/model/OAuth.scala index e1ffd5dc4..7f905c739 100644 --- a/src/main/scala/code/model/OAuth.scala +++ b/src/main/scala/code/model/OAuth.scala @@ -36,6 +36,7 @@ import code.token.TokensProvider import code.consumer.{Consumers, ConsumersProvider} import code.model.TokenType.TokenType import code.model.dataAccess.ResourceUser +import code.nonce.NoncesProvider import code.users.Users import net.liftweb.common._ import net.liftweb.http.S @@ -294,7 +295,56 @@ object Consumer extends Consumer with Loggable with LongKeyedMetaMapper[Consumer } +object MappedNonceProvider extends NoncesProvider { + override def createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]): Box[Nonce] = { + tryo { + val n = Nonce.create + id match { + case Some(v) => n.id(v) + case None => + } + consumerKey match { + case Some(v) => n.consumerkey(v) + case None => + } + tokenKey match { + case Some(v) => n.tokenKey(v) + case None => + } + timestamp match { + case Some(v) => n.timestamp(v) + case None => + } + value match { + case Some(v) => n.value(v) + case None => + } + val nonce = n.saveMe() + nonce + } + } + override def deleteExpiredNonces(currentDate: Date): Boolean = { + Nonce.findAll(By_<(Nonce.timestamp, currentDate)).forall(_.delete_!) + } + + override def countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String): Long = { + Nonce.count( + By(Nonce.value, value), + By(Nonce.tokenKey, tokenKey), + By(Nonce.consumerkey, consumerKey), + By(Nonce.timestamp, timestamp) + ) + } + +} class Nonce extends LongKeyedMapper[Nonce] { def getSingleton = Nonce diff --git a/src/main/scala/code/nonce/NonceProvider.scala b/src/main/scala/code/nonce/NonceProvider.scala new file mode 100644 index 000000000..dfa8a2dae --- /dev/null +++ b/src/main/scala/code/nonce/NonceProvider.scala @@ -0,0 +1,45 @@ +package code.nonce + +import java.util.Date + +import code.model.Nonce +import net.liftweb.util.SimpleInjector +import code.remotedata.RemotedataNonces +import net.liftweb.common.Box + + +object Nonces extends SimpleInjector { + + val nonces = new Inject(buildOne _) {} + + def buildOne: NoncesProvider = RemotedataNonces + +} + +trait NoncesProvider { + def createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]): Box[Nonce] + def deleteExpiredNonces(currentDate: Date): Boolean + def countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String): Long +} + +class RemotedataNoncesCaseClasses { + case class createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]) + case class deleteExpiredNonces(currentDate: Date) + case class countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String) +} + +object RemotedataNoncesCaseClasses extends RemotedataNoncesCaseClasses diff --git a/src/main/scala/code/remotedata/RemotedataActors.scala b/src/main/scala/code/remotedata/RemotedataActors.scala index c4e8505ad..503920600 100644 --- a/src/main/scala/code/remotedata/RemotedataActors.scala +++ b/src/main/scala/code/remotedata/RemotedataActors.scala @@ -96,7 +96,8 @@ object RemotedataActors extends Loggable { ActorProps[RemotedataConsumersActor] -> RemotedataConsumers.actorName, ActorProps[RemotedataTransactionRequestsActor] -> RemotedataTransactionRequests.actorName, ActorProps[RemotedataMetricsActor] -> RemotedataMetrics.actorName, - ActorProps[RemotedataTokensActor] -> RemotedataTokens.actorName + ActorProps[RemotedataTokensActor] -> RemotedataTokens.actorName, + ActorProps[RemotedataNoncesActor] -> RemotedataNonces.actorName ) actorsRemotedata.foreach { a => logger.info(actorSystem.actorOf(a._1, name = a._2)) } diff --git a/src/main/scala/code/remotedata/RemotedataNonces.scala b/src/main/scala/code/remotedata/RemotedataNonces.scala new file mode 100644 index 000000000..2ce99356c --- /dev/null +++ b/src/main/scala/code/remotedata/RemotedataNonces.scala @@ -0,0 +1,32 @@ +package code.remotedata + +import java.util.Date + +import code.model.Nonce +import code.nonce.{NoncesProvider, RemotedataNoncesCaseClasses} +import net.liftweb.common.Box +import akka.pattern.ask + + +object RemotedataNonces extends ActorInit with NoncesProvider { + + val cc = RemotedataNoncesCaseClasses + + def createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]): Box[Nonce] = + extractFutureToBox(actor ? cc.createNonce(id, consumerKey, tokenKey, timestamp, value)) + + def deleteExpiredNonces(currentDate: Date): Boolean = + extractFuture(actor ? cc.deleteExpiredNonces(currentDate)) + + def countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String): Long = + extractFuture(actor ? cc.countNonces(consumerKey, tokenKey, timestamp, value)) + + +} diff --git a/src/main/scala/code/remotedata/RemotedataNoncesActor.scala b/src/main/scala/code/remotedata/RemotedataNoncesActor.scala new file mode 100644 index 000000000..9561dfcc6 --- /dev/null +++ b/src/main/scala/code/remotedata/RemotedataNoncesActor.scala @@ -0,0 +1,54 @@ +package code.remotedata + +import java.util.Date + +import akka.actor.Actor +import akka.event.Logging +import code.model._ +import code.nonce.RemotedataNoncesCaseClasses + + +class RemotedataNoncesActor extends Actor with ActorHelper { + + val logger = Logging(context.system, this) + + val mapper = MappedNonceProvider + val cc = RemotedataNoncesCaseClasses + + def receive = { + + case cc.createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]) => + logger.debug("createNonce(" + id + ", " + + consumerKey+ ", " + + tokenKey + ", " + + timestamp + ", " + + value + ")") + sender ! extractResult(mapper.createNonce(id, consumerKey, tokenKey, timestamp, value)) + + case cc.deleteExpiredNonces(currentDate: Date) => + logger.debug("deleteExpiredNonces(" + currentDate +")") + sender ! extractResult(mapper.deleteExpiredNonces(currentDate)) + + case cc.countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String) => + logger.debug("countNonces(" + consumerKey + ", " + + tokenKey+ ", " + + timestamp + ", " + + value + ", " + + ")") + sender ! extractResult(mapper.countNonces(consumerKey, tokenKey, timestamp, value)) + + + case message => logger.warning("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) + + } + +} + + diff --git a/src/main/scala/code/snippet/OAuthAuthorisation.scala b/src/main/scala/code/snippet/OAuthAuthorisation.scala index 1b6a43a97..9d53bfdc1 100644 --- a/src/main/scala/code/snippet/OAuthAuthorisation.scala +++ b/src/main/scala/code/snippet/OAuthAuthorisation.scala @@ -36,11 +36,12 @@ package code.snippet import java.util.Date -import code.token.Tokens import code.api.util.APIUtil import code.consumer.Consumers import code.model.dataAccess.AuthUser -import code.model.{Nonce, Token, TokenType} +import code.model.{Token, TokenType} +import code.nonce.Nonces +import code.token.Tokens import code.users.Users import code.util.Helper import code.util.Helper.NOOP_SELECTOR @@ -193,7 +194,6 @@ object OAuthAuthorisation { //looks for expired tokens and nonces and deletes them def dataBaseCleaner: Unit = { - import net.liftweb.mapper.By_< import net.liftweb.util.Schedule Schedule.schedule(dataBaseCleaner _, 1 hour) @@ -208,6 +208,6 @@ object OAuthAuthorisation { //delete expired tokens and nonces Tokens.tokens.vend.deleteExpiredTokens(currentDate) - Nonce.findAll(By_<(Nonce.timestamp, timeLimit)).foreach(t => t.delete_!) + Nonces.nonces.vend.deleteExpiredNonces(currentDate) } } \ No newline at end of file