Merge remote-tracking branch 'Simon/develop' into develop

# Conflicts:
#	obp-api/src/main/scala/code/api/util/migration/MigrationOfMappedUserAuthContext.scala
#	obp-api/src/main/scala/code/api/util/migration/MigrationOfMappedUserAuthContextUpdate.scala
This commit is contained in:
hongwei 2020-06-22 10:58:33 +02:00
commit 77ac521904
17 changed files with 112 additions and 30 deletions

View File

@ -245,6 +245,9 @@ class Boot extends MdcLoggable {
}
}
}
logger.info("Mapper database info: ")
logger.info(Migration.DbFunction.mapperDatabaseInfo())
import java.security.SecureRandom
val rand = new SecureRandom(SecureRandom.getSeed(20))

View File

@ -467,6 +467,7 @@ object ErrorMessages {
// MethodRouting Exceptions (OBP-7XXXX)
val InvalidBankIdRegex = "OBP-70001: Incorrect regex for bankIdPattern."
val MethodRoutingNotFoundByMethodRoutingId = "OBP-70002: MethodRouting not found. Please specify a valid value for method_routing_id."
val MethodRoutingNameAlreadyUsed = "OBP-70003: Method Routing Name already used."
// Cascade Deletion Exceptions (OBP-8XXXX)
val CouldNotDeleteCascade = "OBP-80001: Could not delete cascade."

View File

@ -1696,6 +1696,13 @@ object NewStyle {
def getMethodRoutingsByMethdName(methodName: Box[String]): Future[List[MethodRoutingT]] = Future {
this.getMethodRoutings(methodName.toOption)
}
def checkMethodRoutingAlreadyExists(methodName: String, callContext:Option[CallContext]): OBPReturnType[Boolean] = Future {
val exists = this.getMethodRoutings(Some(methodName)).isEmpty match {
case true => Full(true)
case false => Empty
}
(unboxFullOrFail(exists, callContext, s"$MethodRoutingNameAlreadyUsed"), callContext)
}
def getCardAttributeById(cardAttributeId: String, callContext:Option[CallContext]) =
Connector.connector.vend.getCardAttributeById(cardAttributeId: String, callContext:Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, s"$CardAttributeNotFound Current CardAttributeId($cardAttributeId)"), i._2)

View File

@ -6,6 +6,7 @@ import java.time.{ZoneId, ZonedDateTime}
import code.api.util.APIUtil
import code.api.util.migration.Migration.{DbFunction, saveLog}
import code.consent.MappedConsent
import net.liftweb.common.Full
import net.liftweb.mapper.{DB, Schemifier}
import net.liftweb.util.DefaultConnectionIdentifier
@ -24,7 +25,12 @@ object MigrationOfMappedConsent {
val executedSql =
DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) {
() => "ALTER TABLE mappedconsent ALTER COLUMN mjsonwebtoken type text;"
APIUtil.getPropsValue("db.driver") match {
case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") =>
() => "ALTER TABLE mappedconsent ALTER COLUMN mjsonwebtoken text;"
case _ =>
() => "ALTER TABLE mappedconsent ALTER COLUMN mjsonwebtoken type text;"
}
}
val endDate = System.currentTimeMillis()

View File

@ -24,7 +24,7 @@ object MigrationOfMappedUserAuthContext {
val executedSql =
DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) {
() => "DROP INDEX if exists mappeduserauthcontext_muserid_mkey;"
() => "DROP INDEX IF EXISTS mappeduserauthcontext_muserid_mkey;"
}
val endDate = System.currentTimeMillis()

View File

@ -24,7 +24,7 @@ object MigrationOfMappedUserAuthContextUpdate {
val executedSql =
DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) {
() => "DROP INDEX if exists mappeduserauthcontextupdate_muserid_mkey;"
() => "DROP INDEX IF EXISTS mappeduserauthcontextupdate_muserid_mkey;"
}
val endDate = System.currentTimeMillis()

View File

@ -4315,6 +4315,7 @@ trait APIMethods310 {
Pattern.compile(postedData.bankIdPattern.get)
}
}
_ <- NewStyle.function.checkMethodRoutingAlreadyExists(methodName, callContext)
Full(methodRouting) <- NewStyle.function.createOrUpdateMethodRouting(postedData)
} yield {
val commonsData: MethodRoutingCommons = methodRouting

View File

@ -410,6 +410,14 @@ trait Connector extends MdcLoggable {
* @return
*/
def getUser(name: String, password: String): Box[InboundUser]= Failure(setUnimplementedError)
/**
* This method is for checking external User via connector
* @param name
* @param password
* @return
*/
def checkExternalUserCredentials(name: String, password: String): Box[InboundExternalUser] = Failure(setUnimplementedError)
/**
* This is a helper method

View File

@ -396,6 +396,44 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable {
val req = OutBound(name, password)
val response: Future[Box[InBound]] = sendRequest[InBound]("obp_get_user", req, callContext)
response.map(convertToTuple[InboundUser](callContext))
}
messageDocs += getUserDoc
def checkExternalUserCredentialsDoc = MessageDoc(
process = "obp.checkExternalUserCredentials",
messageFormat = messageFormat,
description = "Check External User Credentials",
outboundTopic = None,
inboundTopic = None,
exampleOutboundMessage = (
OutBoundGetExternalUser(
name=usernameExample.value,
password="string")
),
exampleInboundMessage =
InBoundGetExternalUser(
status=MessageDocsSwaggerDefinitions.inboundStatus,
data= InboundExternalUser(
aud = "String",
exp = "String",
iat = "String",
iss = "String",
sub = "String",
azp = Some("String"),
email=Some(emailExample.value),
emailVerified = Some("String"),
name = Some("String")
)
),
adapterImplementation = Some(AdapterImplementation("- Core", 1))
)
override def checkExternalUserCredentials(name: String, password: String): Box[InboundExternalUser] = {
import com.openbankproject.commons.dto.{OutBoundGetExternalUser => OutBound, InBoundGetExternalUser => InBound}
val callContext: Option[CallContext] = None
val req = OutBound(name, password)
val response: Future[Box[InBound]] = sendRequest[InBound]("obp_check_external_user_credentials", req, callContext)
response.map(convertToTuple[InboundExternalUser](callContext))
}
messageDocs += getBankAccountOldDoc

View File

@ -32,7 +32,7 @@ object StoredProcedureUtils {
val initialSize = APIUtil.getPropsAsIntValue("stored_procedure_connector.poolInitialSize", 5)
val maxSize = APIUtil.getPropsAsIntValue("stored_procedure_connector.poolMaxSize", 20)
val timeoutMillis = APIUtil.getPropsAsLongValue("stored_procedure_connector.poolConnectionTimeoutMillis", 3000L)
val validationQuery = APIUtil.getPropsValue("stored_procedure_connector.poolValidationQuery", "select 1 from dual")
val validationQuery = APIUtil.getPropsValue("stored_procedure_connector.poolValidationQuery", "select 1")
val poolFactoryName = APIUtil.getPropsValue("stored_procedure_connector.poolFactoryName", "commons-dbcp2")

View File

@ -81,7 +81,7 @@ class MethodRouting extends MethodRoutingT with LongKeyedMapper[MethodRouting] w
}
object IsBankIdExactMatch extends MappedBoolean(this)
object ConnectorName extends MappedString(this, 255)
object Parameters extends MappedString(this, 5000)
object Parameters extends MappedText(this)
override def methodRoutingId: Option[String] = Option(MethodRoutingId.get)
override def methodName: String = MethodName.get

View File

@ -450,7 +450,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
val extedndedExcludeImplementedByPartialFunctionsQueries = extendCurrentQuery(excludeImplementedByPartialFunctionsNumberSet.size)
for {
dbQuery <- Full("SELECT count(*) as count, consumer.id as consumerprimaryid, mappedmetric.appname as appname, consumer.developeremail as email " +
dbQuery <- Full("SELECT count(*) as count, consumer.id as consumerprimaryid, mappedmetric.appname as appname, consumer.developeremail as email, consumer.consumerid as consumerid " +
"FROM mappedmetric, consumer " +
"WHERE mappedmetric.appname = consumer.name " +
"AND date_c >= ? " +
@ -509,10 +509,10 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
topConsumers <- tryo(resultSet._2.map(
a =>
TopConsumer(
if (a(0) != null) a(0).toInt else 0,
if (a(1) != null) a(1).toString else "",
if (a(2) != null) a(2).toString else "",
if (a(3) != null) a(3).toString else ""
count = if (a(0) != null) a(0).toInt else 0,
consumerId = if (a(4) != null) a(4).toString else "",
appName = if (a(2) != null) a(2).toString else "",
developerEmail = if (a(3) != null) a(3).toString else ""
))) ?~! {
logger.error(s"getTopConsumersBox.create TopConsumer class error. Here is the result from database $resultSet ");
s"$UnknownError getTopConsumersBox.create TopApi class error. "

View File

@ -664,17 +664,7 @@ import net.liftweb.util.Helpers._
def getUserFromConnector(name: String, password: String):Box[AuthUser] = {
Connector.connector.vend.getUser(name, password) match {
case Full(InboundUser(extEmail, extPassword, extUsername)) => {
logger.info("external user authenticated. login redir: " + loginRedirect.get)
val redir = loginRedirect.get match {
case Full(url) =>
loginRedirect(Empty)
url
case _ =>
homePage
}
val extProvider = connector
val user = findUserByUsernameLocally(name) match {
// Check if the external user is already created locally
case Full(user) if user.validated_?
@ -685,9 +675,9 @@ import net.liftweb.util.Helpers._
user
}
// If not found, create new user
case _ => {
// Create AuthUser using fetched data from Kafka
// If not found, create a new user
case _ =>
// Create AuthUser using fetched data from connector
// assuming that user's email is always validated
logger.info("external user "+ extEmail +" does not exist locally, creating one")
val newUser = AuthUser.create
@ -698,11 +688,8 @@ import net.liftweb.util.Helpers._
.password(generateUUID())
.provider(extProvider)
.validated(true)
// Save the user in order to be able to log in
newUser.save()
// Return created user
newUser
}
newUser.saveMe()
}
Full(user)
}
@ -784,7 +771,7 @@ def restoreSomeSessions(): Unit = {
}
}
// Check if user came from kafka/obpjvm and
// Check if user came from kafka/obpjvm/stored_procedure and
// if User is NOT locked. Then check username and password
// from connector in case they changed on the south-side
case Full(user) if user.validated_? &&
@ -901,10 +888,10 @@ def restoreSomeSessions(): Unit = {
/**
* The user authentications is not exciting in obp side, it need get the user from south-side
* The user authentications is not exciting in obp side, it need get the user via connector
*/
def testExternalPassword(usernameFromGui: Box[String], passwordFromGui: Box[String]): Box[Boolean] = {
if (connector.startsWith("kafka") || connector == "obpjvm") {
if (connector.startsWith("kafka") || connector == "obpjvm" || connector == "stored_procedure") {
val res = for {
username <- usernameFromGui
password <- passwordFromGui

View File

@ -241,6 +241,7 @@ object Helper{
*/
val matchKafkaVersion = "kafka_v([0-9a-zA-Z_]+)".r
val matchAnyKafka = "^kafka.*$".r
val matchAnyStoredProcedure = "^stored_procedure.*$".r
/**
* change the TimeZone to the current TimeZOne

View File

@ -5,6 +5,7 @@ import code.api.APIFailureNewStyle
import code.api.util.APIUtil.fullBoxOrException
import code.api.util.ErrorMessages.CouldNotDeleteCascade
import code.bankconnectors.Connector
import code.cards.MappedPhysicalCard
import code.model.dataAccess.{MappedBankAccount, MappedBankAccountData}
import code.views.system.{AccountAccess, ViewDefinition}
import code.webhook.MappedAccountWebhook
@ -27,6 +28,7 @@ object DeleteAccountCascade {
deleteAccountAttributes(bankId, accountId) ::
deleteAccountWebhooks(bankId, accountId) ::
deleteBankAccountData(bankId, accountId) ::
deleteCards(accountId) ::
deleteAccount(bankId, accountId) ::
Nil
doneTasks.forall(_ == true)
@ -49,6 +51,17 @@ object DeleteAccountCascade {
)
}
private def deleteCards(accountId: AccountId): Boolean = {
MappedBankAccount.findAll(
By(MappedBankAccount.theAccountId, accountId.value)
) map (
account =>
MappedPhysicalCard.bulkDelete_!!(
By(MappedPhysicalCard.mAccount, account.id.get)
)
)
}.forall(_ == true)
private def deleteBankAccountData(bankId: BankId, accountId: AccountId): Boolean = {
MappedBankAccountData.bulkDelete_!!(
By(MappedBankAccountData.bankId, bankId.value),

View File

@ -452,6 +452,11 @@ case class OutBoundGetUser(name: String, password: String) extends TopicTrait
case class InBoundGetUser(status: Status, data: InboundUser) extends InBoundTrait[InboundUser] {
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
}
case class OutBoundGetExternalUser(name: String, password: String) extends TopicTrait
case class InBoundGetExternalUser(status: Status, data: InboundExternalUser) extends InBoundTrait[InboundExternalUser] {
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
}
//create bound case classes

View File

@ -788,6 +788,18 @@ case class InboundUser(
displayName: String
)
case class InboundExternalUser(
aud: String,
exp: String,
iat: String,
iss: String,
sub: String,
azp: Option[String],
email: Option[String],
emailVerified: Option[String],
name: Option[String]
)
case class ErrorMessage(code: Int, message: String)