Merge pull request #2173 from constantine2nd/develop

A few changes
This commit is contained in:
Simon Redfern 2023-01-25 14:09:59 +01:00 committed by GitHub
commit 4d29743585
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
96 changed files with 710 additions and 3254 deletions

View File

@ -58,40 +58,12 @@ To compile and run jetty, install Maven 3, create your configuration in obp-api/
mvn install -pl .,obp-commons && mvn jetty:run -pl obp-api
## To run with IntelliJ IDEA
* Make sure you have the IntelliJ Scala plugin installed.
* Create a new folder e.g. OpenBankProject and cd there
* git clone https://github.com/OpenBankProject/OBP-API.git
* In IntelliJ IDEA do File -> New -> Project from existing sources, navigate to the folder and select pom.xml
* Alternatively you can do File -> New -> Project from VCS and checkout the project directly from github.
* When / if prompted for SDK, choose Java 1.8 (and Scala 2.12) otherwise keep the defaults. Use the Maven options. Do not change the project name etc.
* If you see a message about an unmanaged pom.xml, click the option to let Maven manage it.
* Navigate to obp-api/test/scala/code/RunWebApp. You may see a Setup Scala SDK link. Click this and check Scala 2.12.4 or so.
[Note: How to run via IntelliJ IDEA](docs/glossary/Run_via_IntelliJ_IDEA.md)
## Run some tests.
* In obp-api/src/main/resources/props create a test.default.props for tests. Set connector=mapped
* In obp-api/src/main/resources/props create a \<yourloginname\>.props (or default.props) for development. Set connector=mapped
* Now **Rebuild** the project so everything is compiled. At this point you may need to select the SDK, see above.
* Once you have rebuilt the project without compile errors, you should be able to RunWebApp in obp-api/src/test/scala
* If you have trouble (re)building, try using the IntelliJ IDEA terminal: mvn clean test-compile
* Run RunWebApp by right clicking on it or selecting Run. The built in jetty server should start on localhost:8080
* Browse to localhost:8080 but don't try anything else there yet.
### Run some tests.
* Run a single test. For instance right click on obp-api/test/scala/code/branches/MappedBranchProviderTest and select Run Mapp...
* Run multiple tests: Right click on obp-api/test/scala/code and select Run. If need be:

View File

@ -0,0 +1,49 @@
## To run via IntelliJ IDEA
* Make sure you have the IntelliJ Scala plugin installed.
* Create a new folder e.g. OpenBankProject and cd there
* git clone https://github.com/OpenBankProject/OBP-API.git
* In IntelliJ IDEA do File -> New -> Project from existing sources, navigate to the folder and select pom.xml
* Alternatively you can do File -> New -> Project from VCS and checkout the project directly from github.
* When / if prompted for SDK, choose Java 1.8 (and Scala 2.12) otherwise keep the defaults. Use the Maven options. Do not change the project name etc.
* If you see a message about an unmanaged pom.xml, click the option to let Maven manage it.
* Navigate to obp-api/test/scala/code/RunWebApp. You may see a Setup Scala SDK link. Click this and check Scala 2.12.12 or so.
* In obp-api/src/main/resources/props create a \<yourloginname\>.props (or default.props) for development. Set connector=mapped
* Now **Rebuild** the project so everything is compiled. At this point you may need to select the SDK, see above.
* Once you have rebuilt the project without compile errors, you should be able to RunWebApp/RunTLSWebApp/RunMTLSWebApp in obp-api/src/test/scala
* If you have trouble (re)building, try using the IntelliJ IDEA terminal: mvn clean test-compile
### To run via IntelliJ IDEA in development mode without secure connection
* Run RunWebApp by right clicking on it or selecting Run. The built in jetty server should start on localhost:8080
* Browse to http://localhost:8080 but don't try anything else there yet.
### To run via IntelliJ IDEA in TLS development mode (secure connection)
* Run RunTLSWebApp by right clicking on it and selecting Run/Debug. The built in jetty server should start on localhost:8080
* Browse to https://localhost:8080 but don't try anything else there yet
In `development` mode we use this option in order to try OpenID Connect functionality. I.e. redirect URI must be `https` one.
### To run via IntelliJ IDEA in MTLS development mode (secure connection)
* Run RunMTLSWebApp by right clicking on it and selecting Run/Debug. The built in jetty server should start on localhost:8080
* Import certificate obp-api/src/test/resources/cert/localhost_SAN_dns_ip.pfx into your browser.
* Browse to https://localhost:8080 but don't try anything else there yet
In `development` mode we use this option in order to try UK Open Banking APIs functionality where mutual TLS is part of that standard.

View File

@ -169,16 +169,6 @@
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.liftweb</groupId>
<artifactId>lift-mongodb_${scala.version}</artifactId>
<version>${lift.version}</version>
</dependency>
<dependency>
<groupId>net.liftweb</groupId>
<artifactId>lift-mongodb-record_${scala.version}</artifactId>
<version>${lift.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
@ -508,6 +498,12 @@
<artifactId>jackson-databind</artifactId>
<version>2.12.7.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.1</version>
</dependency>
</dependencies>
<build>

View File

@ -232,6 +232,10 @@ apiPathZero=obp
## Not need in dev mode, but important for production
mail.api.consumer.registered.sender.address=no-reply@example.com
mail.api.consumer.registered.notification.addresses=you@example.com
## Not need in dev mode, but important for production
## We send an email after any exception
# mail.exception.sender.address=no-reply@example.com
# mail.exception.registered.notification.addresses=notify@example.com,notify2@example.com,notify3@example.com
# This property allows sending API registration data to developer's email.
#mail.api.consumer.registered.notification.send=false
We only send consumer keys and secret if this is true
@ -448,9 +452,6 @@ webui_oauth_1_documentation_url =
# Link to OAuth 2.0 glossary on api explorer
webui_oauth_2_documentation_url =
# URL of OAuth2.0 server
oauth2_server_url =
# Link to Privacy Policy on signup page
#webui_signup_form_submit_button_value=
#webui_signup_form_title_text=Sign Up

View File

@ -17,7 +17,6 @@
#which data connector to use
#connector=mongodb
#connector=rest
#connector=kafka
#connector=obpjvm

View File

@ -29,6 +29,7 @@ package bootstrap.liftweb
import java.io.{File, FileInputStream}
import java.util.stream.Collectors
import java.util.{Locale, TimeZone}
import code.CustomerDependants.MappedCustomerDependant
import code.DynamicData.DynamicData
import code.DynamicEndpoint.DynamicEndpoint
@ -47,24 +48,33 @@ import code.api.util.APIUtil.{enableVersionIfAllowed, errorJsonResponse, getProp
import code.api.util._
import code.api.util.migration.Migration
import code.api.util.migration.Migration.DbFunction
import code.apicollection.ApiCollection
import code.apicollectionendpoint.ApiCollectionEndpoint
import code.atms.MappedAtm
import code.authtypevalidation.AuthenticationTypeValidation
import code.bankattribute.BankAttribute
import code.bankconnectors.storedprocedure.StoredProceduresMockedData
import code.bankconnectors.{Connector, ConnectorEndpoints}
import code.branches.MappedBranch
import code.cardattribute.MappedCardAttribute
import code.cards.{MappedPhysicalCard, PinReset}
import code.connectormethod.ConnectorMethod
import code.consent.{ConsentRequest, MappedConsent}
import code.consumer.Consumers
import code.context.{MappedConsentAuthContext, MappedUserAuthContext, MappedUserAuthContextUpdate}
import code.crm.MappedCrmEvent
import code.customer.internalMapping.MappedCustomerIdMapping
import code.customer.{MappedCustomer, MappedCustomerMessage}
import code.customeraccountlinks.CustomerAccountLink
import code.customeraddress.MappedCustomerAddress
import code.customerattribute.MappedCustomerAttribute
import code.database.authorisation.Authorisation
import code.directdebit.DirectDebit
import code.dynamicEntity.DynamicEntity
import code.dynamicMessageDoc.DynamicMessageDoc
import code.dynamicResourceDoc.DynamicResourceDoc
import code.endpointMapping.EndpointMapping
import code.endpointTag.EndpointTag
import code.entitlement.MappedEntitlement
import code.entitlementrequest.MappedEntitlementRequest
import code.fx.{MappedCurrency, MappedFXRate}
@ -85,28 +95,19 @@ import code.metadata.wheretags.MappedWhereTag
import code.methodrouting.MethodRouting
import code.metrics.{MappedConnectorMetric, MappedMetric, MetricsArchive}
import code.migration.MigrationScriptLog
import code.model.{Consumer, _}
import code.model.dataAccess._
import code.model.dataAccess.internalMapping.AccountIdMapping
import code.model.{Consumer, _}
import code.obp.grpc.HelloWorldServer
import code.productAttributeattribute.MappedProductAttribute
import code.productcollection.MappedProductCollection
import code.productcollectionitem.MappedProductCollectionItem
import code.productfee.ProductFee
import code.products.MappedProduct
import code.ratelimiting.RateLimiting
import code.remotedata.RemotedataActors
import code.scheduler.{DatabaseDriverScheduler, MetricsArchiveScheduler}
import code.scope.{MappedScope, MappedUserScope}
import code.apicollectionendpoint.ApiCollectionEndpoint
import code.apicollection.ApiCollection
import code.bankattribute.BankAttribute
import code.connectormethod.ConnectorMethod
import code.customeraccountlinks.CustomerAccountLink
import code.dynamicMessageDoc.DynamicMessageDoc
import code.dynamicResourceDoc.DynamicResourceDoc
import code.endpointMapping.EndpointMapping
import code.endpointTag.EndpointTag
import code.productfee.ProductFee
import code.snippet.{OAuthAuthorisation, OAuthWorkedThanks}
import code.socialmedia.MappedSocialMedia
import code.standingorders.StandingOrder
@ -121,19 +122,17 @@ import code.transactionattribute.MappedTransactionAttribute
import code.transactionrequests.{MappedTransactionRequest, MappedTransactionRequestTypeCharge, TransactionRequestReasons}
import code.usercustomerlinks.MappedUserCustomerLink
import code.userlocks.UserLocks
import code.users.{UserAgreement, UserAttribute, UserInitAction, UserInvitation, Users}
import code.users._
import code.util.Helper.MdcLoggable
import code.util.{Helper, HydraUtil}
import code.validation.JsonSchemaValidation
import code.views.Views
import code.views.system.{AccountAccess, ViewDefinition}
import code.webhook.{BankAccountNotificationWebhook, MappedAccountWebhook, SystemAccountNotificationWebhook, WebhookHelperActors}
import code.webhook.{BankAccountNotificationWebhook, MappedAccountWebhook, SystemAccountNotificationWebhook}
import code.webuiprops.WebUiProps
import com.openbankproject.commons.model.{ErrorMessage, User}
import com.openbankproject.commons.model.ErrorMessage
import com.openbankproject.commons.util.Functions.Implicits._
import com.openbankproject.commons.util.{ApiVersion, Functions}
import javax.mail.{Authenticator, PasswordAuthentication}
import javax.mail.internet.MimeMessage
import net.liftweb.common._
import net.liftweb.db.DBLogEntry
@ -332,12 +331,8 @@ class Boot extends MdcLoggable {
// ensure our relational database's tables are created/fit the schema
val connector = APIUtil.getPropsValue("connector").openOrThrowException("no connector set")
if(connector != "mongodb")
schemifyAll()
schemifyAll()
// This sets up MongoDB config (for the mongodb connector)
if( connector == "mongodb")
MongoConfig.init
val runningMode = Props.mode match {
case Props.RunModes.Production => "Production mode"
@ -488,8 +483,7 @@ class Boot extends MdcLoggable {
Nil
}
}
WebhookHelperActors.startLocalWebhookHelperWorkers(actorSystem)
if (connector.startsWith("kafka") || (connector == "star" && APIUtil.getPropsValue("starConnector_supported_types","").split(",").contains("kafka"))) {
logger.info(s"KafkaHelperActors.startLocalKafkaHelperWorkers( ${actorSystem} ) starting")

View File

@ -6,7 +6,6 @@ import code.bankconnectors.LocalMappedOutInBoundTransfer
import code.bankconnectors.akka.actor.{AkkaConnectorActorConfig, AkkaConnectorHelperActor}
import code.util.Helper
import code.util.Helper.MdcLoggable
import code.webhook.WebhookHelperActors
import com.openbankproject.adapter.akka.commons.config.AkkaConfig
import com.typesafe.config.ConfigFactory
import net.liftweb.common.Full
@ -79,31 +78,6 @@ trait ObpLookupSystem extends MdcLoggable {
this.obpLookupSystem.actorSelection(actorPath)
}
/**
* This function is a Single Point Of Entry for Webhook's Actor
* I.e. we can obtain te Actor all over the code in next way:
* {
* val actor: ActorSelection = ObpLookupSystem.getWebhookActor()
* }
*
* @return An ActorSelection which is a logical view of a section of an ActorSystem's tree of Actors,
* allowing for broadcasting of messages to that section.
*/
def getWebhookActor(): ActorSelection = {
val name = WebhookHelperActors.actorName
val actorPath: String = {
val hostname = ObpActorConfig.localHostname
val port = ObpActorConfig.localPort
val props_hostname = Helper.getHostname
if (port == 0) {
logger.error("Failed to connect to local Webhook's actor")
}
s"akka.tcp://ObpActorSystem_${props_hostname}@${hostname}:${port}/user/${name}"
}
this.obpLookupSystem.actorSelection(actorPath)
}
def getAkkaConnectorActor(actorName: String) = {
val hostname = APIUtil.getPropsValue("akka_connector.hostname")

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_AccountAccessConsentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_AccountsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_BalancesApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_BeneficiariesApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_DirectDebitsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_DomesticFutureDatedPaymentConsentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_DomesticFutureDatedPaymentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_DomesticPaymentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_DomesticPaymentsConsentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_EventNotificationApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_FilePaymentConsentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_FilePaymentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_FutureDatedPaymentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_InternationalPaymentConsentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_InternationalPaymentsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_OffersApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_PartiesApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_StandingOrdersApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_StatementsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_SupplementaryAccountInfoApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -1,27 +1,19 @@
package code.api.BahrainOBF.v1_0_0
import code.api.APIFailureNewStyle
import code.api.berlin.group.v1_3.JvalueCaseClass
import net.liftweb.json
import net.liftweb.json._
import code.api.util.APIUtil.{defaultBankId, _}
import code.api.util.NewStyle
import code.api.util.ErrorMessages._
import code.api.util.APIUtil._
import code.api.util.ApiTag
import code.api.util.ApiTag._
import code.api.util.NewStyle.HttpCode
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import code.api.util.ErrorMessages._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.json
import net.liftweb.json._
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import com.openbankproject.commons.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.BahrainOBF.v1_0_0.ApiCollector
import code.api.util.ApiTag
object APIMethods_TransactionsApi extends RestHelper {
val apiVersion = ApiCollector.apiVersion

View File

@ -128,11 +128,14 @@ object OAuth2Login extends RestHelper with MdcLoggable {
if(consumer.isEmpty) {
return (Failure(Oauth2TokenHaveNoConsumer), Some(cc.copy(consumer = Failure(Oauth2TokenHaveNoConsumer))))
}
val clientCert = APIUtil.`getPSD2-CERT`(cc.requestHeaders)
val clientCert: Option[String] = APIUtil.`getPSD2-CERT`(cc.requestHeaders)
clientCert.filter(StringUtils.isNotBlank).foreach {cert =>
val foundConsumer = consumer.orNull
val certInConsumer = foundConsumer.clientCertificate.get
if(StringUtils.isBlank(certInConsumer)) {
// In case that the certificate of a consumer is not populated in a database
// we use the value at PSD2-CERT header in order to populate it for the first time.
// Please note that every next call MUST match that value.
foundConsumer.clientCertificate.set(cert)
consumer = Full(foundConsumer.saveMe())
val clientId = foundConsumer.key.get
@ -147,10 +150,18 @@ object OAuth2Login extends RestHelper with MdcLoggable {
// hydra update client endpoint have bug, So here delete and create to do update
hydraAdmin.deleteOAuth2Client(clientId)
hydraAdmin.createOAuth2Client(oAuth2Client)
} else if(stringNotEq(certInConsumer, cert)) {
} else if(stringNotEq(certInConsumer, cert)) {
// Cannot match the value from PSD2-CERT header and the database value Consumer.clientCertificate
logger.debug("Cert in Consumer: " + certInConsumer)
logger.debug("Cert in Request: " + cert)
logger.debug(s"Token: $value")
logger.debug(s"Client ID: ${introspectOAuth2Token.getClientId}")
return (Failure(Oauth2TokenMatchCertificateFail), Some(cc.copy(consumer = Failure(Oauth2TokenMatchCertificateFail))))
} else {
// Certificate is matched. Just make some debug logging.
logger.debug("The token is linked with a proper client certificate.")
logger.debug(s"Token: $value")
logger.debug(s"Client Key: ${introspectOAuth2Token.getClientId}")
}
}
}

View File

@ -6,7 +6,7 @@ import java.util.Date
import code.api.util.APIUtil._
import code.api.util.{APIUtil, ConsentJWT, CustomJsonFormats, JwtUtil}
import code.bankconnectors.Connector
import code.consent.Consent
import code.consent.ConsentTrait
import code.database.authorisation.Authorisation
import code.model.ModeratedTransaction
import com.openbankproject.commons.model.enums.AccountRoutingScheme
@ -496,7 +496,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats {
)
}
def createPostConsentResponseJson(consent: Consent) : PostConsentResponseJson = {
def createPostConsentResponseJson(consent: ConsentTrait) : PostConsentResponseJson = {
PostConsentResponseJson(
consentId = consent.consentId,
consentStatus = consent.status.toLowerCase(),
@ -504,7 +504,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats {
)
}
def createGetConsentResponseJson(createdConsent: Consent) : GetConsentResponseJson = {
def createGetConsentResponseJson(createdConsent: ConsentTrait) : GetConsentResponseJson = {
val jsonWebTokenAsJValue: Box[ConsentJWT] = JwtUtil.getSignedPayloadAsJson(createdConsent.jsonWebToken)
.map(parse(_).extract[ConsentJWT])
val access: ConsentAccessJson = jsonWebTokenAsJValue
@ -520,7 +520,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats {
)
}
def createStartConsentAuthorisationJson(consent: Consent, challenge: ChallengeTrait) : StartConsentAuthorisationJson = {
def createStartConsentAuthorisationJson(consent: ConsentTrait, challenge: ChallengeTrait) : StartConsentAuthorisationJson = {
StartConsentAuthorisationJson(
scaStatus = challenge.scaStatus.map(_.toString).getOrElse("None"),
pushMessage = "started", //TODO Not implement how to fill this.

View File

@ -3452,10 +3452,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
// All OBP REST end points start with /obp
def getObpApiRoot: String = s"$getServerUrl/obp"
// Get OAuth2 Authentication Server URL
def getOAuth2ServerUrl: String = getPropsValue("oauth2_server_url").openOr(MissingPropsValueAtThisInstance + "oauth2_server_url")
lazy val defaultBankId =
if (Props.mode == Props.RunModes.Test)
APIUtil.getPropsValue("defaultBank.bank_id", "DEFAULT_BANK_ID_NOT_SET_Test")

View File

@ -334,6 +334,8 @@ object Consent {
case _ =>
(Failure(ErrorMessages.UnknownError), Some(cc))
}
case _ =>
(Failure("Cannot add entitlements based on: " + consentAsJwt), Some(cc))
}
case _ =>
(Failure("Cannot create or get the user based on: " + consentAsJwt), Some(cc))
@ -421,13 +423,15 @@ object Consent {
case _ =>
(Failure(ErrorMessages.UnknownError), Some(cc))
}
case _ =>
(Failure("Cannot add entitlements based on: " + consentId), Some(cc))
}
case _ =>
(Failure("Cannot create or get the user based on: " + consentId), Some(cc))
}
}
def checkFrequencyPerDay(storedConsent: consent.Consent) = {
def checkFrequencyPerDay(storedConsent: consent.ConsentTrait) = {
def isSameDay(date1: Date, date2: Date): Boolean = {
val fmt = new SimpleDateFormat("yyyyMMdd")
fmt.format(date1).equals(fmt.format(date2))

View File

@ -213,7 +213,7 @@ object ErrorMessages {
val Oauth2JOSEException = "OBP-20207: Bad JSON Object Signing and Encryption (JOSE) exception. An internal JOSE exception was encountered. "
val Oauth2CannotMatchIssuerAndJwksUriException = "OBP-20208: Cannot match the issuer and JWKS URI at this server instance. "
val Oauth2TokenHaveNoConsumer = "OBP-20209: The token have no linked consumer. "
val Oauth2TokenMatchCertificateFail = "OBP-20210: The token linked with a different client certificate. "
val Oauth2TokenMatchCertificateFail = "OBP-20210: The token is linked with a different client certificate. "
val OneTimePasswordExpired = "OBP-20211: The One Time Password (OTP) has expired. "

View File

@ -1,12 +1,15 @@
package code.api.util
import java.io.File
import code.api.Constant.PARAM_LOCALE
import code.api.util.APIUtil.{getOAuth2ServerUrl, getObpApiRoot, getServerUrl}
import code.api.util.APIUtil.{getObpApiRoot, getServerUrl}
import code.api.util.ExampleValue.{accountIdExample, bankIdExample, customerIdExample, userIdExample}
import code.util.Helper.MdcLoggable
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
import net.liftweb.http.LiftRules
import scala.collection.mutable.ArrayBuffer
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
object Glossary extends MdcLoggable {
@ -3106,7 +3109,38 @@ object Glossary extends MdcLoggable {
|""".stripMargin)
private def getContentFromMarkdownFile(path: String): String = {
val source = scala.io.Source.fromFile(path)
val lines: String = try source.mkString finally source.close()
lines
.replaceAll("getServerUrl", getServerUrl)
.replaceAll("getObpApiRoot", getObpApiRoot)
}
private def getListOfFiles():List[File] = {
val dir= LiftRules.getResource("/")
.map(_.toURI.getPath
.replace("obp-api/src/main/webapp", "docs/glossary"))
val d = new File(dir.getOrElse(""))
if (d.exists && d.isDirectory) {
d.listFiles.filter(_.isFile).filter(_.getName.endsWith(".md")).toList
} else {
List[File]()
}
}
// Append all files from /OBP-API/docs/glossary as items
// File name is used as a title
// File content is used as a description
glossaryItems.appendAll(
getListOfFiles().map(file =>
GlossaryItem(
title = file.getName.replace(".md", "").replace("_", " "),
description = getContentFromMarkdownFile(file.getPath)
)
)
)
///////////////////////////////////////////////////////////////////
// NOTE! Some glossary items are generated in ExampleValue.scala
//////////////////////////////////////////////////////////////////

View File

@ -35,7 +35,7 @@ object TableAccountAccess {
.user_fk(permission.user.get)
.view_id(viewId)
.view_fk(viewFk)
.save()
.save
}
val isSuccessful = insertedRows.forall(_ == true)
val accountAccess = AccountAccess.findAll()

View File

@ -99,7 +99,7 @@ object MigrationOfAccountRoutings {
false // DB have the same routing
case Full(routing) =>
// only accountRoutingAddress is different.
routing.AccountRoutingAddress(accountRoutingAddress).save()
routing.AccountRoutingAddress(accountRoutingAddress).save
case _ =>
// query according unique index: UniqueIndex(BankId, AccountRoutingScheme, AccountRoutingAddress)
BankAccountRouting.find(By(BankAccountRouting.BankId, bankId),
@ -108,7 +108,7 @@ object MigrationOfAccountRoutings {
) match {
case Full(routing) =>
// only accountId is different
routing.AccountId(accountId).save()
routing.AccountId(accountId).save
case _ =>
// not exists corresponding routing in DB.
BankAccountRouting.create
@ -116,7 +116,7 @@ object MigrationOfAccountRoutings {
.AccountId(accountId)
.AccountRoutingScheme(accountRoutingScheme)
.AccountRoutingAddress(accountRoutingAddress)
.save()
.save
}
}
}

View File

@ -47,7 +47,7 @@ object TableRateLmiting {
.PerMonthCallLimit(consumer.perMonthCallLimit.get)
.FromDate(Date.from(oneDayAgo.toInstant()))
.ToDate(Date.from(oneYearInFuture.toInstant()))
.save()
.save
}
}
val isSuccessful = insertedRows.forall(_ == true)

View File

@ -58,7 +58,7 @@ object UpdateTableViewDefinition {
view <- views
accountAccess <- AccountAccess.find(By(AccountAccess.view_fk, view.id)).toList
} yield {
accountAccess.view_id(view.viewId.value).save()
accountAccess.view_id(view.viewId.value).save
}
val isSuccessful = views.forall(_.isSystem == false)

View File

@ -0,0 +1,3 @@
#What is mutual TLS (mTLS)?
Mutual TLS (mTLS) is a type of authentication in which the two parties in a connection authenticate each other using the TLS protocol.

View File

@ -9559,7 +9559,7 @@ trait APIMethods400 {
lazy val createJsonSchemaValidation: OBPEndpoint = {
case "management" :: "json-schema-validations" :: operationId :: Nil JsonPost _ -> _ => {
cc =>
val Some(httpBody): Option[String] = cc.httpBody
val httpBody: String = cc.httpBody.getOrElse("")
for {
(Full(u), callContext) <- SS.user
@ -9605,7 +9605,7 @@ trait APIMethods400 {
lazy val updateJsonSchemaValidation: OBPEndpoint = {
case "management" :: "json-schema-validations" :: operationId :: Nil JsonPut _ -> _ => {
cc =>
val Some(httpBody): Option[String] = cc.httpBody
val httpBody: String = cc.httpBody.getOrElse("")
for {
(Full(u), callContext) <- SS.user

View File

@ -1,7 +1,7 @@
package code.api.v5_1_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{apiCollectionJson400, apiCollectionsJson400, postApiCollectionJson400, revokedConsentJsonV310}
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{apiCollectionJson400, apiCollectionsJson400, apiInfoJson400, postApiCollectionJson400, revokedConsentJsonV310}
import code.api.util.APIUtil._
import code.api.util.ApiRole._
import code.api.util.ApiTag._
@ -16,7 +16,7 @@ import code.util.Helper
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model.BankId
import com.openbankproject.commons.util.ApiVersion
import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion}
import net.liftweb.common.Full
import net.liftweb.http.rest.RestHelper
@ -32,7 +32,7 @@ trait APIMethods510 {
class Implementations510 {
val implementedInApiVersion = ApiVersion.v5_1_0
val implementedInApiVersion: ScannedApiVersion = ApiVersion.v5_1_0
private val staticResourceDocs = ArrayBuffer[ResourceDoc]()
def resourceDocs = staticResourceDocs
@ -41,6 +41,34 @@ trait APIMethods510 {
val codeContext = CodeContext(staticResourceDocs, apiRelations)
staticResourceDocs += ResourceDoc(
root,
implementedInApiVersion,
"root",
"GET",
"/root",
"Get API Info (root)",
"""Returns information about:
|
|* API version
|* Hosted by information
|* Hosted at information
|* Energy source information
|* Git Commit""",
EmptyBody,
apiInfoJson400,
List(UnknownError, "no connector set"),
apiTagApi :: apiTagNewStyle :: Nil)
lazy val root : OBPEndpoint = {
case (Nil | "root" :: Nil) JsonGet _ => {
cc => Future {
JSONFactory510.getApiInfoJSON(implementedInApiVersion) -> HttpCode.`200`(cc.callContext)
}
}
}
staticResourceDocs += ResourceDoc(
getAllApiCollections,
implementedInApiVersion,

View File

@ -26,8 +26,61 @@
*/
package code.api.v5_1_0
import code.api.Constant
import code.api.util.APIUtil
import code.api.util.APIUtil.gitCommit
import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400}
import com.openbankproject.commons.util.ScannedApiVersion
case class APIInfoJsonV510(
version : String,
version_status: String,
git_commit : String,
stage : String,
connector : String,
hostname : String,
local_identity_provider : String,
hosted_by : HostedBy400,
hosted_at : HostedAt400,
energy_source : EnergySource400,
resource_docs_requires_role: Boolean
)
object JSONFactory510 {
def getApiInfoJSON(implementedInApiVersion: ScannedApiVersion) = {
val (apiVersion, apiVersionStatus) = (implementedInApiVersion, OBPAPI5_1_0.versionStatus)
val organisation = APIUtil.getPropsValue("hosted_by.organisation", "TESOBE")
val email = APIUtil.getPropsValue("hosted_by.email", "contact@tesobe.com")
val phone = APIUtil.getPropsValue("hosted_by.phone", "+49 (0)30 8145 3994")
val organisationWebsite = APIUtil.getPropsValue("organisation_website", "https://www.tesobe.com")
val hostedBy = new HostedBy400(organisation, email, phone, organisationWebsite)
val organisationHostedAt = APIUtil.getPropsValue("hosted_at.organisation", "")
val organisationWebsiteHostedAt = APIUtil.getPropsValue("hosted_at.organisation_website", "")
val hostedAt = HostedAt400(organisationHostedAt, organisationWebsiteHostedAt)
val organisationEnergySource = APIUtil.getPropsValue("energy_source.organisation", "")
val organisationWebsiteEnergySource = APIUtil.getPropsValue("energy_source.organisation_website", "")
val energySource = EnergySource400(organisationEnergySource, organisationWebsiteEnergySource)
val connector = APIUtil.getPropsValue("connector").openOrThrowException("no connector set")
val resourceDocsRequiresRole = APIUtil.getPropsAsBoolValue("resource_docs_requires_role", false)
APIInfoJsonV510(
version = apiVersion.vDottedApiVersion,
version_status = apiVersionStatus,
git_commit = gitCommit,
connector = connector,
hostname = Constant.HostName,
stage = System.getProperty("run.mode"),
local_identity_provider = Constant.localIdentityProvider,
hosted_by = hostedBy,
hosted_at = hostedAt,
energy_source = energySource,
resource_docs_requires_role = resourceDocsRequiresRole
)
}
}

View File

@ -79,7 +79,6 @@ object Connector extends SimpleInjector {
val nameToConnector: Map[String, () => Connector] = Map(
"mapped" -> lazyValue(LocalMappedConnector),
"akka_vDec2018" -> lazyValue(AkkaConnector_vDec2018),
"mongodb" -> lazyValue(LocalRecordConnector),
"kafka_vSept2018" -> lazyValue(KafkaMappedConnector_vSept2018),
"kafka_vMay2019" -> lazyValue(KafkaMappedConnector_vMay2019),
"rest_vMar2019" -> lazyValue(RestConnector_vMar2019),

View File

@ -114,8 +114,7 @@ import scala.util.{Random, Try}
object LocalMappedConnector extends Connector with MdcLoggable {
// override type AccountType = MappedBankAccount
val maxBadLoginAttempts = APIUtil.getPropsValue("max.bad.login.attempts") openOr "10"
val underlyingGuavaCache = CacheBuilder.newBuilder().maximumSize(10000L).build[String, Object]
implicit val scalaCache = ScalaCache(GuavaCache(underlyingGuavaCache))
val getTransactionsTTL = APIUtil.getPropsValue("connector.cache.ttl.seconds.getTransactions", "0").toInt * 1000 // Miliseconds
@ -1892,7 +1891,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
newAccountBalance <- Full(Helper.convertToSmallestCurrencyUnits(fromAccount.balance, currency) + Helper.convertToSmallestCurrencyUnits(amount, currency))
//Here is the `LocalMappedConnector`, once get this point, fromAccount must be a mappedBankAccount. So can use asInstanceOf....
_ <- tryo(fromAccount.asInstanceOf[MappedBankAccount].accountBalance(newAccountBalance).save()) ?~! UpdateBankAccountException
_ <- tryo(fromAccount.asInstanceOf[MappedBankAccount].accountBalance(newAccountBalance).save) ?~! UpdateBankAccountException
mappedTransaction <- tryo(MappedTransaction.create
.bank(fromAccount.bankId.value)
@ -2047,7 +2046,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
newAccountBalance <- Full(Helper.convertToSmallestCurrencyUnits(fromAccount.balance, currency) + Helper.convertToSmallestCurrencyUnits(amount, currency))
//Here is the `LocalMappedConnector`, once get this point, fromAccount must be a mappedBankAccount. So can use asInstanceOf....
_ <- tryo(fromAccount.asInstanceOf[MappedBankAccount].accountBalance(newAccountBalance).save()) ?~! UpdateBankAccountException
_ <- tryo(fromAccount.asInstanceOf[MappedBankAccount].accountBalance(newAccountBalance).save) ?~! UpdateBankAccountException
mappedTransaction <- tryo(MappedTransaction.create
//No matter which type (SANDBOX_TAN,SEPA,FREE_FORM,COUNTERPARTYE), always filled the following nine fields.
@ -5070,7 +5069,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
.Currency(reason.currency.getOrElse(""))
.DocumentNumber(reason.documentNumber.getOrElse(""))
.Description(reason.description.getOrElse(""))
.save()
.save
}
}

View File

@ -1,540 +0,0 @@
package code.bankconnectors
import java.util.{Date, TimeZone}
import code.api.util.ErrorMessages._
import code.api.util._
import code.management.ImporterAPI.ImporterTransaction
import code.metadata.counterparties.{Counterparties, Metadata, MongoCounterparties}
import code.model._
import code.model.dataAccess._
import code.util.Helper
import code.util.Helper.MdcLoggable
import com.mongodb.QueryBuilder
import com.openbankproject.commons.model._
import com.tesobe.model.UpdateBankAccount
import net.liftweb.common.{Box, Empty, Failure, Full}
import net.liftweb.json.Extraction
import net.liftweb.json.JsonAST.JValue
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.util.Helpers._
import org.bson.types.ObjectId
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model.enums.AccountRoutingScheme
import scala.collection.immutable.List
import scala.concurrent._
private object LocalRecordConnector extends Connector with MdcLoggable {
implicit override val nameOfConnector = LocalRecordConnector.getClass.getSimpleName
override def getBankLegacy(bankId : BankId, callContext: Option[CallContext]) =
getHostedBank(bankId).map(bank =>(bank, callContext))
//gets banks handled by this connector
override def getBanksLegacy(callContext: Option[CallContext]) =
Full(HostedBank.findAll, callContext)
override def getBankAccountLegacy(bankId : BankId, accountId : AccountId, callContext: Option[CallContext]) : Box[(BankAccount, Option[CallContext])] = {
for{
bank <- getHostedBank(bankId)
account <- bank.getAccount(accountId)
} yield (account,callContext)
}
override def getCounterpartyFromTransaction(bankId: BankId, accountId : AccountId, counterpartyID : String): Box[Counterparty] = {
/**
* In this implementation (for legacy reasons), the "otherAccountID" is actually the mongodb id of the
* "other account metadata" object.
*/
for{
objId <- tryo{ new ObjectId(counterpartyID) }
otherAccountmetadata <- {
//"otherAccountID" is actually the mongodb id of the other account metadata" object.
val query = QueryBuilder.
start("_id").is(objId)
.put("originalPartyBankId").is(bankId.value)
.put("originalPartyAccountId").is(accountId.value).get()
Metadata.find(query)
}
} yield{
val query = QueryBuilder
.start("obp_transaction.other_account.holder").is(otherAccountmetadata.holder.get)
// .put("obp_transaction.other_account.number").is(otherAccountmetadata.accountNumber.get)
.get()
val otherAccountFromTransaction : OBPAccount = OBPEnvelope.find(query) match {
case Full(envelope) => envelope.obp_transaction.get.other_account.get
case _ => {
logger.warn("no other account found")
OBPAccount.createRecord
}
}
createOtherBankAccount(bankId, accountId, otherAccountmetadata, otherAccountFromTransaction)
}
}
override def getCounterpartiesFromTransaction(bankId: BankId, accountId : AccountId) = {
/**
* In this implementation (for legacy reasons), the "otherAccountID" is actually the mongodb id of the
* "other account metadata" object.
*/
Full(Counterparties.counterparties.vend.getMetadatas(bankId, accountId).map(meta => {
//for legacy reasons some of the data about the "other account" are stored only on the transactions
//so we need first to get a transaction that match to have the rest of the data
val query = QueryBuilder
.start("obp_transaction.other_account.holder").is(meta.getCounterpartyName)
// .put("obp_transaction.other_account.number").is(meta.getAccountNumber)
.get()
val otherAccountFromTransaction : OBPAccount = OBPEnvelope.find(query) match {
case Full(envelope) => {
envelope.obp_transaction.get.other_account.get
}
case _ => {
logger.warn(s"envelope not found for other account ${meta.getCounterpartyId}")
OBPAccount.createRecord
}
}
createOtherBankAccount(bankId, accountId, meta, otherAccountFromTransaction)
}))
}
override def getTransactionsLegacy(bankId: BankId, accountId: AccountId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]) = {
logger.debug("getTransactions for " + bankId + "/" + accountId)
val transactions = for{
bank <- getHostedBank(bankId)
account <- bank.getAccount(accountId)
} yield {
updateAccountTransactions(bank, account)
account.envelopes(queryParams).map(createTransaction(_, account))
}
transactions.map( transactions => (transactions, callContext))
}
override def getTransactionLegacy(bankId: BankId, accountId : AccountId, transactionId : TransactionId, callContext: Option[CallContext])= {
for{
bank <- getHostedBank(bankId) ?~! s"Transaction not found: bank $bankId not found"
account <- bank.getAccount(accountId) ?~! s"Transaction not found: account $accountId not found"
envelope <- OBPEnvelope.find(account.transactionsForAccount.put("transactionId").is(transactionId.value).get)
} yield {
updateAccountTransactions(bank, account)
(createTransaction(envelope,account), callContext)
}
}
override protected def makePaymentImpl(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amt: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String): Box[TransactionId] = {
val fromTransAmt = -amt //from account balance should decrease
val toTransAmt = amt //to account balance should increase
//this is the transaction that gets attached to the account of the person making the payment
val createdFromTrans = saveNewTransaction(fromAccount, fromTransAmt, description)
// this creates the transaction that gets attached to the account of the person receiving the payment
// saveNewTransaction(toAccount, fromAccount, toTransAmt, description)
//assumes OBPEnvelope id is what gets used as the Transaction id in the API. If that gets changed, this needs to
//be updated (the tests should fail if it doesn't)
createdFromTrans.map(t => TransactionId(t.transactionId.get))
}
private def createTransaction(env: OBPEnvelope, theAccount: Account): Transaction = {
val transaction: OBPTransaction = env.obp_transaction.get
val otherAccount_ = transaction.other_account.get
val id = TransactionId(env.transactionId.get)
val uuid = id.value
//slight hack required: otherAccount id is, for legacy reasons, the mongodb id of its metadata object
//so we have to find that
val query = QueryBuilder.start("originalPartyBankId").is(theAccount.bankId.value).
put("originalPartyAccountId").is(theAccount.permalink.get).
put("accountNumber").is(otherAccount_.number.get).
put("holder").is(otherAccount_.holder.get).get
//it's a bit confusing what's going on here, as normally metadata should be automatically generated if
//it doesn't exist when an OtherBankAccount object is created. The issue here is that for legacy reasons
//otherAccount ids are mongo metadata ids, so the metadata needs to exist before we created the OtherBankAccount
//so that we know what id to give it. That's why there's a hardcoded dependency on MongoCounterparties.
val metadata = Metadata.find(query) match {
case Full(m) => m
case _ => MongoCounterparties.createMetadata(
theAccount.bankId,
theAccount.accountId,
otherAccount_.holder.get,
otherAccount_.number.get)
}
val otherAccount = new Counterparty(
counterpartyId = metadata.getCounterpartyId,
counterpartyName = otherAccount_.holder.get,
nationalIdentifier = otherAccount_.bank.get.national_identifier.get,
otherBankRoutingAddress = None,
otherAccountRoutingAddress = Some(otherAccount_.bank.get.IBAN.get),
thisAccountId = AccountId(otherAccount_.number.get),
thisBankId = BankId(otherAccount_.bank.get.name.get),
kind = otherAccount_.kind.get,
otherBankRoutingScheme = "",
otherAccountRoutingScheme="",
otherAccountProvider = "",
isBeneficiary = true
)
val transactionType = transaction.details.get.kind.get
val amount = transaction.details.get.value.get.amount.get
val currency = transaction.details.get.value.get.currency.get
val label = Some(transaction.details.get.label.get)
val startDate = transaction.details.get.posted.get
val finishDate = transaction.details.get.completed.get
val balance = transaction.details.get.new_balance.get.amount.get
new Transaction(
uuid,
id,
theAccount,
otherAccount,
transactionType,
amount,
currency,
label,
startDate,
finishDate,
balance)
}
private def saveNewTransaction(account : BankAccount, amount : BigDecimal, description : String) : Box[OBPEnvelope] = {
val oldBalance = account.balance
def saveAndUpdateAccountBalance(transactionJS : JValue, thisAccount : BankAccount) : Box[OBPEnvelope] = {
val envelope: Box[OBPEnvelope] = OBPEnvelope.envelopesFromJValue(transactionJS)
val account = thisAccount.asInstanceOf[Account]
if(envelope.isDefined) {
val e : OBPEnvelope = envelope.openOrThrowException(attemptedToOpenAnEmptyBox)
logger.debug(s"Updating current balance for ${account.bankName} / ${account.accountNumber} / ${account.accountType}")
account.accountBalance(e.obp_transaction.get.details.get.new_balance.get.amount.get).save(true)
logger.debug("Saving new transaction")
Full(e.save(true))
} else {
Failure("couldn't save transaction")
}
}
for {
// otherBank <- Connector.connector.vend.getBank(otherAccount.bankId) ?~! "no other bank found"
transTime <- Full(now)
//mongodb/the lift mongo thing wants a literal Z in the timestamp, apparently
envJsonDateFormat = {
val simpleDateFormat = APIUtil.DateWithMsFormat
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"))
simpleDateFormat
}
envJson =
"obp_transaction" ->
("this_account" ->
// ("holder" -> account.owners.headOption.map(_.name).getOrElse("")) ~ //TODO: this is rather fragile...
("number" -> account.number) ~
("kind" -> account.accountType) ~
("bank" ->
("IBAN" -> account.accountRoutings.find(_.scheme == AccountRoutingScheme.IBAN.toString).map(_.address).getOrElse("")) ~
("national_identifier" -> account.nationalIdentifier) ~
("name" -> account.bankId.value))) ~
// ("other_account" ->
//// ("holder" -> otherAccount.accountHolder) ~
//// ("number" -> otherAccount.number) ~
//// ("kind" -> otherAccount.accountType) ~
// ("bank" ->
// ("IBAN" -> "") ~
//// ("national_identifier" -> otherBank.nationalIdentifier) ~
//// ("name" -> otherBank.fullName))) ~
("details" ->
("type_en" -> "") ~
("type_de" -> "") ~
("posted" ->
("$dt" -> envJsonDateFormat.format(transTime))
) ~
("completed" ->
("$dt" -> envJsonDateFormat.format(transTime))
) ~
("new_balance" ->
("currency" -> account.currency) ~
("amount" -> (oldBalance + amount).toString)) ~
("value" ->
("currency" -> account.currency) ~
("amount" -> amount.toString)))
saved <- saveAndUpdateAccountBalance(envJson, account)
} yield {
saved
}
}
/**
* Checks if the last update of the account was made more than one hour ago.
* if it is the case we put a message in the message queue to ask for
* transactions updates
*
* It will be used each time we fetch transactions from the DB. But the test
* is performed in a different thread.
*/
private def updateAccountTransactions(bank: HostedBank, account: Account): Unit = {
Future {
val useMessageQueue = APIUtil.getPropsAsBoolValue("messageQueue.updateBankAccountsTransaction", false)
val outDatedTransactions = now after time(account.accountLastUpdate.get.getTime + hours(APIUtil.getPropsAsIntValue("messageQueue.updateTransactionsInterval", 1)))
if(outDatedTransactions && useMessageQueue) {
UpdatesRequestSender.sendMsg(UpdateBankAccount(account.accountNumber.get, bank.national_identifier.get))
}
}
}
private def createOtherBankAccount(originalPartyBankId: BankId, originalPartyAccountId: AccountId,
otherAccount : CounterpartyMetadata, otherAccountFromTransaction : OBPAccount) : Counterparty = {
new Counterparty(
counterpartyId = otherAccount.getCounterpartyId,
counterpartyName = otherAccount.getCounterpartyName,
nationalIdentifier = otherAccountFromTransaction.bank.get.national_identifier.get,
otherBankRoutingAddress = None,
otherAccountRoutingAddress = Some(otherAccountFromTransaction.bank.get.IBAN.get),
thisAccountId = AccountId(otherAccountFromTransaction.number.get),
thisBankId = BankId(otherAccountFromTransaction.bank.get.name.get),
kind = "",
otherBankRoutingScheme = "",
otherAccountRoutingScheme="",
otherAccountProvider = "",
isBeneficiary = true
)
}
private def getHostedBank(bankId : BankId) : Box[HostedBank] = {
HostedBank.find("permalink", bankId.value) ?~ {"bank " + bankId + " not found"}
}
//Need to pass in @hostedBank because the Account model doesn't have any references to BankId, just to the mongo id of the Bank object (which itself does have the bank id)
private def createAccount(hostedBank : HostedBank, accountId : AccountId, accountNumber: String,
accountType: String, accountLabel: String, currency : String, initialBalance : BigDecimal, holderName : String) : BankAccount = {
import net.liftweb.mongodb.BsonDSL._
Account.find(
(Account.accountNumber.name -> accountNumber)~
(Account.bankID.name -> hostedBank.id.get)
) match {
case Full(bankAccount) => {
logger.debug(s"account with number ${bankAccount.accountNumber} at bank ${hostedBank.bankId} already exists. No need to create a new one.")
bankAccount
}
case _ => {
logger.debug("creating account record ")
val bankAccount =
Account
.createRecord
.accountBalance(initialBalance)
.holder(holderName)
.accountNumber(accountNumber)
.kind(accountType)
.accountLabel(accountLabel)
.accountName("")
.permalink(accountId.value)
.bankID(hostedBank.id.get)
.accountCurrency(currency)
.accountIban("")
.accountLastUpdate(now)
.save(true)
bankAccount
}
}
}
//creates a bank account (if it doesn't exist) and creates a bank (if it doesn't exist)
override def createBankAndAccount(
bankName: String,
bankNationalIdentifier: String,
accountNumber: String,
accountType: String,
accountLabel: String,
currency: String,
accountHolderName: String,
branchId: String,
accountRoutingScheme: String,
accountRoutingAddress: String
) = {
// TODO: use a more unique id for the long term
val hostedBank = {
// TODO: use a more unique id for the long term
HostedBank.find(HostedBank.national_identifier.name, bankNationalIdentifier) match {
case Full(b)=> {
logger.debug(s"bank ${b.name} found")
b
}
case _ =>{
//TODO: if name is empty use bank id as name alias
//TODO: need to handle the case where generatePermalink returns a permalink that is already used for another bank
logger.debug(s"creating HostedBank")
HostedBank
.createRecord
.name(bankName)
.alias(bankName)
.permalink(Helper.generatePermalink(bankName))
.national_identifier(bankNationalIdentifier)
.save(true)
}
}
}
val createdAccount = createAccount(hostedBank, AccountId(APIUtil.generateUUID()),
accountNumber, accountType, accountLabel, currency, BigDecimal("0.00"), accountHolderName)
Full((hostedBank, createdAccount))
}
//for sandbox use -> allows us to check if we can generate a new test account with the given number
override def accountExists(bankId: BankId, accountNumber: String) = {
import net.liftweb.mongodb.BsonDSL._
getHostedBank(bankId).map(_.id.get) match {
case Full(mongoId) =>
Full(Account.count((Account.accountNumber.name -> accountNumber) ~ (Account.bankID.name -> mongoId)) > 0)
case _ =>
logger.warn("tried to check account existence for an account at a bank that doesn't exist")
Full(false)
}
}
override def removeAccount(bankId: BankId, accountId: AccountId) = {
import net.liftweb.mongodb.BsonDSL._
for {
account <- Account.find((Account.bankID.name -> bankId.value) ~ (Account.accountId.value -> accountId.value)) ?~
s"No account found with number ${accountId} at bank with id ${bankId}: could not save envelope"
} yield {
account.delete_!
}
Full(false)
/* account
} match {
case Full(acc) => acc.
}
*/
}
//creates a bank account for an existing bank, with the appropriate values set
override def createSandboxBankAccount(
bankId: BankId,
accountId: AccountId,
accountNumber: String,
accountType: String,
accountLabel: String,
currency: String,
initialBalance: BigDecimal,
accountHolderName: String,
branchId: String,
accountRoutings: List[AccountRouting]
): Box[BankAccount] = {
HostedBank.find(bankId) match {
case Full(b) => Full(createAccount(b, accountId, accountNumber, accountType, accountLabel, currency, initialBalance, accountHolderName))
case _ => Failure(s"Bank with id ${bankId.value} not found. Cannot create account at non-existing bank.")
}
}
//used by transaction import api call to check for duplicates
override def getMatchingTransactionCount(bankNationalIdentifier : String, accountNumber : String, amount: String, completed: Date, otherAccountHolder: String) = {
val baseQuery = QueryBuilder.start("obp_transaction.details.value.amount")
.is(amount)
.put("obp_transaction.details.completed")
.is(completed)
.put("obp_transaction.this_account.bank.national_identifier")
.is(bankNationalIdentifier)
.put("obp_transaction.this_account.number")
.is(accountNumber)
//this is refactored legacy code, and it seems the empty account holder check had to do with potentially missing
//fields in the db. not sure if this is still required.
if(otherAccountHolder.isEmpty){
def emptyHolderOrEmptyString(holder: Box[String]): Boolean = {
holder match {
case Full(s) => s.isEmpty
case _ => true
}
}
val partialMatches = OBPEnvelope.findAll(baseQuery.get())
Full(partialMatches.filter(e => {
emptyHolderOrEmptyString(e.obp_transaction.get.other_account.get.holder.valueBox)
}).size)
}
else{
val qry = baseQuery.put("obp_transaction.other_account.holder").is(otherAccountHolder).get
val partialMatches = OBPEnvelope.count(qry)
Full(partialMatches.toInt)//icky
}
}
//used by transaction import api
override def createImportedTransaction(transaction: ImporterTransaction): Box[Transaction] = {
import net.liftweb.mongodb.BsonDSL._
implicit val formats = CustomJsonFormats.losslessFormats
val asJValue = Extraction.decompose(transaction)
for {
env <- OBPEnvelope.envelopesFromJValue(asJValue)
nationalIdentifier = transaction.obp_transaction.this_account.bank.national_identifier
bank <- HostedBank.find(HostedBank.national_identifier.name -> nationalIdentifier) ?~
s"No bank found with national identifier ${nationalIdentifier} could not save envelope"
accountNumber = transaction.obp_transaction.this_account.number
account <- Account.find((Account.bankID.name -> bank.id.get) ~ (Account.accountNumber.name -> accountNumber)) ?~
s"No account found with number ${accountNumber} at bank with id ${bank.bankId}: could not save envelope"
savedEnv <- env.saveTheRecord() ?~ "Could not save envelope"
} yield {
createTransaction(savedEnv, account)
}
}
//used by the transaction import api
override def updateAccountBalance(bankId: BankId, accountId: AccountId, newBalance: BigDecimal) = {
getBankAccountOld(bankId, accountId).map(_.asInstanceOf[Account]) match {
case Full(acc) =>
acc.accountBalance(newBalance).saveTheRecord().isDefined
Full(true)
case _ =>
Full(false)
}
}
override def setBankAccountLastUpdated(bankNationalIdentifier: String, accountNumber : String, updateDate: Date) = {
Account.find(
(Account.accountNumber.name -> accountNumber)~
(Account.nationalIdentifier -> bankNationalIdentifier)
) match {
case Full(acc) => Full(acc.accountLastUpdate(updateDate).saveTheRecord().isDefined)
case _ => logger.warn("can't set bank account.lastUpdated because the account was not found"); Full(false)
}
}
override def updateAccountLabel(bankId: BankId, accountId: AccountId, label: String) = {
getBankAccountOld(bankId, accountId).map(_.asInstanceOf[Account]) match {
case Full(acc) =>
acc.accountLabel(label).saveTheRecord().isDefined
Full(true)
case _ =>
Full(false)
}
}
}

View File

@ -110,7 +110,7 @@ object MappedPhysicalCardProvider extends PhysicalCardProvider {
.card(v)
.saveMe()
v.mPinResets += pin
v.save()
v.save
}
}
case _ => // There is no enough information to set foreign key
@ -217,7 +217,7 @@ object MappedPhysicalCardProvider extends PhysicalCardProvider {
.card(v)
.saveMe()
v.mPinResets += pin
v.save()
v.save
}
}
case _ => // There is no enough information to set foreign key

View File

@ -33,10 +33,10 @@ trait ConsentProvider {
frequencyPerDay: Int,
combinedServiceIndicator: Boolean,
apiStandard: Option[String],
apiVersion: Option[String]): Box[Consent]
apiVersion: Option[String]): Box[ConsentTrait]
def updateBerlinGroupConsent(
consentId: String,
usesSoFarTodayCounter: Int): Box[Consent]
usesSoFarTodayCounter: Int): Box[ConsentTrait]
def saveUKConsent(
user: Option[User],
@ -49,10 +49,10 @@ trait ConsentProvider {
transactionToDateTime: Date,
apiStandard: Option[String],
apiVersion: Option[String]
): Box[Consent]
): Box[ConsentTrait]
}
trait Consent {
trait ConsentTrait {
def consentId: String
def userId: String
def secret: String

View File

@ -223,7 +223,7 @@ object MappedConsentProvider extends ConsentProvider {
}
}
class MappedConsent extends Consent with LongKeyedMapper[MappedConsent] with IdPK with CreatedUpdated {
class MappedConsent extends ConsentTrait with LongKeyedMapper[MappedConsent] with IdPK with CreatedUpdated {
def getSingleton = MappedConsent

View File

@ -318,7 +318,7 @@ object MappedCustomerProvider extends CustomerProvider with MdcLoggable {
for {
customer <- MappedCustomer.findAll(NullRef(MappedCustomer.mCustomerId))++ MappedCustomer.findAll(By(MappedCustomer.mCustomerId, ""))
} yield {
customer.mCustomerId(APIUtil.generateUUID()).save()
customer.mCustomerId(APIUtil.generateUUID()).save
}
}.forall(_ == true)

View File

@ -69,7 +69,7 @@ object MappedDynamicEntityProvider extends DynamicEntityProvider with CustomJson
.HasPersonalEntity(dynamicEntity.hasPersonalEntity)
.saveMe()
} catch {
case e =>
case e : Throwable =>
logger.error("Create or Update DynamicEntity fail.", e)
throw e
}

View File

@ -10,7 +10,7 @@ import net.liftweb.util.Helpers._
object LoginAttempt extends MdcLoggable {
val maxBadLoginAttempts = APIUtil.getPropsValue("max.bad.login.attempts") openOr "5"
def maxBadLoginAttempts = APIUtil.getPropsValue("max.bad.login.attempts") openOr "5"
def incrementBadLoginAttempts(username: String, provider: String): Unit = {
username.isEmpty() match {
@ -37,7 +37,7 @@ object LoginAttempt extends MdcLoggable {
.Provider(provider)
.mLastFailureDate(now)
.mBadAttemptsSinceLastSuccessOrReset(1) // Start with 1
.save()
.save
logger.debug(s"incrementBadLoginAttempts created loginAttempt")
}

View File

@ -74,7 +74,7 @@ object MappedMeetingProvider extends MeetingProvider {
.mStatus(invitee.status)
.saveMe()
createdMeeting.mInvitees += meetingInvitee
createdMeeting.save()
createdMeeting.save
}} ?~! ErrorMessages.CreateMeetingInviteeException
} yield {
createdMeeting

View File

@ -1,81 +0,0 @@
package code.metadata.comments
import code.model._
import java.util.Date
import code.util.Helper.MdcLoggable
import net.liftweb.common.{Box, Full}
import org.bson.types.ObjectId
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{LongField, StringField}
private object MongoTransactionComments extends Comments {
def getComments(bankId : BankId, accountId : AccountId, transactionId : TransactionId)(viewId : ViewId) : List[Comment] = {
OBPComment.findAll(bankId, accountId, transactionId, viewId)
}
def addComment(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserPrimaryKey, viewId : ViewId, text : String, datePosted : Date) : Box[Comment] = {
OBPComment.createRecord.userId(userId.value).
transactionId(transactionId.value).
accountId(accountId.value).
bankId(bankId.value).
textField(text).
date(datePosted).
forView(viewId.value).saveTheRecord()
}
def deleteComment(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(commentId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPComment.delete(OBPComment.getFindQuery(bankId, accountId, transactionId, commentId))
//we don't have any useful information here so just assume it worked
Full(true)
}
def bulkDeleteComments(bankId: BankId, accountId: AccountId): Boolean = ???
def bulkDeleteCommentsOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId) : Boolean = ???
}
private class OBPComment private() extends MongoRecord[OBPComment] with ObjectIdPk[OBPComment] with Comment {
def meta = OBPComment
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
def postedBy = UserX.findByResourceUserId(userId.get)
def viewId = ViewId(forView.get)
def text = textField.get
def datePosted = date.get
def id_ = id.get.toString
def replyToID = replyTo.get
object userId extends LongField(this)
object forView extends StringField(this, 255)
object textField extends StringField(this, 255)
object date extends DateField(this)
object replyTo extends StringField(this,255)
}
private object OBPComment extends OBPComment with MongoMetaRecord[OBPComment] with MdcLoggable {
def findAll(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : List[OBPComment] = {
val query = QueryBuilder.
start("bankId").is(bankId.value).
put("accountId").is(accountId.value).
put("transactionId").is(transactionId.value).
put("forView").is(viewId.value).get
findAll(query)
}
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, commentId : String) : DBObject = {
//in theory commentId should be enough as we're just using the mongoId
QueryBuilder.start("_id").is(new ObjectId(commentId)).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}

View File

@ -290,27 +290,27 @@ object MapperCounterparties extends Counterparties with MdcLoggable {
}
override def addPublicAlias(counterpartyId : String, alias: String): Box[Boolean] = {
getCounterpartyMetadata(counterpartyId).map(_.publicAlias(alias).save())
getCounterpartyMetadata(counterpartyId).map(_.publicAlias(alias).save)
}
override def addPrivateAlias(counterpartyId : String, alias: String): Box[Boolean] = {
getCounterpartyMetadata(counterpartyId).map(_.privateAlias(alias).save())
getCounterpartyMetadata(counterpartyId).map(_.privateAlias(alias).save)
}
override def addURL(counterpartyId : String, url: String): Box[Boolean] = {
getCounterpartyMetadata(counterpartyId).map(_.url(url).save())
getCounterpartyMetadata(counterpartyId).map(_.url(url).save)
}
override def addImageURL(counterpartyId : String, url: String): Box[Boolean] = {
getCounterpartyMetadata(counterpartyId).map(_.imageUrl(url).save())
getCounterpartyMetadata(counterpartyId).map(_.imageUrl(url).save)
}
override def addOpenCorporatesURL(counterpartyId : String, url: String): Box[Boolean] = {
getCounterpartyMetadata(counterpartyId).map(_.openCorporatesUrl(url).save())
getCounterpartyMetadata(counterpartyId).map(_.openCorporatesUrl(url).save)
}
override def addMoreInfo(counterpartyId : String, moreInfo: String): Box[Boolean] = {
getCounterpartyMetadata(counterpartyId).map(_.moreInfo(moreInfo).save())
getCounterpartyMetadata(counterpartyId).map(_.moreInfo(moreInfo).save)
}
override def addPhysicalLocation(counterpartyId : String, userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double): Box[Boolean] = {
@ -372,7 +372,7 @@ class MappedCounterpartyMetadata extends CounterpartyMetadata with LongKeyedMapp
private def trySave(f : => Any) : Boolean =
tryo{
f
save()
save
}.getOrElse(false)
private def setWhere(whereTag : Box[MappedCounterpartyWhereTag])

View File

@ -1,182 +0,0 @@
package code.metadata.counterparties
import java.util.Date
import code.api.util.CallContext
import code.model._
import code.util.Helper.MdcLoggable
import com.mongodb.QueryBuilder
import com.openbankproject.commons.model._
import net.liftweb.common.{Box, Empty, Full}
import net.liftweb.util.Helpers.tryo
import org.bson.types.ObjectId
object MongoCounterparties extends Counterparties with MdcLoggable {
def getMetadatas(originalPartyBankId: BankId, originalPartyAccountId : AccountId) : List[CounterpartyMetadata] = {
val query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).get
Metadata.findAll(query)
}
def getMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, counterpartyMetadataId : String) : Box[CounterpartyMetadata] = {
/**
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
*/
for {
objId <- tryo { new ObjectId(counterpartyMetadataId) }
query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).
put("_id").is(objId).get()
m <- Metadata.find(query)
} yield m
}
def deleteMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String): Box[Boolean] = Empty
def getOrCreateMetadata(bankId: BankId, accountId : AccountId, counterpartyId:String, counterpartyName:String) : Box[CounterpartyMetadata] = {
/**
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
*/
val existing = getMetadata(bankId, accountId, counterpartyId)
val metadata = existing match {
case Full(m) => m
case _ => createMetadata(bankId, accountId, counterpartyName, counterpartyId)
}
Full(metadata)
}
/**
* This only exists for OBPEnvelope. Avoid using it for any other reason outside of this class
*/
def createMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherAccountHolder : String, counterpartyId : String) : Metadata = {
//create it
if(otherAccountHolder.isEmpty){
logger.info("other account holder is Empty. creating a metadata record with private alias")
//no holder name, nothing to hide, so we don't need to create a public alias
Metadata
.createRecord
.counterpartyId(counterpartyId)
.originalPartyBankId(originalPartyBankId.value)
.originalPartyAccountId(originalPartyAccountId.value)
// .accountNumber(otherAccountNumber)
.holder("")
.save(true)
} else {
Metadata.createRecord.
counterpartyId(counterpartyId).
originalPartyBankId(originalPartyBankId.value).
originalPartyAccountId(originalPartyAccountId.value).
holder(otherAccountHolder).
// accountNumber(otherAccountNumber).
publicAlias(newPublicAliasName(originalPartyBankId, originalPartyAccountId)).save(true)
}
}
/**
* Generates a new alias name that is guaranteed not to collide with any existing public alias names
* for the account in question
*/
def newPublicAliasName(originalPartyBankId : BankId, originalPartyAccountId : AccountId): String = {
import scala.util.Random
val firstAliasAttempt = "ALIAS_" + Random.nextLong().toString.take(6)
/**
* Returns true if @publicAlias is already the name of a public alias within @account
*/
def isDuplicate(publicAlias: String) = {
val query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).get()
Metadata.findAll(query).exists(m => {
m.publicAlias.get == publicAlias
})
}
/**
* Appends things to @publicAlias until it a unique public alias name within @account
*/
def appendUntilUnique(publicAlias: String): String = {
val newAlias = publicAlias + Random.nextLong().toString.take(1)
if (isDuplicate(newAlias)) appendUntilUnique(newAlias)
else newAlias
}
if (isDuplicate(firstAliasAttempt)) appendUntilUnique(firstAliasAttempt)
else firstAliasAttempt
}
override def getCounterparty(counterpartyId : String): Box[CounterpartyTrait] = Empty
override def deleteCounterparty(counterpartyId : String): Box[Boolean] = Empty
override def getCounterpartyByIban(iban : String): Box[CounterpartyTrait] = Empty
override def getCounterpartyByIbanAndBankAccountId(iban : String, bankId: BankId, accountId: AccountId): Box[CounterpartyTrait] = Empty
override def getCounterpartyByRoutings(
otherBankRoutingScheme: String,
otherBankRoutingAddress: String,
otherBranchRoutingScheme: String,
otherBranchRoutingAddress: String,
otherAccountRoutingScheme: String,
otherAccountRoutingAddress: String
): Box[CounterpartyTrait] = Empty
override def getCounterpartyBySecondaryRouting(
otherAccountSecondaryRoutingScheme: String,
otherAccountSecondaryRoutingAddress: String
): Box[CounterpartyTrait] = Empty
override def createCounterparty(
createdByUserId: String,
thisBankId: String,
thisAccountId: String,
thisViewId: String,
name: String,
otherAccountRoutingScheme: String,
otherAccountRoutingAddress: String,
otherBankRoutingScheme: String,
otherBankRoutingAddress: String,
otherBranchRoutingScheme: String,
otherBranchRoutingAddress: String,
isBeneficiary: Boolean,
otherAccountSecondaryRoutingScheme: String,
otherAccountSecondaryRoutingAddress: String,
description: String,
currency: String,
bespoke: List[CounterpartyBespoke]
): Box[CounterpartyTrait] = Empty
override def checkCounterpartyExists(
name: String,
thisBankId: String,
thisAccountId: String,
thisViewId: String
): Box[CounterpartyTrait] = Empty
override def getCounterparties(thisBankId: BankId, thisAccountId: AccountId, viewId: ViewId): Box[List[CounterpartyTrait]] = ???
override def addPublicAlias(counterpartyId : String, alias: String): Box[Boolean] = ???
override def addPrivateAlias(counterpartyId : String, alias: String): Box[Boolean] = ???
override def addURL(counterpartyId : String, url: String): Box[Boolean] = ???
override def addImageURL(counterpartyId : String, imageUrl: String): Box[Boolean] = ???
override def addOpenCorporatesURL(counterpartyId : String, url: String): Box[Boolean] = ???
override def addMoreInfo(counterpartyId : String, moreInfo: String): Box[Boolean] = ???
override def addPhysicalLocation(counterpartyId : String, userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double): Box[Boolean] = ???
override def addCorporateLocation(counterpartyId : String, userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double): Box[Boolean] = ???
override def deletePhysicalLocation(counterpartyId : String): Box[Boolean] = ???
override def deleteCorporateLocation(counterpartyId : String): Box[Boolean] = ???
override def getCorporateLocation(counterpartyId : String): Box[GeoTag] = ???
override def getPhysicalLocation(counterpartyId : String): Box[GeoTag] = ???
override def getOpenCorporatesURL(counterpartyId : String): Box[String] = ???
override def getImageURL(counterpartyId : String): Box[String] = ???
override def getUrl(counterpartyId : String): Box[String] = ???
override def getMoreInfo(counterpartyId : String): Box[String] = ???
override def getPublicAlias(counterpartyId : String): Box[String] = ???
override def getPrivateAlias(counterpartyId : String): Box[String] = ???
override def bulkDeleteAllCounterparties(): Box[Boolean] = ???
}

View File

@ -1,156 +0,0 @@
package code.metadata.counterparties
import code.model.UserX
import net.liftweb.mongodb.record.{BsonMetaRecord, BsonRecord, MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.ObjectIdPk
import net.liftweb.record.field.StringField
import com.openbankproject.commons.model.{CounterpartyMetadata, GeoTag, UserPrimaryKey}
//TODO: this should be private
class Metadata private() extends CounterpartyMetadata with MongoRecord[Metadata] with ObjectIdPk[Metadata] {
import net.liftweb.mongodb.record.field.BsonRecordField
import java.util.Date
def meta = Metadata
//originalPartyBankId and originalPartyAccountId are used to identify the account
//which has the counterparty this metadata is associated with
object originalPartyBankId extends StringField(this, 100)
object originalPartyAccountId extends StringField(this, 100)
object counterpartyId extends StringField(this,100)
object holder extends StringField(this, 255)
// object accountNumber extends StringField(this, 100)
object publicAlias extends StringField(this, 100)
object privateAlias extends StringField(this, 100)
object moreInfo extends StringField(this, 100)
object url extends StringField(this, 100)
object imageUrl extends StringField(this, 100)
object openCorporatesUrl extends StringField(this, 100) {
override def optional_? = true
}
object corporateLocation extends BsonRecordField(this, OBPGeoTag)
object physicalLocation extends BsonRecordField(this, OBPGeoTag)
def addCorporateLocationFn(userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
val newTag = OBPGeoTag.createRecord.
userId(userId.value).
date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude)
corporateLocation(newTag).saveTheRecord()
true
}
def deleteCorporateLocationFn : Boolean = {
corporateLocation.clear
this.saveTheRecord()
true
}
def addPhysicalLocationFn(userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
val newTag = OBPGeoTag.createRecord.
userId(userId.value).
date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude)
physicalLocation(newTag).saveTheRecord()
true
}
def deletePhysicalLocationFn : Boolean = {
physicalLocation.clear
this.saveTheRecord()
true
}
private def locationTag(loc: OBPGeoTag): Option[GeoTag]={
if(loc.longitude==0 && loc.latitude==0)
None
else
Some(loc)
}
override def getCounterpartyId = counterpartyId.get
override def getCounterpartyName = holder.get
// override def getAccountNumber = accountNumber.get
override def getUrl = url.get
override def getCorporateLocation = locationTag(corporateLocation.get)
override def getPhysicalLocation = locationTag(physicalLocation.get)
override val deleteCorporateLocation = deleteCorporateLocationFn _
override val deletePhysicalLocation = deletePhysicalLocationFn _
override def getPrivateAlias = privateAlias.get
override def getPublicAlias = publicAlias.get
override def getMoreInfo = moreInfo.get
override def getImageURL: String = imageUrl.get
override val addPrivateAlias: (String) => Boolean = (alias => {
privateAlias(alias).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addURL: (String) => Boolean = (text => {
url(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addPhysicalLocation: (UserPrimaryKey, Date, Double, Double) => Boolean = addPhysicalLocationFn _
override val addCorporateLocation: (UserPrimaryKey, Date, Double, Double) => Boolean = addCorporateLocationFn _
override val addMoreInfo: (String) => Boolean = (text => {
moreInfo(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override def getOpenCorporatesURL: String = openCorporatesUrl.get
override val addPublicAlias: (String) => Boolean = (alias => {
publicAlias(alias).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addOpenCorporatesURL: (String) => Boolean = (text => {
openCorporatesUrl(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addImageURL: (String) => Boolean = (text => {
imageUrl(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
}
//TODO: this should be private
object Metadata extends Metadata with MongoMetaRecord[Metadata]
class OBPGeoTag private() extends BsonRecord[OBPGeoTag] with GeoTag {
import com.openbankproject.commons.model.User
import net.liftweb.record.field.{DoubleField, LongField}
import net.liftweb.mongodb.record.field.DateField
def meta = OBPGeoTag
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object date extends DateField(this)
object geoLongitude extends DoubleField(this,0)
object geoLatitude extends DoubleField(this,0)
override def datePosted = date.get
override def postedBy = UserX.findByResourceUserId(userId.get)
override def longitude = geoLongitude.get
override def latitude = geoLatitude.get
}
//TODO: this should be private
object OBPGeoTag extends OBPGeoTag with BsonMetaRecord[OBPGeoTag]

View File

@ -1,78 +0,0 @@
package code.metadata.narrative
import net.liftweb.common.Full
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.ObjectIdPk
import net.liftweb.record.field.StringField
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model.{AccountId, BankId, TransactionId}
private object MongoTransactionNarrative extends Narrative {
def getNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)() : String = {
OBPNarrative.find(OBPNarrative.getFindQuery(bankId, accountId, transactionId)) match {
case Full(n) => n.narrative.get
case _ => ""
}
}
def setNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(narrative: String) : Boolean = {
val findQuery = OBPNarrative.getFindQuery(bankId, accountId, transactionId)
if(narrative.isEmpty) {
//if we're setting the value of the narrative to "" then we can just delete it
//use delete with find query to avoid concurrency issues
OBPNarrative.delete(findQuery)
} else {
//avoiding upsert for now as it seemed to behave a little strangely
val found = OBPNarrative.find(findQuery)
found match {
case Full(f) => f.narrative(narrative).save(true)
case _ => {
OBPNarrative.createRecord
.transactionId(transactionId.value)
.accountId(accountId.value)
.bankId(bankId.value)
.narrative(narrative).save(true)
}
}
}
//we don't have any useful information here so just assume it worked
true
}
override def bulkDeleteNarrativeOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId): Boolean = ???
override def bulkDeleteNarratives(bankId: BankId, accountId: AccountId): Boolean = ???
}
private class OBPNarrative private() extends MongoRecord[OBPNarrative] with ObjectIdPk[OBPNarrative] {
def meta = OBPNarrative
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object narrative extends StringField(this, 255)
}
private object OBPNarrative extends OBPNarrative with MongoMetaRecord[OBPNarrative] {
def init = createIndex((transactionId.name -> 1) ~ (accountId.name -> 1) ~ (bankId.name -> 1), true)
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId) : DBObject = {
QueryBuilder.start("bankId").is(bankId.value).put("accountId").is(accountId.value).put("transactionId").is(transactionId.value).get
}
}
object OBPNarrativeInit {
def init = OBPNarrative.init
}

View File

@ -1,96 +0,0 @@
package code.metadata.tags
import code.model._
import java.util.Date
import code.util.Helper
import net.liftweb.common.{Box, Full}
import org.bson.types.ObjectId
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{LongField, StringField}
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
private object MongoTransactionTags extends Tags {
def getTags(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : List[TransactionTag] = {
OBPTag.findAll(bankId, accountId, transactionId, viewId)
}
def getTagsOnAccount(bankId : BankId, accountId : AccountId)(viewId : ViewId) : List[TransactionTag] = {
OBPTag.findAll(bankId, accountId, TransactionId(""), viewId)
}
def addTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = {
OBPTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
transactionId(transactionId.value).
userId(userId.value).
forView(viewId.value).
tag(tagText).
date(datePosted).saveTheRecord()
}
def addTagOnAccount(bankId : BankId, accountId : AccountId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = {
OBPTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
userId(userId.value).
forView(viewId.value).
tag(tagText).
date(datePosted).saveTheRecord()
}
def deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(tagId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPTag.delete(OBPTag.getFindQuery(bankId, accountId, transactionId, tagId))
//we don't have any useful information here so just assume it worked
Full(true)
}
def deleteTagOnAccount(bankId : BankId, accountId : AccountId)(tagId : String) : Box[Boolean] = {
deleteTag(bankId, accountId, TransactionId(""))(tagId)
}
def bulkDeleteTags(bankId: BankId, accountId: AccountId): Boolean = ???
def bulkDeleteTagsOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId) : Boolean = ???
}
private class OBPTag private() extends MongoRecord[OBPTag] with ObjectIdPk[OBPTag] with TransactionTag {
def meta = OBPTag
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object forView extends StringField(this, 255)
object tag extends StringField(this, 255)
object date extends DateField(this)
def id_ = id.get.toString
def datePosted = date.get
def postedBy = UserX.findByResourceUserId(userId.get)
def viewId = ViewId(forView.get)
def value = tag.get
}
private object OBPTag extends OBPTag with MongoMetaRecord[OBPTag] {
def findAll(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : List[OBPTag] = {
val query = QueryBuilder.
start("bankId").is(bankId.value).
put("accountId").is(accountId.value).
put("transactionId").is(transactionId.value).
put("forView").is(viewId.value).get
findAll(query)
}
//in theory commentId should be enough as we're just using the mongoId
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, tagId : String) : DBObject = {
QueryBuilder.start("_id").is(new ObjectId(tagId)).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}

View File

@ -1,95 +0,0 @@
package code.metadata.transactionimages
import code.model._
import code.util.Helper
import net.liftweb.common.Box
import code.util.Helper.MdcLoggable
import java.net.URL
import java.util.Date
import org.bson.types.ObjectId
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{LongField, StringField}
import net.liftweb.util.Helpers._
import net.liftweb.common.Full
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
private object MongoTransactionImages extends TransactionImages with MdcLoggable {
def getImagesForTransaction(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : List[TransactionImage] = {
OBPTransactionImage.findAll(bankId, accountId, transactionId, viewId)
}
def addTransactionImage(bankId : BankId, accountId : AccountId, transactionId: TransactionId)
(userId: UserPrimaryKey, viewId : ViewId, description : String, datePosted : Date, imageURL: String) : Box[TransactionImage] = {
OBPTransactionImage.createRecord.
bankId(bankId.value).
accountId(accountId.value).
transactionId(transactionId.value).
userId(userId.value).
forView(viewId.value).
imageComment(description).
date(datePosted).
url(imageURL.toString).saveTheRecord()
}
def deleteTransactionImage(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(imageId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPTransactionImage.delete(OBPTransactionImage.getFindQuery(bankId, accountId, transactionId, imageId))
//we don't have any useful information here so just assume it worked
Full(true)
}
def bulkDeleteImagesOnTransaction(bankId : BankId, accountId : AccountId, transactionId: TransactionId) : Boolean = ???
def bulkDeleteTransactionImage(bankId: BankId, accountId: AccountId): Boolean = ???
}
private class OBPTransactionImage private() extends MongoRecord[OBPTransactionImage]
with ObjectIdPk[OBPTransactionImage] with TransactionImage {
def meta = OBPTransactionImage
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object forView extends StringField(this, 255)
object imageComment extends StringField(this, 1000)
object date extends DateField(this)
object url extends StringField(this, 500)
def id_ = id.get.toString
def datePosted = date.get
def postedBy = UserX.findByResourceUserId(userId.get)
def viewId = ViewId(forView.get)
def description = imageComment.get
def imageUrl = {
tryo {new URL(url.get)} getOrElse OBPTransactionImage.notFoundUrl
}
}
private object OBPTransactionImage extends OBPTransactionImage with MongoMetaRecord[OBPTransactionImage] {
val notFoundUrl = new URL("http://example.com/notfound.png") //TODO: Make this image exist?
def findAll(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : List[OBPTransactionImage] = {
val query = QueryBuilder.
start("bankId").is(bankId.value).
put("accountId").is(accountId.value).
put("transactionId").is(transactionId.value).
put("forView").is(viewId.value).get
findAll(query)
}
//in theory commentId should be enough as we're just using the mongoId
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, imageId : String) : DBObject = {
QueryBuilder.start("_id").is(new ObjectId(imageId)).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}

View File

@ -1,56 +0,0 @@
package code.metadata.wheretags
import java.util.Date
import code.model._
import net.liftweb.common.{Box, Full}
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.model._
private object MongoTransactionWhereTags extends WhereTags with MdcLoggable {
def addWhereTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)
(userId: UserPrimaryKey, viewId : ViewId, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
//avoiding upsert for now as it seemed to behave a little strangely
val findQuery = OBPWhereTag.getFindQuery(bankId, accountId, transactionId, viewId)
val found = OBPWhereTag.find(findQuery)
found match {
case Full(f) => {
f.date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude).save(true)
}
case _ => {
OBPWhereTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
transactionId(transactionId.value).
userId(userId.value).
forView(viewId.value).
date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude).save(true)
}
}
//we don't have any useful information here so just return true
true
}
def deleteWhereTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): Boolean = {
//use delete with find query to avoid concurrency issues
OBPWhereTag.delete(OBPWhereTag.getFindQuery(bankId, accountId, transactionId, viewId))
//we don't have any useful information here so just return true
true
}
def getWhereTagForTransaction(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : Box[GeoTag] = {
OBPWhereTag.find(bankId, accountId, transactionId, viewId)
}
def bulkDeleteWhereTagsOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId) : Boolean = ???
def bulkDeleteWhereTags(bankId: BankId, accountId: AccountId) : Boolean = ???
}

View File

@ -1,52 +0,0 @@
package code.metadata.wheretags
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{DoubleField, LongField, StringField}
import code.model._
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
private class OBPWhereTag private() extends MongoRecord[OBPWhereTag] with ObjectIdPk[OBPWhereTag] with GeoTag {
def meta = OBPWhereTag
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object forView extends StringField(this, 255)
object date extends DateField(this)
object geoLongitude extends DoubleField(this,0)
object geoLatitude extends DoubleField(this,0)
override def datePosted = date.get
override def postedBy = UserX.findByResourceUserId(userId.get)
override def longitude = geoLongitude.get
override def latitude = geoLatitude.get
}
private object OBPWhereTag extends OBPWhereTag with MongoMetaRecord[OBPWhereTag] {
def init = createIndex((transactionId.name -> 1) ~ (accountId.name -> 1) ~ (bankId.name -> 1) ~ (forView.name -> 1), true)
def find(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : Option[OBPWhereTag] = {
val query = getFindQuery(bankId, accountId, transactionId, viewId)
find(query)
}
//in theory commentId should be enough as we're just using the mongoId
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : DBObject = {
QueryBuilder.start("forView").is(viewId.value).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}
object OBPWhereTagInit {
def init = OBPWhereTag.init
}

View File

@ -295,7 +295,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
val result = scalikeDB readOnly { implicit session =>
val sqlResult =
sql"""SELECT count(*), avg(duration), min(duration), max(duration)
FROM mappedmetric
FROM metric
WHERE date_c >= ${new Timestamp(fromDate.get.getTime)}
AND date_c <= ${new Timestamp(toDate.get.getTime)}
AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${consumerId.getOrElse("")})
@ -378,8 +378,8 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
// TODO Make it work in case of Oracle database
val otherDbLimit = if (dbUrl.contains("sqlserver")) sqls"" else sqls"LIMIT $limit"
val sqlResult =
sql"""SELECT ${msSqlLimit} count(*), mappedmetric.implementedbypartialfunction, mappedmetric.implementedinversion
FROM mappedmetric
sql"""SELECT ${msSqlLimit} count(*), metric.implementedbypartialfunction, metric.implementedinversion
FROM metric
WHERE
date_c >= ${new Timestamp(fromDate.get.getTime)} AND
date_c <= ${new Timestamp(toDate.get.getTime)}
@ -395,7 +395,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
AND (${trueOrFalse(excludeUrlPatterns.isEmpty) } or (url NOT LIKE ($excludeUrlPatternsQueries)))
AND (${trueOrFalse(excludeAppNames.isEmpty) } or appname not in ($extendedExclueAppNameQueries))
AND (${trueOrFalse(excludeImplementedByPartialFunctions.isEmpty) } or implementedbypartialfunction not in ($extendedExcludeImplementedByPartialFunctionsQueries))
GROUP BY mappedmetric.implementedbypartialfunction, mappedmetric.implementedinversion
GROUP BY metric.implementedbypartialfunction, metric.implementedinversion
ORDER BY count(*) DESC
${otherDbLimit}
""".stripMargin
@ -457,10 +457,10 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
val result: List[TopConsumer] = scalikeDB readOnly { implicit session =>
val sqlResult =
sql"""SELECT ${msSqlLimit} count(*) as count, consumer.id as consumerprimaryid, mappedmetric.appname as appname,
sql"""SELECT ${msSqlLimit} count(*) as count, consumer.id as consumerprimaryid, metric.appname as appname,
consumer.developeremail as email, consumer.consumerid as consumerid
FROM mappedmetric, consumer
WHERE mappedmetric.appname = consumer.name
FROM metric, consumer
WHERE metric.appname = consumer.name
AND date_c >= ${new Timestamp(fromDate.get.getTime)}
AND date_c <= ${new Timestamp(toDate.get.getTime)}
AND (${trueOrFalse(consumerId.isEmpty)} or consumer.consumerid = ${consumerId.getOrElse("")})

View File

@ -1,122 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.metrics
import java.util.Date
import code.api.util.OBPQueryParam
import net.liftweb.common.Box
import net.liftweb.mongodb.record.field.{DateField, LongPk}
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.record.field.{IntField, LongField, StringField}
import scala.concurrent.Future
private class MongoAPIMetric extends MongoRecord[MongoAPIMetric] with LongPk[MongoAPIMetric] with APIMetric {
def meta = MongoAPIMetric
object userId extends StringField(this,255)
object url extends StringField(this,255)
object date extends DateField(this)
object duration extends LongField(this)
object userName extends StringField(this,255)
object appName extends StringField(this,255)
object developerEmail extends StringField(this,255)
//The consumerId, Foreign key to Consumer not key
object consumerId extends StringField(this,255)
//name of the Scala Partial Function being used for the endpoint
object implementedByPartialFunction extends StringField(this,255)
//name of version where the call is implemented) -- S.request.get.view
object implementedInVersion extends StringField(this,255)
//(GET, POST etc.) --S.request.get.requestType
object verb extends StringField(this,255)
object httpCode extends IntField(this)
object correlationId extends StringField(this,255)
def getMetricId(): Long = id.get
def getUrl() = url.get
def getDate() = date.get
def getDuration(): Long = duration.get
def getUserId() = userId.get
def getUserName(): String = userName.get
def getAppName(): String = appName.get
def getDeveloperEmail(): String = developerEmail.get
override def getConsumerId(): String = consumerId.get
override def getImplementedByPartialFunction(): String = implementedByPartialFunction.get
override def getImplementedInVersion(): String = implementedInVersion.get
override def getVerb(): String = verb.get
override def getHttpCode(): Int = httpCode.get
override def getCorrelationId(): String = correlationId.get
}
private object MongoAPIMetric extends MongoAPIMetric with MongoMetaRecord[MongoAPIMetric] with APIMetrics {
def saveMetric(userId: String, url: String, date: Date, duration: Long, userName: String, appName: String, developerEmail: String, consumerId: String, implementedByPartialFunction: String, implementedInVersion: String, verb: String, httpCode: Option[Int], correlationId: String): Unit = {
MongoAPIMetric.createRecord.
userId(userId).
url(url).
date(date).
duration(duration).
userName(userName).
appName(appName).
developerEmail(developerEmail).
consumerId(consumerId).
implementedByPartialFunction(implementedByPartialFunction).
implementedInVersion(implementedInVersion).
verb(verb).
correlationId(correlationId)
saveTheRecord()
}
override def saveMetricsArchive(primaryKey: Long, userId: String, url: String, date: Date, duration: Long, userName: String, appName: String, developerEmail: String, consumerId: String, implementedByPartialFunction: String, implementedInVersion: String, verb: String, httpCode: Option[Int], correlationId: String): Unit = ???
// def getAllGroupedByUrl() : Map[String, List[APIMetric]] = {
// MongoAPIMetric.findAll.groupBy[String](_.url.get)
// }
//
// def getAllGroupedByDay() : Map[Date, List[APIMetric]] = {
// MongoAPIMetric.findAll.groupBy[Date](APIMetrics.getMetricDay)
// }
//
// def getAllGroupedByUserId() : Map[String, List[APIMetric]] = {
// MongoAPIMetric.findAll.groupBy[String](_.getUserId)
// }
override def getAllMetrics(queryParams: List[OBPQueryParam]): List[APIMetric] = {
MongoAPIMetric.findAll
}
override def bulkDeleteMetrics(): Boolean = ???
override def getAllAggregateMetricsFuture(queryParams: List[OBPQueryParam]): Future[Box[List[AggregateMetrics]]] = ???
override def getTopApisFuture(queryParams: List[OBPQueryParam]): Future[Box[List[TopApi]]] = ???
override def getTopConsumersFuture(queryParams: List[OBPQueryParam]): Future[Box[List[TopConsumer]]] = ???
}

View File

@ -15,7 +15,7 @@ object MappedMigrationScriptLogProvider extends MigrationScriptLogProvider with
.StartDate(startDate)
.EndDate(endDate)
.Remark(comment)
.save()
.save
case _ =>
MigrationScriptLog
.create
@ -25,7 +25,7 @@ object MappedMigrationScriptLogProvider extends MigrationScriptLogProvider with
.StartDate(startDate)
.EndDate(endDate)
.Remark(comment)
.save()
.save
}
}
override def isExecuted(name: String): Boolean = {

View File

@ -455,7 +455,7 @@ object MappedConsumersProvider extends ConsumersProvider with MdcLoggable {
for {
consumer <- Consumer.findAll(NullRef(Consumer.consumerId))++ Consumer.findAll(By(Consumer.consumerId,""))
} yield {
consumer.consumerId(APIUtil.generateUUID()).save()
consumer.consumerId(APIUtil.generateUUID()).save
}
}.forall(_ == true)
@ -843,7 +843,7 @@ object MappedTokenProvider extends TokensProvider {
override def updateToken(id: Long, userId: Long): Boolean = {
Token.find(By(Token.id, id)) match {
case Full(t) => t.userForeignKey(userId).save()
case Full(t) => t.userForeignKey(userId).save
case _ => false
}
}

View File

@ -1,249 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.model.dataAccess
import java.util.Date
import code.api.util._
import code.model._
import code.util.Helper
import code.util.Helper.MdcLoggable
import com.mongodb.QueryBuilder
import com.openbankproject.commons.model._
import net.liftweb.common._
import net.liftweb.mapper.By
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk, ObjectIdRefField}
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.{Limit, Skip}
import net.liftweb.record.field.{DecimalField, StringField}
import scala.collection.immutable.List
class Account extends BankAccount with MongoRecord[Account] with ObjectIdPk[Account] with MdcLoggable{
def meta = Account
object accountBalance extends DecimalField(this, 0) {
//this is the legacy db field name
override def name = "balance"
}
object holder extends StringField(this, 255)
object accountNumber extends StringField(this, 255){
//this is the legacy db field name
override def name = "number"
}
object kind extends StringField(this, 255)
// object productCode extends StringField(this, 255)
object accountName extends StringField(this, 255){
//this is the legacy db field name
override def name = "name"
}
object permalink extends StringField(this, 255)
object bankID extends ObjectIdRefField(this, HostedBank)
object accountLabel extends StringField(this, 255){
//this is the legacy db field name
override def name = "label"
}
object accountCurrency extends StringField(this, 255){
//this is the legacy db field name
override def name = "currency"
}
object accountIban extends StringField(this, 255){
//this is the legacy db field name
override def name = "iban"
}
object accountLastUpdate extends DateField(this)
object mAccountRoutingScheme extends StringField(this, 255)
object mAccountRoutingAddress extends StringField(this, 255)
object mBranchId extends StringField(this, 255)
object mAccountRuleScheme1 extends StringField(this, 10)
object mAccountRuleValue1 extends DecimalField(this, 0)
object mAccountRuleScheme2 extends StringField(this, 10)
object mAccountRuleValue2 extends DecimalField(this, 0)
def transactionsForAccount: QueryBuilder = {
QueryBuilder
.start("obp_transaction.this_account.number")
.is(accountNumber.get)
//FIX: change that to use the bank identifier
.put("obp_transaction.this_account.bank.national_identifier")
.is(this.nationalIdentifier)
}
//find all the envelopes related to this account
def allEnvelopes: List[OBPEnvelope] = OBPEnvelope.findAll(transactionsForAccount.get)
def envelopes(queryParams: List[OBPQueryParam]): List[OBPEnvelope] = {
import com.mongodb.DBObject
import net.liftweb.mongodb.FindOption
val limit: Seq[Limit] = queryParams.collect { case OBPLimit(value) => Limit(value) }
val offset: Seq[Skip] = queryParams.collect { case OBPOffset(value) => Skip(value) }
val limitAndOffset: Seq[FindOption] = limit ++ offset
val fromDate: Option[OBPFromDate] = queryParams.collect { case param: OBPFromDate => param }.headOption
val toDate: Option[OBPToDate] = queryParams.collect { case param: OBPToDate => param }.headOption
val query: DBObject = {
val queryWithOptionalFromDate = fromDate.map{
date => {
transactionsForAccount
.put("obp_transaction.details.completed")
.greaterThanEquals(date.value)
}
}.getOrElse(transactionsForAccount)
val queryWithOptionalFromDateAndToDate = toDate.map{
date => {
queryWithOptionalFromDate
.put("obp_transaction.details.completed")
.lessThanEquals(date.value)
}
}.getOrElse(queryWithOptionalFromDate)
queryWithOptionalFromDateAndToDate.get
}
val defaultSortField = "obp_transaction.details.completed"
val orderingParams = queryParams
.collect { case param: OBPOrdering => param}
.headOption
val ordering: Option[DBObject] =
orderingParams.map{
o => {
QueryBuilder
.start(defaultSortField)
.is(o.order.orderValue)
.get
}
}
ordering match {
case Some(o) =>{
OBPEnvelope.findAll(query, o, limitAndOffset: _*)
}
case _ =>{
OBPEnvelope.findAll(query, limitAndOffset: _*)
}
}
}
override def bankId: BankId = {
bankID.obj match {
case Full(bank) => BankId(bank.permalink.get)
case _ => BankId("")
}
}
override def accountId : AccountId = AccountId(permalink.get)
def iban: Option[String] = {
val i = accountIban.get
if (i.isEmpty) None else Some(i)
}
override def currency: String = accountCurrency.get
override def number: String = accountNumber.get
override def balance: BigDecimal = accountBalance.get
override def name: String = accountName.get
override def accountType: String = kind.get
override def label: String = accountLabel.get
override def accountHolder: String = holder.get
override def lastUpdate: Date = accountLastUpdate.get
def accountRoutingScheme: String = mAccountRoutingScheme.get
def accountRoutingAddress: String = mAccountRoutingAddress.get
override def branchId: String = mBranchId.get
def createAccountRule(scheme: String, value: Long) = {
scheme match {
case s: String if s.equalsIgnoreCase("") == false =>
val v = Helper.smallestCurrencyUnitToBigDecimal(value, accountCurrency.get)
List(AccountRule(scheme, v.toString()))
case _ =>
Nil
}
}
override def accountRoutings: List[AccountRouting] = {
BankAccountRouting.findAll(
By(BankAccountRouting.BankId, this.bankId.value),
By(BankAccountRouting.AccountId, this.accountId.value)
).map(_.accountRouting) match {
case Nil => // This is the fallback if the BankAccountRouting failed
List(AccountRouting(mAccountRoutingScheme.get, mAccountRoutingAddress.get))
case everythingElseJustForward =>
everythingElseJustForward
}
}
override def accountRules: List[AccountRule] = createAccountRule(mAccountRuleScheme1.get, mAccountRuleValue1.get.toLong) :::
createAccountRule(mAccountRuleScheme2.get, mAccountRuleValue2.get.toLong)
}
object Account extends Account with MongoMetaRecord[Account] {
def init = createIndex((permalink.name -> 1) ~ (bankID.name -> 1), true)
}
class HostedBank extends Bank with MongoRecord[HostedBank] with ObjectIdPk[HostedBank]{
def meta = HostedBank
object name extends StringField(this, 255)
object alias extends StringField(this, 255)
object logoURL extends StringField(this, 255)
object website extends StringField(this, 255)
object email extends StringField(this, 255)
object permalink extends StringField(this, 255)
object swiftBIC extends StringField(this, 255)
object national_identifier extends StringField(this, 255)
object mBankRoutingScheme extends StringField(this, 255)
object mBankRoutingAddress extends StringField(this, 255)
def getAccount(bankAccountId: AccountId) : Box[Account] = {
Account.find((Account.permalink.name -> bankAccountId.value) ~ (Account.bankID.name -> id.get)) ?~ {"account " + bankAccountId +" not found at bank " + permalink}
}
def isAccount(bankAccountId : AccountId) : Boolean =
Account.count((Account.permalink.name -> bankAccountId.value) ~ (Account.bankID.name -> id.get)) == 1
override def bankId: BankId = BankId(permalink.get)
override def shortName: String = alias.get
override def fullName: String = name.get
override def logoUrl: String = logoURL.get
override def websiteUrl: String = website.get
override def swiftBic: String = swiftBIC.get
override def nationalIdentifier: String = national_identifier.get
override def bankRoutingScheme = mBankRoutingAddress.get
override def bankRoutingAddress = mBankRoutingAddress.get
}
object HostedBank extends HostedBank with MongoMetaRecord[HostedBank] {
def init = createIndex((permalink.name -> 1), true)
def find(bankId : BankId) : Box[HostedBank] = find(HostedBank.permalink.name -> bankId.value)
}

View File

@ -82,7 +82,7 @@ import scala.concurrent.Future
*
*
* 3 RelationShips:
* 1)When `Sign up` new user --> create AuthUser --> call AuthUser.save() --> create ResourceUser user.
* 1)When `Sign up` new user --> create AuthUser --> call AuthUser.save --> create ResourceUser user.
* They share the same username and email.
* 2)AuthUser `user` field as the Foreign Key to link to Resource User.
* one AuthUser <---> one ResourceUser
@ -370,7 +370,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga
}
}
}
super.save()
super.save
}
override def delete_!(): Boolean = {
@ -1581,7 +1581,7 @@ def restoreSomeSessions(): Unit = {
.lastName(Helpers.randomString(16))
.password(Helpers.randomString(40))
.validated(false)
scrambledUser.save()
scrambledUser.save
case Empty => true // There is a resource user but no the correlated Auth user
case _ => false // Error case
}

View File

@ -1,64 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.model.dataAccess
import code.api.util.APIUtil
import code.metadata.narrative.OBPNarrativeInit
import code.metadata.wheretags.OBPWhereTagInit
import com.mongodb.MongoClient
import net.liftweb.util.ConnectionIdentifier
object AdminDb extends ConnectionIdentifier {
val jndiName = "admin"
}
object MongoConfig {
def init: Unit = {
import net.liftweb.mongodb.MongoDB
import com.mongodb.{Mongo, ServerAddress}
import net.liftweb.util.{Props, DefaultConnectionIdentifier}
val srvr = new ServerAddress(
APIUtil.getPropsValue("mongo.host", "localhost"),
APIUtil.getPropsAsIntValue("mongo.port", 27017)
)
val defaultDatabase = Props.mode match {
case Props.RunModes.Test => "test"
case _ => "OBP006"
}
MongoDB.defineDb(DefaultConnectionIdentifier, new MongoClient(srvr), APIUtil.getPropsValue("mongo.dbName", defaultDatabase))
MongoDB.defineDb(AdminDb, new MongoClient(srvr), "admin")
HostedBank.init
Account.init
OBPNarrativeInit.init
OBPWhereTagInit.init
}
}

View File

@ -1,408 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.model.dataAccess
import code.util.Helper
import com.mongodb.QueryBuilder
import net.liftweb.mongodb.record.field._
import net.liftweb.mongodb.record.{BsonMetaRecord, BsonRecord, MongoMetaRecord, MongoRecord}
import net.liftweb.common.{Box, Empty, Failure}
import java.util.{Date, UUID}
import net.liftweb.record.field.{LongField, StringField}
import net.liftweb.json.JsonAST._
import code.model._
import code.util.Helper.MdcLoggable
import net.liftweb.record.field.{DecimalField, DoubleField}
import net.liftweb.util.FieldError
import org.bson.types.ObjectId
import scala.xml.Unparsed
import net.liftweb.json.JsonAST.JObject
import scala.Some
import net.liftweb.json.JsonAST.JString
import net.liftweb.common.Full
import net.liftweb.json.JsonAST.JField
import code.metadata.counterparties.MongoCounterparties
import com.openbankproject.commons.model.{AccountId, BankId, TransactionId}
/**
* "Current Account View"
curl -i -H "Content-Type: application/json" -X POST -d '[{
"obp_transaction":{
"this_account":{
"holder":"Music Pictures Limited",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"DE1235123612",
"national_identifier":"de.10010010",
"name":"Postbank"
}
},
"other_account":{
"holder":"Client 1",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"UK12222879",
"national_identifier":"uk.10010010",
"name":"HSBC"
}
},
"details":{
"type_en":"Transfer",
"type_de":"Überweisung",
"posted":{
"$dt":"2012-01-04T18:06:22.000Z"
},
"completed":{
"$dt":"2012-09-04T18:52:13.000Z"
},
"new_balance":{
"currency":"EUR",
"amount":"4323.45"
},
"value":{
"currency":"EUR",
"amount":"123.45"
},
"other_data":"9"
}
}
},
{
"obp_transaction":{
"this_account":{
"holder":"Music Pictures Limited",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"DE1235123612",
"national_identifier":"de.10010010",
"name":"Postbank"
}
},
"other_account":{
"holder":"Client 2",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"UK22222879",
"national_identifier":"uk.10010010",
"name":"HSBC"
}
},
"details":{
"type_en":"Transfer",
"type_de":"Überweisung",
"posted":{
"$dt":"2012-01-04T14:06:22.000Z"
},
"completed":{
"$dt":"2012-09-04T14:52:13.000Z"
},
"new_balance":{
"currency":"EUR",
"amount":"2222.45"
},
"value":{
"currency":"EUR",
"amount":"223.45"
},
"other_data":"9"
}
}
}]' http://localhost:8080/api/transactions
*/
// Seems to map to a collection of the plural name
class OBPEnvelope private() extends MongoRecord[OBPEnvelope] with ObjectIdPk[OBPEnvelope] with MdcLoggable with TransactionUUID {
def meta = OBPEnvelope
def theTransactionId = TransactionId(transactionId.get)
def theAccountId = theAccount.map(_.accountId).getOrElse(AccountId(""))
def theBankId = theAccount.map(_.bankId).getOrElse(BankId(""))
object transactionId extends StringField(this, 100) {
override def defaultValue = UUID.randomUUID.toString
}
// This creates a json attribute called "obp_transaction"
object obp_transaction extends BsonRecordField(this, OBPTransaction)
override def validate: List[FieldError] =
obp_transaction.get.validate ++
super.validate
object DateDescending extends Ordering[OBPEnvelope] {
def compare(e1: OBPEnvelope, e2: OBPEnvelope) = {
val date1 = e1.obp_transaction.get.details.get.completed.get
val date2 = e2.obp_transaction.get.details.get.completed.get
date1.compareTo(date2)
}
}
lazy val theAccount: Box[Account] = {
import net.liftweb.mongodb.BsonDSL._
val thisAcc = obp_transaction.get.this_account.get
val num = thisAcc.number.get
val bankNationalIdentifier = thisAcc.bank.get.national_identifier.get
for {
bank <- HostedBank.find((HostedBank.national_identifier.name -> bankNationalIdentifier))
bankMongoId : ObjectId = bank.id.get
account <- Account.find((Account.accountNumber.name -> num) ~ (Account.bankID.name -> bankMongoId))
} yield account
}
def orderByDateDescending = (e1: OBPEnvelope, e2: OBPEnvelope) => {
val date1 = e1.obp_transaction.get.details.get.completed.get
val date2 = e2.obp_transaction.get.details.get.completed.get
date1.after(date2)
}
}
object OBPEnvelope extends OBPEnvelope with MongoMetaRecord[OBPEnvelope] with MdcLoggable {
def envelopesFromJValue(jval: JValue) : Box[OBPEnvelope] = {
val createdBox = fromJValue(jval)
createdBox match {
case Full(created) =>
val errors = created.validate
if(errors.isEmpty) {
Full(created)
} else {
logger.warn("could not create a obp envelope.errors: ")
logger.warn(errors)
Empty
}
case Failure(msg, _, _) =>
Failure(s"could not create Envelope from JValue: $msg")
case _ =>
Failure(s"could not create Envelope from JValue")
}
}
}
class OBPTransaction private() extends BsonRecord[OBPTransaction]{
def meta = OBPTransaction
object this_account extends BsonRecordField(this, OBPAccount)
object other_account extends BsonRecordField(this, OBPAccount)
object details extends BsonRecordField(this, OBPDetails)
private def validateThisAccount: List[FieldError] = {
val accountNumber = this_account.get.number
val bankId = this_account.get.bank.get.national_identifier
val accountNumberError =
if(accountNumber.get.isEmpty)
Some(new FieldError(accountNumber, Unparsed("this bank account number is empty")))
else
None
val bankIdError =
if(bankId.get.isEmpty)
Some(new FieldError(bankId, Unparsed("this bank number is empty")))
else
None
List(accountNumberError, bankIdError).flatten
}
override def validate: List[FieldError] =
validateThisAccount ++
this_account.get.validate ++
other_account.get.validate ++
details.get.validate ++
super.validate
@deprecated(Helper.deprecatedJsonGenerationMessage, null)
def whenAddedJson(envelopeId : String) : JObject = {
JObject(List(JField("obp_transaction_uuid", JString(envelopeId)),
JField("this_account", this_account.get.whenAddedJson),
JField("other_account", other_account.get.whenAddedJson),
JField("details", details.get.whenAddedJson)))
}
}
object OBPTransaction extends OBPTransaction with BsonMetaRecord[OBPTransaction]
class OBPAccount private() extends BsonRecord[OBPAccount]{
def meta = OBPAccount
object holder extends StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object number extends StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object kind extends StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object bank extends BsonRecordField(this, OBPBank)
override def validate: List[FieldError] =
holder.validate ++
number.validate ++
kind.validate ++
bank.validate ++
super.validate
/**
* @param moderatingAccount a temporary way to provide the obp account whose aliases should
* be used when displaying this account
*/
def whenAddedJson: JObject = {
JObject(List(JField("holder",
JObject(List(
JField("holder", JString(holder.get)),
JField("alias", JString("no"))))),
JField("number", JString(number.get)),
JField("kind", JString(kind.get)),
JField("bank", bank.get.whenAddedJson)))
}
}
object OBPAccount extends OBPAccount with BsonMetaRecord[OBPAccount]{
sealed abstract class AnAlias
case object APublicAlias extends AnAlias
case object APrivateAlias extends AnAlias
}
class OBPBank private() extends BsonRecord[OBPBank]{
def meta = OBPBank
object IBAN extends net.liftweb.record.field.StringField(this, 255)
object national_identifier extends net.liftweb.record.field.StringField(this, 255)
object name extends net.liftweb.record.field.StringField(this, 255)
override def validate: List[FieldError] =
IBAN.validate ++
national_identifier.validate ++
name.validate ++
super.validate
def whenAddedJson : JObject = {
JObject(List( JField("IBAN", JString(IBAN.get)),
JField("national_identifier", JString(national_identifier.get)),
JField("name", JString(name.get))))
}
}
object OBPBank extends OBPBank with BsonMetaRecord[OBPBank]
class OBPDetails private() extends BsonRecord[OBPDetails]{
def meta = OBPDetails
object kind extends net.liftweb.record.field.StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object posted extends DateField(this)
object other_data extends net.liftweb.record.field.StringField(this, 5000){
override def required_? = false
override def optional_? = true
}
object new_balance extends BsonRecordField(this, OBPBalance)
object value extends BsonRecordField(this, OBPValue)
object completed extends DateField(this)
object label extends net.liftweb.record.field.StringField(this, 255){
override def required_? = false
override def optional_? = true
}
override def validate: List[FieldError] =
kind.validate ++
posted.validate ++
other_data.validate ++
new_balance.validate ++
value.validate ++
completed.validate ++
label.validate ++
super.validate
def formatDate(date : Date) : String = {
OBPDetails.formats.dateFormat.format(date)
}
def whenAddedJson : JObject = {
JObject(List( JField("type_en", JString(kind.get)),
JField("type", JString(kind.get)),
JField("posted", JString(formatDate(posted.get))),
JField("completed", JString(formatDate(completed.get))),
JField("other_data", JString(other_data.get)),
JField("new_balance", new_balance.get.whenAddedJson),
JField("value", value.get.whenAddedJson)))
}
}
object OBPDetails extends OBPDetails with BsonMetaRecord[OBPDetails]
class OBPBalance private() extends BsonRecord[OBPBalance]{
def meta = OBPBalance
object currency extends StringField(this, 5)
object amount extends DecimalField(this, 0) // ok to use decimal?
override def validate: List[FieldError] =
currency.validate ++
amount.validate ++
super.validate
def whenAddedJson : JObject = {
JObject(List( JField("currency", JString(currency.get)),
JField("amount", JString(amount.get.toString))))
}
}
object OBPBalance extends OBPBalance with BsonMetaRecord[OBPBalance]
class OBPValue private() extends BsonRecord[OBPValue]{
def meta = OBPValue
object currency extends net.liftweb.record.field.StringField(this, 5)
object amount extends net.liftweb.record.field.DecimalField(this, 0) // ok to use decimal?
def whenAddedJson : JObject = {
JObject(List( JField("currency", JString(currency.get)),
JField("amount", JString(amount.get.toString))))
}
}
object OBPValue extends OBPValue with BsonMetaRecord[OBPValue]

View File

@ -50,7 +50,7 @@ import net.liftweb.mapper._
*
*
* 3 RelationShips:
* 1)When `Sign up` new user --> create AuthUser --> call AuthUser.save() --> create ResourceUser user.
* 1)When `Sign up` new user --> create AuthUser --> call AuthUser.save --> create ResourceUser user.
* They share the same username and email.
* 2)AuthUser `user` field as the Foreign Key to link to Resource User.
* one AuthUser <---> one ResourceUser

View File

@ -18,7 +18,7 @@ trait CreateAuthUsers {
def save() = {
val usr = Users.users.vend.saveResourceUser(value)
for (uu <- usr) {
u.user(uu).save()
u.user(uu).save
}
}
}

View File

@ -1,155 +0,0 @@
package code.sandbox
import code.metadata.counterparties.{MongoCounterparties, Metadata}
import code.model._
import code.model.dataAccess._
import net.liftweb.common._
import java.util.UUID
import net.liftweb.mapper.By
import net.liftweb.mongodb.record.MongoRecord
import net.liftweb.util.Helpers._
import org.bson.types.ObjectId
//An basic implementation of Saveable for MongoRecords
case class SaveableMongoObj[T <: MongoRecord[_]](value : T) extends Saveable[T] {
def save() = value.save(true)
}
/**
* Imports data into the format used by LocalRecordConnector (e.g. HostedBank)
*/
/*
Not currently using this connector so not updating it at the moment.
object LocalRecordConnectorDataImport extends OBPDataImport with CreateAuthUsers {
type BankType = HostedBank
type AccountType = Account
type TransactionType = OBPEnvelope
type MetadataType = Metadata
protected def createSaveableBanks(data : List[SandboxBankImport]) : Box[List[Saveable[BankType]]] = {
val hostedBanks = data.map(b => {
HostedBank.createRecord
.id(ObjectId.get)
.permalink(b.id)
.name(b.full_name)
.alias(b.short_name)
.website(b.website)
.logoURL(b.logo)
.national_identifier(b.id) //this needs to match up with what goes in the OBPEnvelopes
})
val validationErrors = hostedBanks.flatMap(_.validate)
if(!validationErrors.isEmpty) {
Failure(s"Errors: ${validationErrors.map(_.msg)}")
} else {
Full(hostedBanks.map(SaveableMongoObj(_)))
}
}
protected def createSaveableAccount(acc : SandboxAccountImport, banks : List[HostedBank]) : Box[Saveable[Account]] = {
def getHostedBank(acc : SandboxAccountImport) = Box(banks.find(b => b.permalink.get == acc.bank))
def asSaveableAccount(account : Account, hostedBank : HostedBank) = new Saveable[Account] {
val value = account
def save() = {
//this looks pointless, but what it is doing is refreshing the Account.bankID.obj reference, which
//is used by Account.bankId. If we don't refresh it here, Account.bankId will return BankId("")
account.bankID(account.bankID.get).save(true)
}
}
for {
hBank <- getHostedBank(acc) ?~ {
logger.warn("hosted bank not found")
"Server error"
}
balance <- tryo{BigDecimal(acc.balance.amount)} ?~ s"Invalid balance: ${acc.balance.amount}"
} yield {
val account = Account.createRecord
.permalink(acc.id)
.bankID(hBank.id.get)
.accountLabel(acc.label)
.accountCurrency(acc.balance.currency)
.accountBalance(balance)
.accountNumber(acc.number)
.kind(acc.`type`)
.accountIban(acc.IBAN)
asSaveableAccount(account, hBank)
}
}
override protected def createSaveableTransaction(t : SandboxTransactionImport, createdBanks : List[BankType], createdAccounts : List[AccountType]) :
Box[Saveable[TransactionType]] = {
val counterpartyHolder = t.counterparty.flatMap(_.name).getOrElse("")
for {
createdBank <- Box(createdBanks.find(b => b.permalink.get == t.this_account.bank)) ?~
s"Transaction this_account bank must be specified in import banks. Unspecified bank: ${t.this_account.bank}"
//have to compare a.bankID to createdBank.id instead of just checking a.bankId against t.this_account.bank as createdBank hasn't been
//saved so the a.bankId method (which involves a db lookup) will not work
createdAcc <- Box(createdAccounts.find(a => a.bankID.toString == createdBank.id.get.toString && a.accountId == AccountId(t.this_account.id))) ?~
s"Transaction this_account account must be specified in import accounts. Unspecified account id: ${t.this_account.id} at bank: ${t.this_account.bank}"
newBalanceValue <- tryo{BigDecimal(t.details.new_balance)} ?~ s"Invalid new balance: ${t.details.new_balance}"
tValue <- tryo{BigDecimal(t.details.value)} ?~ s"Invalid transaction value: ${t.details.value}"
postedDate <- tryo{dateFormat.parse(t.details.posted)} ?~ s"Invalid date format: ${t.details.posted}. Expected pattern $datePattern"
completedDate <-tryo{dateFormat.parse(t.details.completed)} ?~ s"Invalid date format: ${t.details.completed}. Expected pattern $datePattern"
} yield {
//bankNationalIdentifier not available from createdAcc.bankNationalIdentifier as it hasn't been saved so we get it from createdBank
val obpThisAccountBank = OBPBank.createRecord
.national_identifier(createdBank.national_identifier.get)
val obpThisAccount = OBPAccount.createRecord
.holder(createdAcc.holder.get)
.number(createdAcc.accountNumber.get)
.kind(createdAcc.kind.get)
.bank(obpThisAccountBank)
val counterpartyAccountNumber = t.counterparty.flatMap(_.account_number)
val obpOtherAccount = OBPAccount.createRecord
.holder(counterpartyHolder)
.number(counterpartyAccountNumber.getOrElse(""))
val newBalance = OBPBalance.createRecord
.amount(newBalanceValue)
.currency(createdAcc.accountCurrency.get)
val transactionValue = OBPValue.createRecord
.amount(tValue)
.currency(createdAcc.accountCurrency.get)
val obpDetails = OBPDetails.createRecord
.completed(completedDate)
.posted(postedDate)
.kind(t.details.`type`)
.label(t.details.description)
.new_balance(newBalance)
.value(transactionValue)
val obpTransaction = OBPTransaction.createRecord
.details(obpDetails)
.this_account(obpThisAccount)
.other_account(obpOtherAccount)
val env = OBPEnvelope.createRecord
.transactionId(t.id)
.obp_transaction(obpTransaction)
SaveableMongoObj(env)
}
}
}
*/

View File

@ -18,7 +18,7 @@ import net.liftweb.mapper.Mapper
import net.liftweb.util.Helpers._
case class MappedSaveable[T <: Mapper[_]](value : T) extends Saveable[T] {
def save() = value.save()
def save() = value.save
}
object LocalMappedConnectorDataImport extends OBPDataImport with CreateAuthUsers {

View File

@ -500,22 +500,22 @@ trait OBPDataImport extends MdcLoggable {
crmEvents <- createCrmEvents(data)
} yield {
logger.info(s"importData is saving ${banks.size} banks..")
banks.foreach(_.save())
banks.foreach(_.save)
logger.info(s"importData is saving ${users.size} users..")
users.foreach(_.save())
users.foreach(_.save)
logger.info(s"importData is saving ${branches.size} branches..")
branches.foreach(_.save())
branches.foreach(_.save)
logger.info(s"importData is saving ${atms.size} ATMs..")
atms.foreach(_.save())
atms.foreach(_.save)
logger.info(s"importData is saving ${products.size} products..")
products.foreach(_.save())
products.foreach(_.save)
logger.info(s"importData is saving ${crmEvents.size} crmEvents..")
crmEvents.foreach(_.save())
crmEvents.foreach(_.save)
@ -526,7 +526,7 @@ trait OBPDataImport extends MdcLoggable {
logger.info(s"importData is saving ${accountResults.size} accountResults (accounts, views and permissions)..")
accountResults.foreach {
case (account, systemViews, accOwnerUsernames) =>
account.save()
account.save
systemViews.filterNot(_.isPublic).foreach(v => {
//grant the owner access to Private systemViews
@ -539,7 +539,7 @@ trait OBPDataImport extends MdcLoggable {
}
logger.info(s"importData is saving ${transactions.size} transactions (and loading them again)")
transactions.foreach { t =>
t.save()
t.save
//load it to force creation of metadata (If we are using Mapped connector, MappedCounterpartyMetadata.create will be called)
val lt = Connector.connector.vend.getTransactionLegacy(t.value.theBankId, t.value.theAccountId, t.value.theTransactionId)
}

View File

@ -14,74 +14,72 @@ object WebUITemplate {
val webUIDoc = ArrayBuffer[WebUIDoc]()
val webUiDeveloperUserInvitationEmailText =
s"""
|Hi ${emailRecipient},
|Welcome to the Open Bank Project API. Your account has been registered. Please use the below link to activate it.
|
|Activate your account: ${activateYourAccount}
|
|Our operations team has granted you the appropriate access to the OBP-API. If you have any questions, or you need any assistance, please contact our support.
|
|Thanks,
|Your OBP API team
|
|
|
|Please do not reply to this email. Should you wish to contact us, please raise a ticket at our support page. We maintain strict security standards and procedures to prevent unauthorised access to information about you. We will never contact you by email or otherwise and ask you to validate personal information such as your user ID, password or account numbers. This e-mail is confidential. It may also be legally privileged. If you are not the addressee you may not copy, forward, disclose or use any part of it. If you have received this message in error, please delete it and all copies from your system. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions.
|""".stripMargin
webUIDoc += WebUIDoc(
webUiPropsName = "webui_developer_user_invitation_email_text",
defaultValue = webUiDeveloperUserInvitationEmailText,
typeOfValue = "plain_text",
placeholders = List(emailRecipient, activateYourAccount)
)
val webUiDeveloperUserInvitationEmailText =
s"""
|Hi ${emailRecipient},
|Welcome to the Open Bank Project API. Your account has been registered. Please use the below link to activate it.
|
|Activate your account: ${activateYourAccount}
|
|Our operations team has granted you the appropriate access to the OBP-API. If you have any questions, or you need any assistance, please contact our support.
|
|Thanks,
|Your OBP API team
|
|
|
|Please do not reply to this email. Should you wish to contact us, please raise a ticket at our support page. We maintain strict security standards and procedures to prevent unauthorised access to information about you. We will never contact you by email or otherwise and ask you to validate personal information such as your user ID, password or account numbers. This e-mail is confidential. It may also be legally privileged. If you are not the addressee you may not copy, forward, disclose or use any part of it. If you have received this message in error, please delete it and all copies from your system. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions.
|""".stripMargin
val webUiDeveloperUserInvitationEmailHtmlText =
s"""<!DOCTYPE html>
|<html>
|<head>
|<style>
|.a {
| border: none;
| color: white;
| padding: 15px 32px;
| text-align: center;
| text-decoration: none;
| display: inline-block;
| font-size: 16px;
| margin: 4px 2px;
| cursor: pointer;
|}
|
|.a1 {background-color: #4CAF50;} /* Green */
|.a2 {background-color: #008CBA;} /* Blue */
|</style>
|</head>
|<body>
|<img src="https://static.openbankproject.com/images/OBP_full_web_25pc.png"></img>
|<hr></hr><br></br>
|<p>Hi ${emailRecipient},<br></br>
|Welcome to the Open Bank Project API. Your account has been registered. Please use the below link to activate it.</p>
|<a href="${activateYourAccount}" class="a a1">Activate your account</a>
|<p>Our operations team has granted you the appropriate access to the OBP-API. If you have any questions, or you need any assistance, please contact our support.</p>
|<p>Thanks,<br></br> Your OBP API team</p><br></br>
|<hr></hr>
|<p>
|Please do not reply to this email. Should you wish to contact us, please raise a ticket at our support page. We maintain strict security standards and procedures to prevent unauthorised access to information about you. We will never contact you by email or otherwise and ask you to validate personal information such as your user ID, password or account numbers. This e-mail is confidential. It may also be legally privileged. If you are not the addressee you may not copy, forward, disclose or use any part of it. If you have received this message in error, please delete it and all copies from your system. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions.
|</p>
|</body>
|</html>
|
|""".stripMargin
webUIDoc += WebUIDoc(
webUiPropsName = "webui_developer_user_invitation_email_html_text",
defaultValue = webUiDeveloperUserInvitationEmailHtmlText,
typeOfValue = "html",
placeholders = List(emailRecipient, activateYourAccount)
)
val webUiDeveloperUserInvitationEmailHtmlText =
s"""<!DOCTYPE html>
|<html>
|<head>
|<style>
|.a {
| border: none;
| color: white;
| padding: 15px 32px;
| text-align: center;
| text-decoration: none;
| display: inline-block;
| font-size: 16px;
| margin: 4px 2px;
| cursor: pointer;
|}
|
|.a1 {background-color: #4CAF50;} /* Green */
|.a2 {background-color: #008CBA;} /* Blue */
|</style>
|</head>
|<body>
|<img src="https://static.openbankproject.com/images/OBP_full_web_25pc.png"></img>
|<hr></hr><br></br>
|<p>Hi ${emailRecipient},<br></br>
|Welcome to the Open Bank Project API. Your account has been registered. Please use the below link to activate it.</p>
|<a href="${activateYourAccount}" class="a a1">Activate your account</a>
|<p>Our operations team has granted you the appropriate access to the OBP-API. If you have any questions, or you need any assistance, please contact our support.</p>
|<p>Thanks,<br></br> Your OBP API team</p><br></br>
|<hr></hr>
|<p>
|Please do not reply to this email. Should you wish to contact us, please raise a ticket at our support page. We maintain strict security standards and procedures to prevent unauthorised access to information about you. We will never contact you by email or otherwise and ask you to validate personal information such as your user ID, password or account numbers. This e-mail is confidential. It may also be legally privileged. If you are not the addressee you may not copy, forward, disclose or use any part of it. If you have received this message in error, please delete it and all copies from your system. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions.
|</p>
|</body>
|</html>
|
|""".stripMargin
webUIDoc += WebUIDoc(
webUiPropsName = "webui_terms_and_conditions",

View File

@ -21,7 +21,7 @@ object MappedSocialMediasProvider extends SocialMediaHandleProvider {
.mHandle(handle)
.mDateAdded(dateAdded)
.mDateActivated(dateActivated)
.save()
.save
}
}

View File

@ -2,19 +2,18 @@ package code.transaction
import code.accountholders.AccountHolders
import code.actorsystem.ObpLookupSystem
import code.api.util.{APIUtil, ApiTrigger}
import code.bankconnectors.{Connector, LocalMappedConnector}
import code.bankconnectors.LocalMappedConnector
import code.bankconnectors.LocalMappedConnector.getBankAccountCommon
import code.model._
import code.usercustomerlinks.UserCustomerLink
import code.util.Helper.MdcLoggable
import code.util._
import code.webhook.WebhookActor
import code.webhook.WebhookActor.RelatedEntity
import code.webhook.WebhookAction
import code.webhook.WebhookActor.{AccountNotificationWebhookRequest, RelatedEntity, WebhookRequest}
import com.openbankproject.commons.model._
import net.liftweb.common._
import net.liftweb.common.Box.tryo
import net.liftweb.common._
import net.liftweb.mapper._
class MappedTransaction extends LongKeyedMapper[MappedTransaction] with IdPK with CreatedUpdated with TransactionUUID with MdcLoggable {
@ -239,7 +238,6 @@ object MappedTransaction extends MappedTransaction with LongKeyedMetaMapper[Mapp
override def afterSave = List(
t =>
tryo {
val actor = ObpLookupSystem.getWebhookActor()
def getAmount(value: Long): String = {
Helper.smallestCurrencyUnitToBigDecimal(value, t.currency.get).toString() + " " + t.currency.get
}
@ -256,24 +254,28 @@ object MappedTransaction extends MappedTransaction with LongKeyedMetaMapper[Mapp
val userIdCustomerIdsPairs: Map[String, List[String]] = userIdCustomerIdPairs.groupBy(_._1).map( a => (a._1,a._2.map(_._2)))
val eventId = APIUtil.generateUUID()
logger.debug("Before firing WebhookActor.AccountNotificationWebhookRequest.eventId: " + eventId)
actor ! WebhookActor.AccountNotificationWebhookRequest(
apiTrigger,
eventId,
t.theBankId.value,
t.theAccountId.value,
t.theTransactionId.value,
userIdCustomerIdsPairs.map(pair => RelatedEntity(pair._1, pair._2)).toList
WebhookAction.accountNotificationWebhookRequest(
AccountNotificationWebhookRequest(
apiTrigger,
eventId,
t.theBankId.value,
t.theAccountId.value,
t.theTransactionId.value,
userIdCustomerIdsPairs.map(pair => RelatedEntity(pair._1, pair._2)).toList
)
)
} else{
val eventId = APIUtil.generateUUID()
logger.debug("Before firing WebhookActor.WebhookRequest.eventId: " + eventId)
actor ! WebhookActor.WebhookRequest(
apiTrigger,
eventId,
t.theBankId.value,
t.theAccountId.value,
getAmount(t.amount.get),
getAmount(t.newAccountBalance.get)
WebhookAction.webhookRequest(
WebhookRequest(
apiTrigger,
eventId,
t.theBankId.value,
t.theAccountId.value,
getAmount(t.amount.get),
getAmount(t.newAccountBalance.get)
)
)
}
}

View File

@ -302,12 +302,12 @@ object LiftUsers extends Users with MdcLoggable{
.name_("DELETED-" + Helpers.randomString(16))
.email(Helpers.randomString(10) + "@example.com")
.providerId(Helpers.randomString(16))
.save()
.save
case _ =>
u
.Company(Helpers.randomString(16))
.IsDeleted(true)
.save()
.save
}
}
}

View File

@ -32,7 +32,7 @@ object MappedUserInvitationProvider extends UserInvitationProvider {
UserInvitation.find(
By(UserInvitation.UserInvitationId, userInvitationId)
) match {
case Full(userInvitation) => userInvitation.Status(status).save()
case Full(userInvitation) => userInvitation.Status(status).save
case _ => false
}
}
@ -49,7 +49,7 @@ object MappedUserInvitationProvider extends UserInvitationProvider {
.Country(Helpers.randomString(userInvitation.country.length))
.Purpose(Helpers.randomString(userInvitation.purpose.length))
.Status("DELETED")
.save()
.save
case _ => false
}
}

View File

@ -0,0 +1,30 @@
package code.webhook
import java.io.IOException
import code.webhook.WebhookActor.WebhookRequestTrait
import okhttp3._
object OkHttpWebhookClient {
private val client = new OkHttpClient
@throws[Exception]
def makeAsynchronousRequest(request: Request, webhookRequest: WebhookRequestTrait): Unit = {
client.newCall(request).enqueue(new Callback() {
def onFailure(call: Call, e: IOException): Unit = {
WebhookAction.webhookFailure(e.getMessage, webhookRequest)
}
@throws[IOException]
def onResponse(call: Call, response: Response): Unit = {
val responseBody = response.body
try {
if (!response.isSuccessful) throw new IOException("Unexpected code " + response)
org.scalameta.logger.elem(responseBody.string)
WebhookAction.webhookResponse(response.code().toString, webhookRequest)
} finally if (responseBody != null) responseBody.close()
}
})
}
}

View File

@ -1,25 +0,0 @@
package code.webhook
import akka.actor.{ActorSystem, Props => ActorProps}
import code.util.Helper
import code.util.Helper.MdcLoggable
object WebhookHelperActors extends MdcLoggable {
val props_hostname = Helper.getHostname
val actorName = "Webhook-Actor"
//This method is called in Boot.scala
def startLocalWebhookHelperWorkers(system: ActorSystem): Unit = {
logger.info("Starting local WebhookHelperActors workers")
startWebhookHelperActors(system)
}
def startWebhookHelperActors(actorSystem: ActorSystem): Unit = {
val actorsHelper = Map(
ActorProps[WebhookActor] -> actorName
)
actorsHelper.foreach { a => logger.info(actorSystem.actorOf(a._1, name = a._2)) }
}
}

View File

@ -1,9 +1,8 @@
package code.webhook
import akka.actor.{Actor, ActorLogging}
import code.api.util.ApiTrigger
import code.util.Helper.MdcLoggable
import code.webhook.WebhookActor.{AccountNotificationWebhookRequest, WebhookFailure, WebhookRequest, WebhookResponse}
import code.webhook.WebhookActor.{AccountNotificationWebhookRequest, WebhookRequestTrait}
object WebhookActor {
@ -92,42 +91,25 @@ object WebhookActor {
}
/**
* This Actor process all request/response messages related to Webhooks.
* It's accessible at the North side all over the code.
* Example:
* {
* val actor: ActorSelection = ObpLookupSystem.getWebhookActor()
* }
* We use fire and forget scenario in case of this Actor.
* I.e. we trigger some webhook's event with:
* 1. actor ! Request
* and then send result of event to the Actor:
* 2. actor ! Response
*
*/
class WebhookActor extends Actor with ActorLogging with MdcLoggable {
def receive: Receive = waitingForRequest
private def waitingForRequest: Receive = {
case request@WebhookRequest(trigger, eventId, bankId, accountId, amount, balance) =>
implicit val ec = context.dispatcher
logger.debug("WebhookActor.waitingForRequest.WebhookRequest(request).eventId: " + eventId)
WebhookHttpClient.startEvent(request)
case request@AccountNotificationWebhookRequest(trigger, eventId, bankId, accountId, transactionId, relatedEntities) =>
implicit val ec = context.dispatcher
logger.debug("WebhookActor.waitingForRequest.AccountNotificationWebhookRequest(request).eventId: " + eventId)
WebhookHttpClient.startEvent(request)
case WebhookResponse(status, request) =>
logger.debug("WebhookActor.waitingForRequest.WebhookResponse(status, request).status: " + status)
logger.debug("WebhookActor.waitingForRequest.WebhookResponse(status, request).request.eventId: " + request.eventId)
logger.debug("WebhookActor.waitingForRequest.WebhookResponse(status, request).request.toEventPayload: " + request.toEventPayload)
case WebhookFailure(error, request) =>
logger.debug("WebhookActor.waitingForRequest.WebhookFailure(error, request).error: " + error)
logger.debug("WebhookActor.waitingForRequest.WebhookFailure(error, request).request.eventId:: " + request.eventId)
logger.debug("WebhookActor.waitingForRequest.WebhookFailure(error, request).request.toEventPayload: " + request.toEventPayload)
object WebhookAction extends MdcLoggable {
def webhookRequest(request: WebhookRequestTrait) = {
logger.debug("WebhookActor.webhookRequest(request).eventId: " + request.eventId)
WebhookHttpClient.startEvent(request)
}
def accountNotificationWebhookRequest(request: AccountNotificationWebhookRequest) = {
logger.debug("WebhookActor.accountNotificationWebhookRequest(request).eventId: " + request.eventId)
WebhookHttpClient.startEvent(request)
}
def webhookResponse(status: String,
request: WebhookRequestTrait) = {
logger.debug("WebhookActor.webhookResponse(status, request).status: " + status)
logger.debug("WebhookActor.webhookResponse(status, request).request.eventId: " + request.eventId)
logger.debug("WebhookActor.webhookResponse(status, request).request.toEventPayload: " + request.toEventPayload)
}
def webhookFailure(error: String,
request: WebhookRequestTrait) = {
logger.debug("WebhookActor.webhookFailure(error, request).error: " + error)
logger.debug("WebhookActor.webhookFailure(error, request).request.eventId:: " + request.eventId)
logger.debug("WebhookActor.webhookFailure(error, request).request.toEventPayload: " + request.toEventPayload)
}
}

View File

@ -1,23 +1,14 @@
package code.webhook
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model._
import akka.http.scaladsl.settings.ConnectionPoolSettings
import akka.stream.ActorMaterializer
import akka.util.ByteString
import code.actorsystem.ObpLookupSystem
import code.api.util.ApiTrigger.{OnBalanceChange, OnCreateTransaction, OnCreditTransaction, OnDebitTransaction}
import code.api.util.{ApiTrigger, CustomJsonFormats}
import code.util.Helper.MdcLoggable
import code.webhook.WebhookActor.{AccountNotificationWebhookRequest, WebhookFailure, WebhookRequest, WebhookRequestTrait, WebhookResponse}
import code.webhook.WebhookActor.{AccountNotificationWebhookRequest, WebhookRequest, WebhookRequestTrait}
import net.liftweb
import net.liftweb.json.Extraction
import net.liftweb.mapper.By
import scala.concurrent.Future
import scala.concurrent.duration.DurationInt
import scala.util.{Failure, Success}
import okhttp3.{MediaType, Request, RequestBody}
import code.webhook.OkHttpWebhookClient._
object WebhookHttpClient extends MdcLoggable {
@ -57,7 +48,7 @@ object WebhookHttpClient extends MdcLoggable {
logger.debug("WebhookHttpClient.startEvent(WebhookRequestTrait) i.httpProtocol: " + i.httpProtocol)
val payload = getEventPayload(request)
logger.debug("WebhookHttpClient.startEvent(WebhookRequestTrait) payload: " + payload.toString)
makeRequest(getHttpRequest(i.url, i.httpMethod, i.httpProtocol, getEventPayload(request)), request)
makeAsynchronousRequest(composeRequest(i.url, i.httpMethod, i.httpProtocol, payload), request)
}
}
@ -90,7 +81,7 @@ object WebhookHttpClient extends MdcLoggable {
logger.debug("WebhookHttpClient.startEvent(AccountNotificationWebhookRequest) i.httpProtocol: " + i.httpProtocol)
val payload = getEventPayload(request)
logger.debug("WebhookHttpClient.startEvent(AccountNotificationWebhookRequest) payload: " + payload.toString)
makeRequest(getHttpRequest(i.url, i.httpMethod, i.httpProtocol, payload), request)
makeAsynchronousRequest(composeRequest(i.url, i.httpMethod, i.httpProtocol, payload), request)
}
}
}
@ -107,58 +98,51 @@ object WebhookHttpClient extends MdcLoggable {
* }
*
*/
private def getEventPayload(request: WebhookRequestTrait): RequestEntity = {
def getEventPayload(request: WebhookRequestTrait): Option[String] = {
request.trigger match {
case OnBalanceChange() | OnCreditTransaction() | OnDebitTransaction() | OnCreateTransaction() =>
implicit val formats = CustomJsonFormats.formats
val json = liftweb.json.compactRender(Extraction.decompose(request.toEventPayload))
val entity: RequestEntity = HttpEntity(ContentTypes.`application/json`, json)
entity
Some(json)
case _ =>
HttpEntity.Empty
None
}
}
/**
* This function makes HttpRequest object according to the DB's data related to an account's webhook
* @param uri In most cases it's a URL
* @param method GET/POST/POST/DELETE
* @param httpProtocol HTTP/1.0 / HTTP/1.1 / HTTP/2.0
* @param entity For instance:
* {
* "event_name":"OnCreditTransaction",
* "event_id":"fc7e4a71-5ff1-4006-95bb-7fd9e4adaef9",
* "bank_id":"gh.29.uk.x",
* "account_id":"private_01",
* "amount":"50.00 EUR",
* "balance":"739.00 EUR"
* }
* Please note it's empty in case of GET
* @return HttpRequest object
*/
private def getHttpRequest(uri: String, method: String, httpProtocol: String, entity: RequestEntity = HttpEntity.Empty): HttpRequest = {
* This function makes HttpRequest object according to the DB's data related to an account's webhook
* @param uri In most cases it's a URL
* @param method GET/POST/POST/DELETE
* @param httpProtocol HTTP/1.0 / HTTP/1.1 / HTTP/2.0
* @param json For instance:
* {
* "event_name":"OnCreditTransaction",
* "event_id":"fc7e4a71-5ff1-4006-95bb-7fd9e4adaef9",
* "bank_id":"gh.29.uk.x",
* "account_id":"private_01",
* "amount":"50.00 EUR",
* "balance":"739.00 EUR"
* }
* Please note it's empty in case of GET
* @return HttpRequest object
*/
def composeRequest(uri: String, method: String, httpProtocol: String, json: Option[String]): Request = {
val jsonType = MediaType.parse("application/json; charset=utf-8");
val body = RequestBody.create(jsonType, json.getOrElse(""))
method match {
case m: String if m.toUpperCase == "GET" =>
HttpRequest(uri = uri, method = GET, protocol = getHttpProtocol(httpProtocol))
new Request.Builder().url(uri).build
case m: String if m.toUpperCase == "POST" =>
HttpRequest(uri = uri, method = POST, entity = entity, protocol = getHttpProtocol(httpProtocol))
new Request.Builder().url(uri).post(body).build
case m: String if m.toUpperCase == "PUT" =>
HttpRequest(uri = uri, method = PUT, entity = entity, protocol = getHttpProtocol(httpProtocol))
new Request.Builder().url(uri).put(body).build
case m: String if m.toUpperCase == "DELETE" =>
HttpRequest(uri = uri, method = DELETE, entity = entity, protocol = getHttpProtocol(httpProtocol))
new Request.Builder().url(uri).delete(body).build
case _ =>
HttpRequest(uri = uri, method = GET, protocol = getHttpProtocol(httpProtocol))
new Request.Builder().url(uri).build
}
}
private def getHttpProtocol(httpProtocol: String): HttpProtocol = {
httpProtocol match {
case m: String if m.toUpperCase == "HTTP/1.0" => HttpProtocols.`HTTP/1.0`
case m: String if m.toUpperCase == "HTTP/1.1" => HttpProtocols.`HTTP/1.1`
case m: String if m.toUpperCase == "HTTP/2.0" => HttpProtocols.`HTTP/2.0`
case _ => HttpProtocols.`HTTP/1.1`
}
}
private def logEvent(request: WebhookRequestTrait): Unit = {
logger.debug("TRIGGER: " + request.trigger)
@ -173,76 +157,11 @@ object WebhookHttpClient extends MdcLoggable {
logger.debug("RELATED_ENTITIES: " + request.asInstanceOf[AccountNotificationWebhookRequest].relatedEntities)
}else{
}
}
lazy implicit val system = ObpLookupSystem.obpLookupSystem
implicit lazy val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit lazy val executionContext = system.dispatcher
// The Actor which has sent the request.
// We need to respond to it after we finish an event.
lazy val requestActor = ObpLookupSystem.getWebhookActor()
private def makeRequest(httpRequest: HttpRequest, request: WebhookRequestTrait): Unit = {
makeHttpRequest(httpRequest).onComplete {
case Success(res@HttpResponse(status, headers, entity, protocol)) =>
requestActor ! WebhookResponse(status.toString(), request)
res.discardEntityBytes()
case Failure(error) =>
requestActor ! WebhookFailure(error.getMessage, request)
}
}
private lazy val poolSettingsWithHttpsProxy =
ConnectionPoolSettings.apply(system)
/*
# The minimum duration to backoff new connection attempts after the previous connection attempt failed.
#
# The pool uses an exponential randomized backoff scheme. After the first failure, the next attempt will only be
# tried after a random duration between the base connection backoff and twice the base connection backoff. If that
# attempt fails as well, the next attempt will be delayed by twice that amount. The total delay is capped using the
# `max-connection-backoff` setting.
#
# The backoff applies for the complete pool. I.e. after one failed connection attempt, further connection attempts
# to that host will backoff for all connections of the pool. After the service recovered, connections will come out
# of backoff one by one due to the random extra backoff time. This is to avoid overloading just recently recovered
# services with new connections ("thundering herd").
#
# Example: base-connection-backoff = 100ms, max-connection-backoff = 10 seconds
# - After 1st failure, backoff somewhere between 100ms and 200ms
# - After 2nd, between 200ms and 400ms
# - After 3rd, between 200ms and 400ms
# - After 4th, between 400ms and 800ms
# - After 5th, between 800ms and 1600ms
# - After 6th, between 1600ms and 3200ms
# - After 7th, between 3200ms and 6400ms
# - After 8th, between 5000ms and 10 seconds (max capped by max-connection-backoff, min by half of that)
# - After 9th, etc., stays between 5000ms and 10 seconds
#
# This setting only applies to the new pool implementation and is ignored for the legacy one.
*/
.withBaseConnectionBackoff(1.second)
/*
# Maximum backoff duration between failed connection attempts. For more information see the above comment for the
# `base-connection-backoff` setting.
#
# This setting only applies to the new pool implementation and is ignored for the legacy one.
*/
.withMaxConnectionBackoff(1.minute)
/*
# The maximum number of times failed requests are attempted again,
# (if the request can be safely retried) before giving up and returning an error.
# Set to zero to completely disable request retries.
*/
.withMaxRetries(5)
private def makeHttpRequest(httpRequest: HttpRequest): Future[HttpResponse] =
Http().singleRequest(request = httpRequest, settings = poolSettingsWithHttpsProxy)
def main(args: Array[String]): Unit = {
val uri = "https://www.openbankproject.com"
val uri = "https://publicobject.com/helloworld.txt"
val request = WebhookRequest(
trigger=ApiTrigger.onBalanceChange ,
eventId="418044f2-f74e-412f-a4e1-a78cdacdef9c",
@ -251,34 +170,25 @@ object WebhookHttpClient extends MdcLoggable {
amount="10000",
balance="21000"
)
makeRequest(getHttpRequest(uri, "GET", "HTTP/1.1"), request)
makeAsynchronousRequest(
composeRequest(uri, "GET", "HTTP/1.1", None),
request
)
implicit val formats = CustomJsonFormats.formats
case class User(name: String, job: String)
val user = User("morpheus", "leader")
val json = liftweb.json.compactRender(Extraction.decompose(user))
val entity: RequestEntity = HttpEntity(ContentTypes.`application/json`, json)
makeHttpRequest(getHttpRequest("https://reqres.in/api/users", "POST", "HTTP/1.1", entity)) map {
`POST response` =>
org.scalameta.logger.elem(`POST response`.status)
`POST response`.entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body =>
val `Got POST response, body: ` = body.utf8String
org.scalameta.logger.elem(`Got POST response, body: `)
}
}
makeAsynchronousRequest(
composeRequest("https://reqres.in/api/users", "POST", "HTTP/1.1", Some(json)),
request)
val user2 = User("morpheus", "zion resident")
val json2 = liftweb.json.compactRender(Extraction.decompose(user2))
val entity2: RequestEntity = HttpEntity(ContentTypes.`application/json`, json2)
makeHttpRequest(getHttpRequest("https://reqres.in/api/users", "PUT", "HTTP/1.1", entity2)) map {
`PUT response` =>
org.scalameta.logger.elem(`PUT response`.status)
`PUT response`.entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body =>
val `Got PUT response, body: ` = body.utf8String
org.scalameta.logger.elem(`Got PUT response, body: `)
}
}
makeAsynchronousRequest(
composeRequest("https://reqres.in/api/users/2", "PUT", "HTTP/1.1", Some(json2)),
request
)
}
}

View File

@ -1,6 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head><title>Plain HTML</title></head>
<head>
<title>Plain HTML</title>
<script src="/media/js/jquery.min.js" type="text/javascript"></script>
</head>
<h1>I am an Example HTML, no Liftweb involved. </h1>
with a <a href="http://www.example.com">link</a>
<h1>Link to static</h1><a href="/static">static image</a>

View File

@ -1,6 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head><title>Example HTML</title></head>
<head>
<script src="/media/js/jquery.min.js" type="text/javascript"></script>
<title>Example HTML</title>
</head>
<body bgcolor="green">
<h1>I am some Example HTML</h1>
with a <a href="https://static.openbankproject.com/images/OBP/OBP_full_stack_web.png">image from static</a>

View File

@ -31,12 +31,11 @@ import java.util.ResourceBundle
import code.api.oauth1a.OauthParams._
import code.api.util.APIUtil.OAuth._
import code.api.util.ErrorMessages
import code.api.util.ErrorMessages._
import code.api.util.{APIUtil, ErrorMessages}
import code.consumer.Consumers
import code.loginattempts.LoginAttempt
import code.model.dataAccess.{AuthUser, ResourceUser}
import code.model.{Consumer => OBPConsumer, Token => OBPToken}
import code.setup.ServerSetup
import code.util.Helper.MdcLoggable
import dispatch.Defaults._
@ -322,35 +321,33 @@ class OAuthTest extends ServerSetup {
}
}
feature("Login in locked") {
feature("Login is locked") {
scenario("valid Username, invalid password, login in too many times. The username will be locked", Verifier, Oauth) {
Given("we will use a valid request token to get the valid username and password")
val reply = getRequestToken(consumer, selfCallback)
val requestToken = extractToken(reply.body)
Then("we set the valid username, invalid password and try more than 5 times")
Then("we set the valid username, invalid password and try more than 2 times")
setPropsValues("max.bad.login.attempts"-> "2")
val invalidPassword = "wrongpassword"
var verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
verifier = getVerifier(requestToken.value, user1.username.get, invalidPassword)
Then("we should get a locked account verifier")
verifier.asInstanceOf[Failure].msg.contains(ErrorMessages.UsernameHasBeenLocked)
verifier.asInstanceOf[Failure].msg.contains(ErrorMessages.UsernameHasBeenLocked) should equal (true)
Then("We login in with valid username and password, it will still be failed")
verifier = getVerifier(requestToken.value, user1.username.get, user1Password)
Then("we should get a locked account verifier")
verifier.asInstanceOf[Failure].msg.contains(ErrorMessages.UsernameHasBeenLocked)
verifier.asInstanceOf[Failure].msg.contains(ErrorMessages.UsernameHasBeenLocked) should equal (true)
Then("We unlock the username")
LoginAttempt.resetBadLoginAttempts(user1.username.get)
setPropsValues("max.bad.login.attempts"-> "5")
}
}

View File

@ -98,7 +98,6 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Match
m == Nonce || m == code.model.Token || m == code.model.Consumer || m == AuthUser || m == ResourceUser
}
//drop database tables before
//MongoDB.getDb(DefaultMongoIdentifier).foreach(_.dropDatabase())
ToSchemify.models.filterNot(exclusion).foreach(_.bulkDelete_!!())
ToSchemify.modelsRemotedata.filterNot(exclusion).foreach(_.bulkDelete_!!())
//we need to delete the test uses manully here.

View File

@ -0,0 +1,58 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH
Osloerstrasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.api.v5_1_0
import okhttp3.{OkHttpClient, Request}
class IndexPageTest extends V510ServerSetup {
/**
* Test tags
* Example: To run tests with tag "getPermissions":
* mvn test -D tagsToInclude
*
* This is made possible by the scalatest maven plugin
*/
feature("Test the response of the page /index.html ") {
scenario("We create the apiCollection get All API collections back") {
When("We make a request ")
val client = new OkHttpClient
val request = new Request.Builder().url(s"http://${server.host}:${server.port}/index.html").build
val responseFirst = client.newCall(request).execute
val startTime: Long = System.currentTimeMillis()
val responseSecond = client.newCall(request).execute
val endTime: Long = System.currentTimeMillis()
Then("We should get a 200")
responseSecond.code should equal(200)
val duration: Long = endTime - startTime
And(s"And duration($duration) is less than 1000 ms")
duration should be <= 1000L
}
}
}

View File

@ -1,107 +0,0 @@
package code.setup
import java.util.Date
import code.model._
import code.model.dataAccess._
import com.mongodb.QueryBuilder
import net.liftweb.util.Helpers._
import code.api.util.ErrorMessages._
import com.openbankproject.commons.model.{AccountId, Bank, BankAccount, BankId}
import scala.math.BigDecimal
import scala.math.BigDecimal.RoundingMode
import scala.util.Random._
/**
* This trait is for Liftweb record, link to MangoDB....
*/
trait LocalRecordConnectorTestSetup extends TestConnectorSetupWithStandardPermissions {
override protected def createBank(id : String) : Bank = {
HostedBank.createRecord.
name(randomString(5)).
alias(randomString(5)).
permalink(id).
national_identifier(randomString(5)).
save(true)
}
override protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {
val q = QueryBuilder.start(HostedBank.permalink.name).is(bankId.value).get()
val hostedBank = HostedBank.find(q).openOrThrowException(attemptedToOpenAnEmptyBox)
Account.createRecord.
accountBalance(900000000).
holder(randomString(4)).
accountNumber(randomString(4)).
kind(randomString(4)).
accountName(randomString(4)).
permalink(accountId.value).
bankID(hostedBank.id.get).
accountLabel(randomString(4)).
accountCurrency(currency).
save(true)
}
override protected def createTransaction(account: BankAccount, startDate: Date, finishDate: Date) = {
val thisAccountBank = OBPBank.createRecord.
IBAN(randomString(5)).
national_identifier(account.nationalIdentifier).
name(account.bankName)
val thisAccount = OBPAccount.createRecord.
holder(account.accountHolder).
number(account.number).
kind(account.accountType).
bank(thisAccountBank)
val otherAccountBank = OBPBank.createRecord.
IBAN(randomString(5)).
national_identifier(randomString(5)).
name(randomString(5))
val otherAccount = OBPAccount.createRecord.
holder(randomString(5)).
number(randomString(5)).
kind(randomString(5)).
bank(otherAccountBank)
val transactionAmount = BigDecimal(nextDouble * 1000).setScale(2,RoundingMode.HALF_UP)
val newBalance : OBPBalance = OBPBalance.createRecord.
currency(account.currency).
amount(account.balance + transactionAmount)
val newValue : OBPValue = OBPValue.createRecord.
currency(account.currency).
amount(transactionAmount)
val details ={
OBPDetails
.createRecord
.kind(randomString(5))
.posted(startDate)
.other_data(randomString(5))
.new_balance(newBalance)
.value(newValue)
.completed(finishDate)
.label(randomString(5))
}
val transaction = OBPTransaction.createRecord.
this_account(thisAccount).
other_account(otherAccount).
details(details)
val env = OBPEnvelope.createRecord.
obp_transaction(transaction).save(true)
//slightly ugly
account.asInstanceOf[Account].accountBalance(newBalance.amount.get).accountLastUpdate(now).save(true)
env.save(true)
}
override protected def createTransactionRequest(account: BankAccount) = Nil
}

View File

@ -8,8 +8,6 @@ import code.model.dataAccess._
import code.views.Views
import com.openbankproject.commons.model._
import net.liftweb.mapper.MetaMapper
import net.liftweb.mongodb._
import net.liftweb.util.DefaultConnectionIdentifier
import net.liftweb.util.Helpers._
/**
@ -40,9 +38,6 @@ trait TestConnectorSetupWithStandardPermissions extends TestConnectorSetup {
protected def wipeTestData(): Unit = {
//drop the mongo Database after each test
MongoDB.getDb(DefaultConnectionIdentifier).foreach(_.dropDatabase())
//returns true if the model should not be wiped after each test
def exclusion(m : MetaMapper[_]) = {
m == Nonce || m == Token || m == Consumer || m == AuthUser || m == ResourceUser

View File

@ -41,14 +41,14 @@ import net.liftweb.http.provider.HTTPParam
import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers}
class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with PropsReset {
val DefaultFromDateString = APIUtil.epochTimeString
val DefaultToDateString = APIUtil.DefaultToDateString
val startDateString = DefaultFromDateString
val startDateStringWrongFormat = "Wrong Date Format"
val endDateString = DefaultToDateString
val endDateStringWrongFormat = "Wrong Date Format"
val inputStringDateFormat = DateWithMsFormat
val DefaultFromDateString = APIUtil.epochTimeString
val DefaultToDateString = APIUtil.DefaultToDateString
val startDateObject: Date = DateWithMsFormat.parse(DefaultFromDateString)
val endDateObject: Date = DateWithMsFormat.parse(DefaultToDateString)
ZonedDateTime.now(ZoneId.of("UTC"))
@ -239,7 +239,7 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop
val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List(s"$DateWithMsExampleString")))
val startTime = OBPFromDate(theEpochTime)
val returnValue = getFromDate(httpParams)
returnValue shouldBe a[Full[OBPFromDate]]
returnValue.toString should startWith("Full(OBPFromDate")
val currentTime = OBPFromDate(theEpochTime)
val beWithinTolerance = be >= startTime and be <= currentTime
@ -251,7 +251,7 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop
val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List("wrongValue")))
val startTime = OBPFromDate(theEpochTime)
val returnValue = getFromDate(httpParams)
returnValue shouldBe a[Full[OBPFromDate]]
returnValue.toString should startWith("Full(OBPFromDate")
val currentTime = OBPFromDate(theEpochTime)
val beWithinTolerance = be >= startTime and be <= currentTime
@ -293,7 +293,7 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop
val startTime = OBPToDate(DefaultToDate)
val returnValue = getToDate(httpParams)
returnValue shouldBe a[Full[OBPToDate]]
returnValue.toString should startWith("Full(OBPToDate")
val currentTime = OBPToDate(DefaultToDate)
val beWithinTolerance = be >= startTime and be <= currentTime
@ -307,7 +307,7 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop
val startTime = OBPToDate(DefaultToDate)
val returnValue = getToDate(httpParams)
returnValue shouldBe a[Full[OBPToDate]]
returnValue.toString should startWith("Full(OBPToDate")
val currentTime = OBPToDate(DefaultToDate)
val beWithinTolerance = be >= startTime and be <= currentTime

View File

@ -44,7 +44,7 @@ import java.util.Date
*
*
* 3 RelationShips:
* 1)When `Sign up` new user --> create AuthUser --> call AuthUser.save() --> create ResourceUser user.
* 1)When `Sign up` new user --> create AuthUser --> call AuthUser.save --> create ResourceUser user.
* They share the same username and email.
* 2)AuthUser `user` field as the Foreign Key to link to Resource User.
* one AuthUser <---> one ResourceUser

View File

@ -32,7 +32,7 @@ object JsonSerializers {
override def lookupParameterNames(constructor: Constructor[_]): Traversable[String] = try {
defaultFormats.parameterNameReader.lookupParameterNames(constructor)
} catch {
case _ => constructor.getParameters.map(_.getName)
case _ : Throwable => constructor.getParameters.map(_.getName)
}
}
}

View File

@ -11,12 +11,12 @@
<inceptionYear>2011</inceptionYear>
<properties>
<scala.version>2.12</scala.version>
<scala.compiler>2.12.10</scala.compiler>
<scala.compiler>2.12.12</scala.compiler>
<akka.version>2.5.32</akka.version>
<akka-streams-kafka.version>2.0.5</akka-streams-kafka.version>
<kafka.version>1.1.0</kafka.version>
<avro.version>1.8.2</avro.version>
<lift.version>3.4.1</lift.version>
<lift.version>3.5.0</lift.version>
<jetty.version>9.4.50.v20221201</jetty.version>
<log4j.version>2.17.1</log4j.version>
<obp-ri.version>2016.11-RC6-SNAPSHOT</obp-ri.version>