Merge pull request #2207 from constantine2nd/develop

The results of Create Consumer page should be copy and paste  friendly
This commit is contained in:
Simon Redfern 2023-03-27 16:22:49 +02:00 committed by GitHub
commit a3ddbcdda7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 2142 additions and 6 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
package code.api.util
import net.liftweb.common.Full
import net.liftweb.http.LiftRules
import net.liftweb.json.parse
object CurrencyUtil {
implicit val formats = CustomJsonFormats.formats
case class CurrenciesJson(currencies: List[CurrencyJson])
case class CurrencyJson(entity: String,
currency: String,
alphanumeric_code: Option[String],
number_code: Option[Int],
minor_unit: Option[String]
)
def getCurrencies(): Option[CurrenciesJson] = {
val filename = s"/currency/currency.json"
val source = LiftRules.loadResourceAsString(filename)
source match {
case Full(payload) =>
val currencies = parse(payload).extract[CurrenciesJson]
Some(currencies)
case _ => None
}
}
def getCurrencyCodes(): List[String] = {
getCurrencies.map(_.currencies
.filter(_.alphanumeric_code.isDefined)
.map(_.alphanumeric_code.getOrElse(""))).headOption.getOrElse(Nil)
}
def main(args: Array[String]): Unit = {
println(getCurrencyCodes())
}
}

View File

@ -565,7 +565,7 @@ object JSONFactory500 {
stringOrNull(bank.fullName),
stringOrNull(bank.logoUrl),
stringOrNull(bank.websiteUrl),
routings.filter(a => stringOrNull(a.address) != null),
routings,
Option(
attributes.filter(_.isActive == Some(true)).map(a => BankAttributeBankResponseJsonV400(
name = a.name,

View File

@ -7,7 +7,7 @@ import code.api.util.APIUtil._
import code.api.util.ApiRole._
import code.api.util.ApiTag._
import code.api.util.ErrorMessages.{$UserNotLoggedIn, BankNotFound, ConsentNotFound, InvalidJsonFormat, UnknownError, UserNotFoundByUserId, UserNotLoggedIn, _}
import code.api.util.{APIUtil, ApiRole, NewStyle, X509}
import code.api.util.{APIUtil, ApiRole, CurrencyUtil, NewStyle, X509}
import code.api.util.NewStyle.HttpCode
import code.api.v3_0_0.JSONFactory300.createAggregateMetricJson
import code.api.v3_1_0.ConsentJsonV310
@ -16,6 +16,7 @@ import code.api.v4_0_0.{JSONFactory400, PostApiCollectionJson400}
import code.consent.Consents
import code.loginattempts.LoginAttempt
import code.metrics.APIMetrics
import code.model.dataAccess.MappedBankAccount
import code.transactionrequests.TransactionRequests.TransactionRequestTypes.{apply => _}
import code.userlocks.UserLocksProvider
import code.users.Users
@ -218,6 +219,41 @@ trait APIMethods510 {
(JSONFactory510.getAccountAccessUniqueIndexCheck(groupedRows), HttpCode.`200`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(
accountCurrencyCheck,
implementedInApiVersion,
nameOf(accountCurrencyCheck),
"GET",
"/management/system/integrity/account-currency-check",
"Check for Sensible Currencies",
s"""Check for sensible currencies at account access table.
|
|${authenticationRequiredMessage(true)}
|""".stripMargin,
EmptyBody,
CheckSystemIntegrityJsonV510(true),
List(
$UserNotLoggedIn,
UserHasMissingRoles,
UnknownError
),
List(apiTagSystemIntegrity, apiTagNewStyle),
Some(canGetSystemIntegrity :: Nil)
)
lazy val accountCurrencyCheck: OBPEndpoint = {
case "management" :: "system" :: "integrity" :: "account-currency-check" :: Nil JsonGet _ => {
cc =>
for {
currenciess: List[String] <- Future {
MappedBankAccount.findAll().map(_.accountCurrency.get).distinct
}
currentCurrencies: List[String] <- Future { CurrencyUtil.getCurrencyCodes() }
} yield {
(JSONFactory510.getSensibleCurrenciesCheck(currenciess, currentCurrencies), HttpCode.`200`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(

View File

@ -90,6 +90,15 @@ object JSONFactory510 {
success = success,
debug_info = debugInfo
)
}
def getSensibleCurrenciesCheck(currencies: List[String], currentCurrencies: List[String]): CheckSystemIntegrityJsonV510 = {
val incorrectCurrencies: List[String] = currencies.filterNot(c => currentCurrencies.contains(c))
val success = incorrectCurrencies.size == 0
val debugInfo = if(success) None else Some(s"Incorrect currencies: ${incorrectCurrencies.mkString(",")}")
CheckSystemIntegrityJsonV510(
success = success,
debug_info = debugInfo
)
}
def getApiInfoJSON(apiVersion : ApiVersion, apiVersionStatus: String) = {

View File

@ -1161,7 +1161,12 @@ def restoreSomeSessions(): Unit = {
//If there is NO the username, throw the error message.
case Empty =>
S.error(Helper.i18n("invalid.login.credentials"))
case _ =>
case unhandledCase =>
logger.error("------------------------------------------------------")
logger.error(s"username from GUI: $usernameFromGui")
logger.error("An unexpected login error occurred:")
logger.error(unhandledCase)
logger.error("------------------------------------------------------")
LoginAttempt.incrementBadLoginAttempts(user.foreign.map(_.provider).getOrElse(Constant.HostName), usernameFromGui)
S.error(S.?(ErrorMessages.UnexpectedErrorDuringLogin)) // Note we hit this if user has not clicked email validation link
}

View File

@ -208,7 +208,7 @@ class ConsumerRegistration extends MdcLoggable {
"#post-consumer-registration-more-info-link a *" #> registrationMoreInfoText &
"#post-consumer-registration-more-info-link a [href]" #> registrationMoreInfoUrl & {
if(HydraUtil.integrateWithHydra) {
"#hydra-client-info-title *" #>"OAuth2" &
"#hydra-client-info-title *" #>"OAuth2: " &
"#admin_url *" #> HydraUtil.hydraAdminUrl &
"#client_id *" #> {consumer.key.get} &
"#redirect_uri *" #> consumer.redirectURL.get &

View File

@ -172,7 +172,9 @@ Berlin 13359, Germany
</div>
<br>
<p>Please save it in a secure location.</p>
<div style="cursor:pointer;text-align: right;" title="">
<div class="fa-solid fa-copy" onclick="copyConsumerRegistrationResultToClipboard(this)" id="register-consumer-success-copy-icon" title=""></div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-4">Consumer ID: </div>
<div class="col-xs-12 col-sm-8"><span id="app-consumer_id">123</span></div>

File diff suppressed because one or more lines are too long

View File

@ -394,3 +394,44 @@ $(document).ready(function() {
showIndicatorCookiePage('cookies-consent');
});
// This function copies the JSON result at an API Explorer endpoint to a clipboard
// when we press a copy icon in top left corner.
// In case that action is successful the icon is changed for a 2 seconds in order to notify a user about it.
function copyConsumerRegistrationResultToClipboard(element) {
var id = String(element.id).replace('register-consumer-success-copy-icon','register-consumer-success');
var r = document.createRange();
r.selectNode(document.getElementById(id));
window.getSelection().removeAllRanges();
window.getSelection().addRange(r);
let copiedText = window.getSelection().toString()
navigator.clipboard.writeText(copiedText.replace(/:\n/g, ": ")); // replace ": + new line" with ": + space"
window.getSelection().removeAllRanges();
// Store original values
var titleText = document.getElementById(element.id).title;
var iconClass = document.getElementById(element.id).className;
// and then change hey
document.getElementById(element.id).title = "";
document.getElementById(element.id).className = "fa-regular fa-copy";
// Below code is GUI related i.e. to notify a user that text is copied to clipboard
// --------------------------------------------------------------------------------
// It delays the call by ms milliseconds
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
// Function which revert icon and text to the initial state.
function revertTextAndClass(titleText, iconClass) {
document.getElementById(element.id).title = titleText;
document.getElementById(element.id).className = iconClass
}
var revertTextAndClassDeferred = defer(revertTextAndClass, 2000);
// Revert the original values of text and icon after 2 seconds
revertTextAndClassDeferred(titleText, iconClass);
}

View File

@ -44,7 +44,8 @@ Berlin 13359, Germany
<link href="/media/css/bootstrap-datetimepicker.min.css" rel="stylesheet">
<link id="main_style_sheet" data-lift="WebUI.mainStyleSheet" href="/media/css/website.css?201707241207" rel="stylesheet" type="text/css" />
<link id="override_style_sheet" data-lift="WebUI.overrideStyleSheet" href="" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="/font-awesome/css/all.min.css">
<script src="/media/js/jquery.min.js" type="text/javascript"></script>
<script src="/media/js/bootstrap.min.js" type="text/javascript"></script>
<script src="/media/js/select2.min.js"></script>

View File

@ -22,6 +22,7 @@ class SystemIntegrityTest extends V510ServerSetup {
object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.customViewNamesCheck))
object ApiEndpoint2 extends Tag(nameOf(Implementations5_1_0.systemViewNamesCheck))
object ApiEndpoint3 extends Tag(nameOf(Implementations5_1_0.accountAccessUniqueIndexCheck))
object ApiEndpoint4 extends Tag(nameOf(Implementations5_1_0.accountCurrencyCheck))
feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
@ -128,5 +129,41 @@ class SystemIntegrityTest extends V510ServerSetup {
response510.body.extract[CheckSystemIntegrityJsonV510]
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When("We make a request v5.1.0")
val request510 = (v5_1_0_Request / "management" / "system" / "integrity" / "account-currency-check").GET
val response510 = makeGetRequest(request510)
Then("We should get a 401")
response510.code should equal(401)
response510.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint with user credentials but without a proper entitlement", ApiEndpoint1, VersionOfApi) {
When("We make a request v5.1.0")
val request510 = (v5_1_0_Request / "management" / "system" / "integrity" / "account-currency-check").GET <@(user1)
val response510 = makeGetRequest(request510)
Then("error should be " + UserHasMissingRoles + CanGetSystemIntegrity)
response510.code should equal(403)
response510.body.extract[ErrorMessage].message should be (UserHasMissingRoles + CanGetSystemIntegrity)
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint with user credentials and a proper entitlement", ApiEndpoint1, VersionOfApi) {
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetSystemIntegrity.toString)
When("We make a request v5.1.0")
val request510 = (v5_1_0_Request / "management" / "system" / "integrity" / "account-currency-check").GET <@(user1)
val response510 = makeGetRequest(request510)
Then("We get successful response")
response510.code should equal(200)
response510.body.extract[CheckSystemIntegrityJsonV510]
}
}
}